summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Robinson <pbrobinson@gmail.com>2017-09-19 16:13:24 +0100
committerPeter Robinson <pbrobinson@gmail.com>2017-09-19 16:13:24 +0100
commit91207d805fb3a3008fd88974c3ec0f586b9eaa48 (patch)
tree4f653fba07f80711e0443585777d5eb72f623c1e
parent906bfcb85e0045a2ac4eb476d945cd427f640aa7 (diff)
downloadkernel-91207d805fb3a3008fd88974c3ec0f586b9eaa48.tar.gz
kernel-91207d805fb3a3008fd88974c3ec0f586b9eaa48.tar.xz
kernel-91207d805fb3a3008fd88974c3ec0f586b9eaa48.zip
stabilisation fixes for the RPi on 4.13
-rw-r--r--bcm283x-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-constructed-BO..patch42
-rw-r--r--bcm283x-vc4-fixes.patch1803
-rw-r--r--kernel.spec3
3 files changed, 1804 insertions, 44 deletions
diff --git a/bcm283x-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-constructed-BO..patch b/bcm283x-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-constructed-BO..patch
deleted file mode 100644
index 70a528253..000000000
--- a/bcm283x-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-constructed-BO..patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From patchwork Thu Feb 9 18:16:00 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: drm/vc4: Fix OOPSes from trying to cache a partially constructed BO.
-From: Eric Anholt <eric@anholt.net>
-X-Patchwork-Id: 138087
-Message-Id: <20170209181600.24048-1-eric@anholt.net>
-To: dri-devel@lists.freedesktop.org
-Cc: linux-kernel@vger.kernel.org, pbrobinson@gmail.com
-Date: Thu, 9 Feb 2017 10:16:00 -0800
-
-If a CMA allocation failed, the partially constructed BO would be
-unreferenced through the normal path, and we might choose to put it in
-the BO cache. If we then reused it before it expired from the cache,
-the kernel would OOPS.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Fixes: c826a6e10644 ("drm/vc4: Add a BO cache.")
----
- drivers/gpu/drm/vc4/vc4_bo.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
-index 5ec14f25625d..fd83a2807656 100644
---- a/drivers/gpu/drm/vc4/vc4_bo.c
-+++ b/drivers/gpu/drm/vc4/vc4_bo.c
-@@ -314,6 +314,14 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
- goto out;
- }
-
-+ /* If this object was partially constructed but CMA allocation
-+ * had failed, just free it.
-+ */
-+ if (!bo->base.vaddr) {
-+ vc4_bo_destroy(bo);
-+ goto out;
-+ }
-+
- cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size);
- if (!cache_list) {
- vc4_bo_destroy(bo);
diff --git a/bcm283x-vc4-fixes.patch b/bcm283x-vc4-fixes.patch
new file mode 100644
index 000000000..d17ff1873
--- /dev/null
+++ b/bcm283x-vc4-fixes.patch
@@ -0,0 +1,1803 @@
+From d74617cb4aebe5a4cb3eeda3070053ccfc36a0ae Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 25 Jul 2017 09:27:32 -0700
+Subject: [PATCH 1/6] drm/vc4: Demote user-accessible DRM_ERROR paths to
+ DRM_DEBUG.
+
+Userspace shouldn't be able to spam dmesg by passing bad arguments.
+This has particularly become an issues since we started using a bad
+argument to set_tiling to detect if set_tiling was supported.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Fixes: 83753117f1de ("drm/vc4: Add get/set tiling ioctls.")
+Link: https://patchwork.freedesktop.org/patch/msgid/20170725162733.28007-1-eric@anholt.net
+Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+---
+ drivers/gpu/drm/vc4/vc4_bo.c | 14 +++---
+ drivers/gpu/drm/vc4/vc4_gem.c | 10 ++--
+ drivers/gpu/drm/vc4/vc4_kms.c | 2 +-
+ drivers/gpu/drm/vc4/vc4_render_cl.c | 40 +++++++--------
+ drivers/gpu/drm/vc4/vc4_validate.c | 78 +++++++++++++++---------------
+ drivers/gpu/drm/vc4/vc4_validate_shaders.c | 72 +++++++++++++--------------
+ 6 files changed, 108 insertions(+), 108 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
+index 487f96412d35..ede80199001d 100644
+--- a/drivers/gpu/drm/vc4/vc4_bo.c
++++ b/drivers/gpu/drm/vc4/vc4_bo.c
+@@ -389,7 +389,7 @@ vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags)
+ struct vc4_bo *bo = to_vc4_bo(obj);
+
+ if (bo->validated_shader) {
+- DRM_ERROR("Attempting to export shader BO\n");
++ DRM_DEBUG("Attempting to export shader BO\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+@@ -410,7 +410,7 @@ int vc4_mmap(struct file *filp, struct vm_area_struct *vma)
+ bo = to_vc4_bo(gem_obj);
+
+ if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
+- DRM_ERROR("mmaping of shader BOs for writing not allowed.\n");
++ DRM_DEBUG("mmaping of shader BOs for writing not allowed.\n");
+ return -EINVAL;
+ }
+
+@@ -435,7 +435,7 @@ int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+ struct vc4_bo *bo = to_vc4_bo(obj);
+
+ if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
+- DRM_ERROR("mmaping of shader BOs for writing not allowed.\n");
++ DRM_DEBUG("mmaping of shader BOs for writing not allowed.\n");
+ return -EINVAL;
+ }
+
+@@ -447,7 +447,7 @@ void *vc4_prime_vmap(struct drm_gem_object *obj)
+ struct vc4_bo *bo = to_vc4_bo(obj);
+
+ if (bo->validated_shader) {
+- DRM_ERROR("mmaping of shader BOs not allowed.\n");
++ DRM_DEBUG("mmaping of shader BOs not allowed.\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+@@ -501,7 +501,7 @@ int vc4_mmap_bo_ioctl(struct drm_device *dev, void *data,
+
+ gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+ if (!gem_obj) {
+- DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
++ DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
+ return -EINVAL;
+ }
+
+@@ -605,7 +605,7 @@ int vc4_set_tiling_ioctl(struct drm_device *dev, void *data,
+
+ gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+ if (!gem_obj) {
+- DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
++ DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
+ return -ENOENT;
+ }
+ bo = to_vc4_bo(gem_obj);
+@@ -636,7 +636,7 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
+
+ gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+ if (!gem_obj) {
+- DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
++ DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
+ return -ENOENT;
+ }
+ bo = to_vc4_bo(gem_obj);
+diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
+index d5b821ad06af..a3e45e67f417 100644
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -659,7 +659,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
+ /* See comment on bo_index for why we have to check
+ * this.
+ */
+- DRM_ERROR("Rendering requires BOs to validate\n");
++ DRM_DEBUG("Rendering requires BOs to validate\n");
+ return -EINVAL;
+ }
+
+@@ -691,7 +691,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
+ struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
+ handles[i]);
+ if (!bo) {
+- DRM_ERROR("Failed to look up GEM BO %d: %d\n",
++ DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
+ i, handles[i]);
+ ret = -EINVAL;
+ spin_unlock(&file_priv->table_lock);
+@@ -729,7 +729,7 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
+ args->shader_rec_count >= (UINT_MAX /
+ sizeof(struct vc4_shader_state)) ||
+ temp_size < exec_size) {
+- DRM_ERROR("overflow in exec arguments\n");
++ DRM_DEBUG("overflow in exec arguments\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+@@ -974,7 +974,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
+
+ gem_obj = drm_gem_object_lookup(file_priv, args->handle);
+ if (!gem_obj) {
+- DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
++ DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
+ return -EINVAL;
+ }
+ bo = to_vc4_bo(gem_obj);
+@@ -1009,7 +1009,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
+ int ret = 0;
+
+ if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
+- DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
++ DRM_DEBUG("Unknown flags: 0x%02x\n", args->flags);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
+index bc6ecdc6f104..b2c55eb09ca3 100644
+--- a/drivers/gpu/drm/vc4/vc4_kms.c
++++ b/drivers/gpu/drm/vc4/vc4_kms.c
+@@ -204,7 +204,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
+ gem_obj = drm_gem_object_lookup(file_priv,
+ mode_cmd->handles[0]);
+ if (!gem_obj) {
+- DRM_ERROR("Failed to look up GEM BO %d\n",
++ DRM_DEBUG("Failed to look up GEM BO %d\n",
+ mode_cmd->handles[0]);
+ return ERR_PTR(-ENOENT);
+ }
+diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c
+index 5dc19429d4ae..da3bfd53f0bd 100644
+--- a/drivers/gpu/drm/vc4/vc4_render_cl.c
++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c
+@@ -378,14 +378,14 @@ static int vc4_full_res_bounds_check(struct vc4_exec_info *exec,
+ u32 render_tiles_stride = DIV_ROUND_UP(exec->args->width, 32);
+
+ if (surf->offset > obj->base.size) {
+- DRM_ERROR("surface offset %d > BO size %zd\n",
++ DRM_DEBUG("surface offset %d > BO size %zd\n",
+ surf->offset, obj->base.size);
+ return -EINVAL;
+ }
+
+ if ((obj->base.size - surf->offset) / VC4_TILE_BUFFER_SIZE <
+ render_tiles_stride * args->max_y_tile + args->max_x_tile) {
+- DRM_ERROR("MSAA tile %d, %d out of bounds "
++ DRM_DEBUG("MSAA tile %d, %d out of bounds "
+ "(bo size %zd, offset %d).\n",
+ args->max_x_tile, args->max_y_tile,
+ obj->base.size,
+@@ -401,7 +401,7 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec,
+ struct drm_vc4_submit_rcl_surface *surf)
+ {
+ if (surf->flags != 0 || surf->bits != 0) {
+- DRM_ERROR("MSAA surface had nonzero flags/bits\n");
++ DRM_DEBUG("MSAA surface had nonzero flags/bits\n");
+ return -EINVAL;
+ }
+
+@@ -415,7 +415,7 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec,
+ exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj;
+
+ if (surf->offset & 0xf) {
+- DRM_ERROR("MSAA write must be 16b aligned.\n");
++ DRM_DEBUG("MSAA write must be 16b aligned.\n");
+ return -EINVAL;
+ }
+
+@@ -437,7 +437,7 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
+ int ret;
+
+ if (surf->flags & ~VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
+- DRM_ERROR("Extra flags set\n");
++ DRM_DEBUG("Extra flags set\n");
+ return -EINVAL;
+ }
+
+@@ -453,12 +453,12 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
+
+ if (surf->flags & VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) {
+ if (surf == &exec->args->zs_write) {
+- DRM_ERROR("general zs write may not be a full-res.\n");
++ DRM_DEBUG("general zs write may not be a full-res.\n");
+ return -EINVAL;
+ }
+
+ if (surf->bits != 0) {
+- DRM_ERROR("load/store general bits set with "
++ DRM_DEBUG("load/store general bits set with "
+ "full res load/store.\n");
+ return -EINVAL;
+ }
+@@ -473,19 +473,19 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
+ if (surf->bits & ~(VC4_LOADSTORE_TILE_BUFFER_TILING_MASK |
+ VC4_LOADSTORE_TILE_BUFFER_BUFFER_MASK |
+ VC4_LOADSTORE_TILE_BUFFER_FORMAT_MASK)) {
+- DRM_ERROR("Unknown bits in load/store: 0x%04x\n",
++ DRM_DEBUG("Unknown bits in load/store: 0x%04x\n",
+ surf->bits);
+ return -EINVAL;
+ }
+
+ if (tiling > VC4_TILING_FORMAT_LT) {
+- DRM_ERROR("Bad tiling format\n");
++ DRM_DEBUG("Bad tiling format\n");
+ return -EINVAL;
+ }
+
+ if (buffer == VC4_LOADSTORE_TILE_BUFFER_ZS) {
+ if (format != 0) {
+- DRM_ERROR("No color format should be set for ZS\n");
++ DRM_DEBUG("No color format should be set for ZS\n");
+ return -EINVAL;
+ }
+ cpp = 4;
+@@ -499,16 +499,16 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
+ cpp = 4;
+ break;
+ default:
+- DRM_ERROR("Bad tile buffer format\n");
++ DRM_DEBUG("Bad tile buffer format\n");
+ return -EINVAL;
+ }
+ } else {
+- DRM_ERROR("Bad load/store buffer %d.\n", buffer);
++ DRM_DEBUG("Bad load/store buffer %d.\n", buffer);
+ return -EINVAL;
+ }
+
+ if (surf->offset & 0xf) {
+- DRM_ERROR("load/store buffer must be 16b aligned.\n");
++ DRM_DEBUG("load/store buffer must be 16b aligned.\n");
+ return -EINVAL;
+ }
+
+@@ -533,7 +533,7 @@ vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
+ int cpp;
+
+ if (surf->flags != 0) {
+- DRM_ERROR("No flags supported on render config.\n");
++ DRM_DEBUG("No flags supported on render config.\n");
+ return -EINVAL;
+ }
+
+@@ -541,7 +541,7 @@ vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
+ VC4_RENDER_CONFIG_FORMAT_MASK |
+ VC4_RENDER_CONFIG_MS_MODE_4X |
+ VC4_RENDER_CONFIG_DECIMATE_MODE_4X)) {
+- DRM_ERROR("Unknown bits in render config: 0x%04x\n",
++ DRM_DEBUG("Unknown bits in render config: 0x%04x\n",
+ surf->bits);
+ return -EINVAL;
+ }
+@@ -556,7 +556,7 @@ vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
+ exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj;
+
+ if (tiling > VC4_TILING_FORMAT_LT) {
+- DRM_ERROR("Bad tiling format\n");
++ DRM_DEBUG("Bad tiling format\n");
+ return -EINVAL;
+ }
+
+@@ -569,7 +569,7 @@ vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
+ cpp = 4;
+ break;
+ default:
+- DRM_ERROR("Bad tile buffer format\n");
++ DRM_DEBUG("Bad tile buffer format\n");
+ return -EINVAL;
+ }
+
+@@ -590,7 +590,7 @@ int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec)
+
+ if (args->min_x_tile > args->max_x_tile ||
+ args->min_y_tile > args->max_y_tile) {
+- DRM_ERROR("Bad render tile set (%d,%d)-(%d,%d)\n",
++ DRM_DEBUG("Bad render tile set (%d,%d)-(%d,%d)\n",
+ args->min_x_tile, args->min_y_tile,
+ args->max_x_tile, args->max_y_tile);
+ return -EINVAL;
+@@ -599,7 +599,7 @@ int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec)
+ if (has_bin &&
+ (args->max_x_tile > exec->bin_tiles_x ||
+ args->max_y_tile > exec->bin_tiles_y)) {
+- DRM_ERROR("Render tiles (%d,%d) outside of bin config "
++ DRM_DEBUG("Render tiles (%d,%d) outside of bin config "
+ "(%d,%d)\n",
+ args->max_x_tile, args->max_y_tile,
+ exec->bin_tiles_x, exec->bin_tiles_y);
+@@ -642,7 +642,7 @@ int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec)
+ */
+ if (!setup.color_write && !setup.zs_write &&
+ !setup.msaa_color_write && !setup.msaa_zs_write) {
+- DRM_ERROR("RCL requires color or Z/S write\n");
++ DRM_DEBUG("RCL requires color or Z/S write\n");
+ return -EINVAL;
+ }
+
+diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c
+index 814b512c6b9a..2db485abb186 100644
+--- a/drivers/gpu/drm/vc4/vc4_validate.c
++++ b/drivers/gpu/drm/vc4/vc4_validate.c
+@@ -109,7 +109,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex)
+ struct vc4_bo *bo;
+
+ if (hindex >= exec->bo_count) {
+- DRM_ERROR("BO index %d greater than BO count %d\n",
++ DRM_DEBUG("BO index %d greater than BO count %d\n",
+ hindex, exec->bo_count);
+ return NULL;
+ }
+@@ -117,7 +117,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex)
+ bo = to_vc4_bo(&obj->base);
+
+ if (bo->validated_shader) {
+- DRM_ERROR("Trying to use shader BO as something other than "
++ DRM_DEBUG("Trying to use shader BO as something other than "
+ "a shader\n");
+ return NULL;
+ }
+@@ -172,7 +172,7 @@ vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
+ * our math.
+ */
+ if (width > 4096 || height > 4096) {
+- DRM_ERROR("Surface dimensions (%d,%d) too large",
++ DRM_DEBUG("Surface dimensions (%d,%d) too large",
+ width, height);
+ return false;
+ }
+@@ -191,7 +191,7 @@ vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
+ aligned_height = round_up(height, utile_h);
+ break;
+ default:
+- DRM_ERROR("buffer tiling %d unsupported\n", tiling_format);
++ DRM_DEBUG("buffer tiling %d unsupported\n", tiling_format);
+ return false;
+ }
+
+@@ -200,7 +200,7 @@ vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
+
+ if (size + offset < size ||
+ size + offset > fbo->base.size) {
+- DRM_ERROR("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %zd)\n",
++ DRM_DEBUG("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %zd)\n",
+ width, height,
+ aligned_width, aligned_height,
+ size, offset, fbo->base.size);
+@@ -214,7 +214,7 @@ static int
+ validate_flush(VALIDATE_ARGS)
+ {
+ if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 1)) {
+- DRM_ERROR("Bin CL must end with VC4_PACKET_FLUSH\n");
++ DRM_DEBUG("Bin CL must end with VC4_PACKET_FLUSH\n");
+ return -EINVAL;
+ }
+ exec->found_flush = true;
+@@ -226,13 +226,13 @@ static int
+ validate_start_tile_binning(VALIDATE_ARGS)
+ {
+ if (exec->found_start_tile_binning_packet) {
+- DRM_ERROR("Duplicate VC4_PACKET_START_TILE_BINNING\n");
++ DRM_DEBUG("Duplicate VC4_PACKET_START_TILE_BINNING\n");
+ return -EINVAL;
+ }
+ exec->found_start_tile_binning_packet = true;
+
+ if (!exec->found_tile_binning_mode_config_packet) {
+- DRM_ERROR("missing VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
++ DRM_DEBUG("missing VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
+ return -EINVAL;
+ }
+
+@@ -243,7 +243,7 @@ static int
+ validate_increment_semaphore(VALIDATE_ARGS)
+ {
+ if (!validate_bin_pos(exec, untrusted, exec->args->bin_cl_size - 2)) {
+- DRM_ERROR("Bin CL must end with "
++ DRM_DEBUG("Bin CL must end with "
+ "VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+@@ -264,7 +264,7 @@ validate_indexed_prim_list(VALIDATE_ARGS)
+
+ /* Check overflow condition */
+ if (exec->shader_state_count == 0) {
+- DRM_ERROR("shader state must precede primitives\n");
++ DRM_DEBUG("shader state must precede primitives\n");
+ return -EINVAL;
+ }
+ shader_state = &exec->shader_state[exec->shader_state_count - 1];
+@@ -281,7 +281,7 @@ validate_indexed_prim_list(VALIDATE_ARGS)
+
+ if (offset > ib->base.size ||
+ (ib->base.size - offset) / index_size < length) {
+- DRM_ERROR("IB access overflow (%d + %d*%d > %zd)\n",
++ DRM_DEBUG("IB access overflow (%d + %d*%d > %zd)\n",
+ offset, length, index_size, ib->base.size);
+ return -EINVAL;
+ }
+@@ -301,13 +301,13 @@ validate_gl_array_primitive(VALIDATE_ARGS)
+
+ /* Check overflow condition */
+ if (exec->shader_state_count == 0) {
+- DRM_ERROR("shader state must precede primitives\n");
++ DRM_DEBUG("shader state must precede primitives\n");
+ return -EINVAL;
+ }
+ shader_state = &exec->shader_state[exec->shader_state_count - 1];
+
+ if (length + base_index < length) {
+- DRM_ERROR("primitive vertex count overflow\n");
++ DRM_DEBUG("primitive vertex count overflow\n");
+ return -EINVAL;
+ }
+ max_index = length + base_index - 1;
+@@ -324,7 +324,7 @@ validate_gl_shader_state(VALIDATE_ARGS)
+ uint32_t i = exec->shader_state_count++;
+
+ if (i >= exec->shader_state_size) {
+- DRM_ERROR("More requests for shader states than declared\n");
++ DRM_DEBUG("More requests for shader states than declared\n");
+ return -EINVAL;
+ }
+
+@@ -332,7 +332,7 @@ validate_gl_shader_state(VALIDATE_ARGS)
+ exec->shader_state[i].max_index = 0;
+
+ if (exec->shader_state[i].addr & ~0xf) {
+- DRM_ERROR("high bits set in GL shader rec reference\n");
++ DRM_DEBUG("high bits set in GL shader rec reference\n");
+ return -EINVAL;
+ }
+
+@@ -356,7 +356,7 @@ validate_tile_binning_config(VALIDATE_ARGS)
+ int bin_slot;
+
+ if (exec->found_tile_binning_mode_config_packet) {
+- DRM_ERROR("Duplicate VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
++ DRM_DEBUG("Duplicate VC4_PACKET_TILE_BINNING_MODE_CONFIG\n");
+ return -EINVAL;
+ }
+ exec->found_tile_binning_mode_config_packet = true;
+@@ -368,14 +368,14 @@ validate_tile_binning_config(VALIDATE_ARGS)
+
+ if (exec->bin_tiles_x == 0 ||
+ exec->bin_tiles_y == 0) {
+- DRM_ERROR("Tile binning config of %dx%d too small\n",
++ DRM_DEBUG("Tile binning config of %dx%d too small\n",
+ exec->bin_tiles_x, exec->bin_tiles_y);
+ return -EINVAL;
+ }
+
+ if (flags & (VC4_BIN_CONFIG_DB_NON_MS |
+ VC4_BIN_CONFIG_TILE_BUFFER_64BIT)) {
+- DRM_ERROR("unsupported binning config flags 0x%02x\n", flags);
++ DRM_DEBUG("unsupported binning config flags 0x%02x\n", flags);
+ return -EINVAL;
+ }
+
+@@ -493,20 +493,20 @@ vc4_validate_bin_cl(struct drm_device *dev,
+ const struct cmd_info *info;
+
+ if (cmd >= ARRAY_SIZE(cmd_info)) {
+- DRM_ERROR("0x%08x: packet %d out of bounds\n",
++ DRM_DEBUG("0x%08x: packet %d out of bounds\n",
+ src_offset, cmd);
+ return -EINVAL;
+ }
+
+ info = &cmd_info[cmd];
+ if (!info->name) {
+- DRM_ERROR("0x%08x: packet %d invalid\n",
++ DRM_DEBUG("0x%08x: packet %d invalid\n",
+ src_offset, cmd);
+ return -EINVAL;
+ }
+
+ if (src_offset + info->len > len) {
+- DRM_ERROR("0x%08x: packet %d (%s) length 0x%08x "
++ DRM_DEBUG("0x%08x: packet %d (%s) length 0x%08x "
+ "exceeds bounds (0x%08x)\n",
+ src_offset, cmd, info->name, info->len,
+ src_offset + len);
+@@ -519,7 +519,7 @@ vc4_validate_bin_cl(struct drm_device *dev,
+ if (info->func && info->func(exec,
+ dst_pkt + 1,
+ src_pkt + 1)) {
+- DRM_ERROR("0x%08x: packet %d (%s) failed to validate\n",
++ DRM_DEBUG("0x%08x: packet %d (%s) failed to validate\n",
+ src_offset, cmd, info->name);
+ return -EINVAL;
+ }
+@@ -537,7 +537,7 @@ vc4_validate_bin_cl(struct drm_device *dev,
+ exec->ct0ea = exec->ct0ca + dst_offset;
+
+ if (!exec->found_start_tile_binning_packet) {
+- DRM_ERROR("Bin CL missing VC4_PACKET_START_TILE_BINNING\n");
++ DRM_DEBUG("Bin CL missing VC4_PACKET_START_TILE_BINNING\n");
+ return -EINVAL;
+ }
+
+@@ -549,7 +549,7 @@ vc4_validate_bin_cl(struct drm_device *dev,
+ * semaphore increment.
+ */
+ if (!exec->found_increment_semaphore_packet || !exec->found_flush) {
+- DRM_ERROR("Bin CL missing VC4_PACKET_INCREMENT_SEMAPHORE + "
++ DRM_DEBUG("Bin CL missing VC4_PACKET_INCREMENT_SEMAPHORE + "
+ "VC4_PACKET_FLUSH\n");
+ return -EINVAL;
+ }
+@@ -588,11 +588,11 @@ reloc_tex(struct vc4_exec_info *exec,
+ uint32_t remaining_size = tex->base.size - p0;
+
+ if (p0 > tex->base.size - 4) {
+- DRM_ERROR("UBO offset greater than UBO size\n");
++ DRM_DEBUG("UBO offset greater than UBO size\n");
+ goto fail;
+ }
+ if (p1 > remaining_size - 4) {
+- DRM_ERROR("UBO clamp would allow reads "
++ DRM_DEBUG("UBO clamp would allow reads "
+ "outside of UBO\n");
+ goto fail;
+ }
+@@ -612,14 +612,14 @@ reloc_tex(struct vc4_exec_info *exec,
+ if (VC4_GET_FIELD(p3, VC4_TEX_P2_PTYPE) ==
+ VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE) {
+ if (cube_map_stride) {
+- DRM_ERROR("Cube map stride set twice\n");
++ DRM_DEBUG("Cube map stride set twice\n");
+ goto fail;
+ }
+
+ cube_map_stride = p3 & VC4_TEX_P2_CMST_MASK;
+ }
+ if (!cube_map_stride) {
+- DRM_ERROR("Cube map stride not set\n");
++ DRM_DEBUG("Cube map stride not set\n");
+ goto fail;
+ }
+ }
+@@ -660,7 +660,7 @@ reloc_tex(struct vc4_exec_info *exec,
+ case VC4_TEXTURE_TYPE_RGBA64:
+ case VC4_TEXTURE_TYPE_YUV422R:
+ default:
+- DRM_ERROR("Texture format %d unsupported\n", type);
++ DRM_DEBUG("Texture format %d unsupported\n", type);
+ goto fail;
+ }
+ utile_w = utile_width(cpp);
+@@ -713,7 +713,7 @@ reloc_tex(struct vc4_exec_info *exec,
+ level_size = aligned_width * cpp * aligned_height;
+
+ if (offset < level_size) {
+- DRM_ERROR("Level %d (%dx%d -> %dx%d) size %db "
++ DRM_DEBUG("Level %d (%dx%d -> %dx%d) size %db "
+ "overflowed buffer bounds (offset %d)\n",
+ i, level_width, level_height,
+ aligned_width, aligned_height,
+@@ -764,7 +764,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+
+ nr_relocs = ARRAY_SIZE(shader_reloc_offsets) + nr_attributes;
+ if (nr_relocs * 4 > exec->shader_rec_size) {
+- DRM_ERROR("overflowed shader recs reading %d handles "
++ DRM_DEBUG("overflowed shader recs reading %d handles "
+ "from %d bytes left\n",
+ nr_relocs, exec->shader_rec_size);
+ return -EINVAL;
+@@ -774,7 +774,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+ exec->shader_rec_size -= nr_relocs * 4;
+
+ if (packet_size > exec->shader_rec_size) {
+- DRM_ERROR("overflowed shader recs copying %db packet "
++ DRM_DEBUG("overflowed shader recs copying %db packet "
+ "from %d bytes left\n",
+ packet_size, exec->shader_rec_size);
+ return -EINVAL;
+@@ -794,7 +794,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+
+ for (i = 0; i < shader_reloc_count; i++) {
+ if (src_handles[i] > exec->bo_count) {
+- DRM_ERROR("Shader handle %d too big\n", src_handles[i]);
++ DRM_DEBUG("Shader handle %d too big\n", src_handles[i]);
+ return -EINVAL;
+ }
+
+@@ -810,13 +810,13 @@ validate_gl_shader_rec(struct drm_device *dev,
+
+ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) !=
+ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) {
+- DRM_ERROR("Thread mode of CL and FS do not match\n");
++ DRM_DEBUG("Thread mode of CL and FS do not match\n");
+ return -EINVAL;
+ }
+
+ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded ||
+ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) {
+- DRM_ERROR("cs and vs cannot be threaded\n");
++ DRM_DEBUG("cs and vs cannot be threaded\n");
+ return -EINVAL;
+ }
+
+@@ -831,7 +831,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+ *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
+
+ if (src_offset != 0) {
+- DRM_ERROR("Shaders must be at offset 0 of "
++ DRM_DEBUG("Shaders must be at offset 0 of "
+ "the BO.\n");
+ return -EINVAL;
+ }
+@@ -842,7 +842,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+
+ if (validated_shader->uniforms_src_size >
+ exec->uniforms_size) {
+- DRM_ERROR("Uniforms src buffer overflow\n");
++ DRM_DEBUG("Uniforms src buffer overflow\n");
+ return -EINVAL;
+ }
+
+@@ -900,7 +900,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+
+ if (vbo->base.size < offset ||
+ vbo->base.size - offset < attr_size) {
+- DRM_ERROR("BO offset overflow (%d + %d > %zu)\n",
++ DRM_DEBUG("BO offset overflow (%d + %d > %zu)\n",
+ offset, attr_size, vbo->base.size);
+ return -EINVAL;
+ }
+@@ -909,7 +909,7 @@ validate_gl_shader_rec(struct drm_device *dev,
+ max_index = ((vbo->base.size - offset - attr_size) /
+ stride);
+ if (state->max_index > max_index) {
+- DRM_ERROR("primitives use index %d out of "
++ DRM_DEBUG("primitives use index %d out of "
+ "supplied %d\n",
+ state->max_index, max_index);
+ return -EINVAL;
+diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
+index 0b2df5c6efb4..d3f15bf60900 100644
+--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c
++++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
+@@ -200,7 +200,7 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+ uint32_t clamp_reg, clamp_offset;
+
+ if (sig == QPU_SIG_SMALL_IMM) {
+- DRM_ERROR("direct TMU read used small immediate\n");
++ DRM_DEBUG("direct TMU read used small immediate\n");
+ return false;
+ }
+
+@@ -209,7 +209,7 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+ */
+ if (is_mul ||
+ QPU_GET_FIELD(inst, QPU_OP_ADD) != QPU_A_ADD) {
+- DRM_ERROR("direct TMU load wasn't an add\n");
++ DRM_DEBUG("direct TMU load wasn't an add\n");
+ return false;
+ }
+
+@@ -220,13 +220,13 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+ */
+ clamp_reg = raddr_add_a_to_live_reg_index(inst);
+ if (clamp_reg == ~0) {
+- DRM_ERROR("direct TMU load wasn't clamped\n");
++ DRM_DEBUG("direct TMU load wasn't clamped\n");
+ return false;
+ }
+
+ clamp_offset = validation_state->live_min_clamp_offsets[clamp_reg];
+ if (clamp_offset == ~0) {
+- DRM_ERROR("direct TMU load wasn't clamped\n");
++ DRM_DEBUG("direct TMU load wasn't clamped\n");
+ return false;
+ }
+
+@@ -238,7 +238,7 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+
+ if (!(add_b == QPU_MUX_A && raddr_a == QPU_R_UNIF) &&
+ !(add_b == QPU_MUX_B && raddr_b == QPU_R_UNIF)) {
+- DRM_ERROR("direct TMU load didn't add to a uniform\n");
++ DRM_DEBUG("direct TMU load didn't add to a uniform\n");
+ return false;
+ }
+
+@@ -246,14 +246,14 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+ } else {
+ if (raddr_a == QPU_R_UNIF || (sig != QPU_SIG_SMALL_IMM &&
+ raddr_b == QPU_R_UNIF)) {
+- DRM_ERROR("uniform read in the same instruction as "
++ DRM_DEBUG("uniform read in the same instruction as "
+ "texture setup.\n");
+ return false;
+ }
+ }
+
+ if (validation_state->tmu_write_count[tmu] >= 4) {
+- DRM_ERROR("TMU%d got too many parameters before dispatch\n",
++ DRM_DEBUG("TMU%d got too many parameters before dispatch\n",
+ tmu);
+ return false;
+ }
+@@ -265,7 +265,7 @@ check_tmu_write(struct vc4_validated_shader_info *validated_shader,
+ */
+ if (!is_direct) {
+ if (validation_state->needs_uniform_address_update) {
+- DRM_ERROR("Texturing with undefined uniform address\n");
++ DRM_DEBUG("Texturing with undefined uniform address\n");
+ return false;
+ }
+
+@@ -336,35 +336,35 @@ validate_uniform_address_write(struct vc4_validated_shader_info *validated_shade
+ case QPU_SIG_LOAD_TMU1:
+ break;
+ default:
+- DRM_ERROR("uniforms address change must be "
++ DRM_DEBUG("uniforms address change must be "
+ "normal math\n");
+ return false;
+ }
+
+ if (is_mul || QPU_GET_FIELD(inst, QPU_OP_ADD) != QPU_A_ADD) {
+- DRM_ERROR("Uniform address reset must be an ADD.\n");
++ DRM_DEBUG("Uniform address reset must be an ADD.\n");
+ return false;
+ }
+
+ if (QPU_GET_FIELD(inst, QPU_COND_ADD) != QPU_COND_ALWAYS) {
+- DRM_ERROR("Uniform address reset must be unconditional.\n");
++ DRM_DEBUG("Uniform address reset must be unconditional.\n");
+ return false;
+ }
+
+ if (QPU_GET_FIELD(inst, QPU_PACK) != QPU_PACK_A_NOP &&
+ !(inst & QPU_PM)) {
+- DRM_ERROR("No packing allowed on uniforms reset\n");
++ DRM_DEBUG("No packing allowed on uniforms reset\n");
+ return false;
+ }
+
+ if (add_lri == -1) {
+- DRM_ERROR("First argument of uniform address write must be "
++ DRM_DEBUG("First argument of uniform address write must be "
+ "an immediate value.\n");
+ return false;
+ }
+
+ if (validation_state->live_immediates[add_lri] != expected_offset) {
+- DRM_ERROR("Resetting uniforms with offset %db instead of %db\n",
++ DRM_DEBUG("Resetting uniforms with offset %db instead of %db\n",
+ validation_state->live_immediates[add_lri],
+ expected_offset);
+ return false;
+@@ -372,7 +372,7 @@ validate_uniform_address_write(struct vc4_validated_shader_info *validated_shade
+
+ if (!(add_b == QPU_MUX_A && raddr_a == QPU_R_UNIF) &&
+ !(add_b == QPU_MUX_B && raddr_b == QPU_R_UNIF)) {
+- DRM_ERROR("Second argument of uniform address write must be "
++ DRM_DEBUG("Second argument of uniform address write must be "
+ "a uniform.\n");
+ return false;
+ }
+@@ -417,7 +417,7 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader,
+ switch (waddr) {
+ case QPU_W_UNIFORMS_ADDRESS:
+ if (is_b) {
+- DRM_ERROR("relative uniforms address change "
++ DRM_DEBUG("relative uniforms address change "
+ "unsupported\n");
+ return false;
+ }
+@@ -452,11 +452,11 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader,
+ /* XXX: I haven't thought about these, so don't support them
+ * for now.
+ */
+- DRM_ERROR("Unsupported waddr %d\n", waddr);
++ DRM_DEBUG("Unsupported waddr %d\n", waddr);
+ return false;
+
+ case QPU_W_VPM_ADDR:
+- DRM_ERROR("General VPM DMA unsupported\n");
++ DRM_DEBUG("General VPM DMA unsupported\n");
+ return false;
+
+ case QPU_W_VPM:
+@@ -559,7 +559,7 @@ check_instruction_writes(struct vc4_validated_shader_info *validated_shader,
+ bool ok;
+
+ if (is_tmu_write(waddr_add) && is_tmu_write(waddr_mul)) {
+- DRM_ERROR("ADD and MUL both set up textures\n");
++ DRM_DEBUG("ADD and MUL both set up textures\n");
+ return false;
+ }
+
+@@ -588,7 +588,7 @@ check_branch(uint64_t inst,
+ * there's no need for it.
+ */
+ if (waddr_add != QPU_W_NOP || waddr_mul != QPU_W_NOP) {
+- DRM_ERROR("branch instruction at %d wrote a register.\n",
++ DRM_DEBUG("branch instruction at %d wrote a register.\n",
+ validation_state->ip);
+ return false;
+ }
+@@ -614,7 +614,7 @@ check_instruction_reads(struct vc4_validated_shader_info *validated_shader,
+ validated_shader->uniforms_size += 4;
+
+ if (validation_state->needs_uniform_address_update) {
+- DRM_ERROR("Uniform read with undefined uniform "
++ DRM_DEBUG("Uniform read with undefined uniform "
+ "address\n");
+ return false;
+ }
+@@ -660,19 +660,19 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
+ continue;
+
+ if (ip - last_branch < 4) {
+- DRM_ERROR("Branch at %d during delay slots\n", ip);
++ DRM_DEBUG("Branch at %d during delay slots\n", ip);
+ return false;
+ }
+ last_branch = ip;
+
+ if (inst & QPU_BRANCH_REG) {
+- DRM_ERROR("branching from register relative "
++ DRM_DEBUG("branching from register relative "
+ "not supported\n");
+ return false;
+ }
+
+ if (!(inst & QPU_BRANCH_REL)) {
+- DRM_ERROR("relative branching required\n");
++ DRM_DEBUG("relative branching required\n");
+ return false;
+ }
+
+@@ -682,13 +682,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
+ * end of the shader object.
+ */
+ if (branch_imm % sizeof(inst) != 0) {
+- DRM_ERROR("branch target not aligned\n");
++ DRM_DEBUG("branch target not aligned\n");
+ return false;
+ }
+
+ branch_target_ip = after_delay_ip + (branch_imm >> 3);
+ if (branch_target_ip >= validation_state->max_ip) {
+- DRM_ERROR("Branch at %d outside of shader (ip %d/%d)\n",
++ DRM_DEBUG("Branch at %d outside of shader (ip %d/%d)\n",
+ ip, branch_target_ip,
+ validation_state->max_ip);
+ return false;
+@@ -699,7 +699,7 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
+ * the shader.
+ */
+ if (after_delay_ip >= validation_state->max_ip) {
+- DRM_ERROR("Branch at %d continues past shader end "
++ DRM_DEBUG("Branch at %d continues past shader end "
+ "(%d/%d)\n",
+ ip, after_delay_ip, validation_state->max_ip);
+ return false;
+@@ -709,7 +709,7 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
+ }
+
+ if (max_branch_target > validation_state->max_ip - 3) {
+- DRM_ERROR("Branch landed after QPU_SIG_PROG_END");
++ DRM_DEBUG("Branch landed after QPU_SIG_PROG_END");
+ return false;
+ }
+
+@@ -750,7 +750,7 @@ vc4_handle_branch_target(struct vc4_shader_validation_state *validation_state)
+ return true;
+
+ if (texturing_in_progress(validation_state)) {
+- DRM_ERROR("Branch target landed during TMU setup\n");
++ DRM_DEBUG("Branch target landed during TMU setup\n");
+ return false;
+ }
+
+@@ -837,7 +837,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ case QPU_SIG_LAST_THREAD_SWITCH:
+ if (!check_instruction_writes(validated_shader,
+ &validation_state)) {
+- DRM_ERROR("Bad write at ip %d\n", ip);
++ DRM_DEBUG("Bad write at ip %d\n", ip);
+ goto fail;
+ }
+
+@@ -855,7 +855,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ validated_shader->is_threaded = true;
+
+ if (ip < last_thread_switch_ip + 3) {
+- DRM_ERROR("Thread switch too soon after "
++ DRM_DEBUG("Thread switch too soon after "
+ "last switch at ip %d\n", ip);
+ goto fail;
+ }
+@@ -867,7 +867,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ case QPU_SIG_LOAD_IMM:
+ if (!check_instruction_writes(validated_shader,
+ &validation_state)) {
+- DRM_ERROR("Bad LOAD_IMM write at ip %d\n", ip);
++ DRM_DEBUG("Bad LOAD_IMM write at ip %d\n", ip);
+ goto fail;
+ }
+ break;
+@@ -878,14 +878,14 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ goto fail;
+
+ if (ip < last_thread_switch_ip + 3) {
+- DRM_ERROR("Branch in thread switch at ip %d",
++ DRM_DEBUG("Branch in thread switch at ip %d",
+ ip);
+ goto fail;
+ }
+
+ break;
+ default:
+- DRM_ERROR("Unsupported QPU signal %d at "
++ DRM_DEBUG("Unsupported QPU signal %d at "
+ "instruction %d\n", sig, ip);
+ goto fail;
+ }
+@@ -898,7 +898,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ }
+
+ if (ip == validation_state.max_ip) {
+- DRM_ERROR("shader failed to terminate before "
++ DRM_DEBUG("shader failed to terminate before "
+ "shader BO end at %zd\n",
+ shader_obj->base.size);
+ goto fail;
+@@ -907,7 +907,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+ /* Might corrupt other thread */
+ if (validated_shader->is_threaded &&
+ validation_state.all_registers_used) {
+- DRM_ERROR("Shader uses threading, but uses the upper "
++ DRM_DEBUG("Shader uses threading, but uses the upper "
+ "half of the registers, too\n");
+ goto fail;
+ }
+--
+2.13.5
+
+From 28b369f5abc790f56e668869d88f261ca7a27c55 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 8 Aug 2017 13:56:05 -0700
+Subject: [PATCH 2/6] drm/vc4: Fix leak of HDMI EDID
+
+We don't keep a pointer to it around anywhere, so it's our job to free
+it.
+
+Cc: Stefan Wahren <stefan.wahren@i2se.com>
+Link: https://github.com/anholt/linux/issues/101
+Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.")
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170808205605.4432-1-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index ed63d4e85762..f7803fd7f47c 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -260,6 +260,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+ drm_edid_to_eld(connector, edid);
++ kfree(edid);
+
+ return ret;
+ }
+--
+2.13.5
+
+From 3b688b6d347f777a8e86165decc33198b063b8c0 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 25 Jul 2017 11:27:16 -0700
+Subject: [PATCH 3/6] drm/vc4: Start using u64_to_user_ptr.
+
+Chris Wilson pointed out this little cleanup in a review of new code,
+so let's fix up the code I was copying from.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170725182718.31468-1-eric@anholt.net
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+---
+ drivers/gpu/drm/vc4/vc4_gem.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
+index a3e45e67f417..8b551bc630c4 100644
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -119,7 +119,7 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
+ bo_state[i].size = vc4_bo->base.base.size;
+ }
+
+- if (copy_to_user((void __user *)(uintptr_t)get_state->bo,
++ if (copy_to_user(u64_to_user_ptr(get_state->bo),
+ bo_state,
+ state->bo_count * sizeof(*bo_state)))
+ ret = -EFAULT;
+@@ -678,8 +678,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
+ goto fail;
+ }
+
+- if (copy_from_user(handles,
+- (void __user *)(uintptr_t)args->bo_handles,
++ if (copy_from_user(handles, u64_to_user_ptr(args->bo_handles),
+ exec->bo_count * sizeof(uint32_t))) {
+ ret = -EFAULT;
+ DRM_ERROR("Failed to copy in GEM handles\n");
+@@ -755,21 +754,21 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
+ exec->shader_state_size = args->shader_rec_count;
+
+ if (copy_from_user(bin,
+- (void __user *)(uintptr_t)args->bin_cl,
++ u64_to_user_ptr(args->bin_cl),
+ args->bin_cl_size)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ if (copy_from_user(exec->shader_rec_u,
+- (void __user *)(uintptr_t)args->shader_rec,
++ u64_to_user_ptr(args->shader_rec),
+ args->shader_rec_size)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ if (copy_from_user(exec->uniforms_u,
+- (void __user *)(uintptr_t)args->uniforms,
++ u64_to_user_ptr(args->uniforms),
+ args->uniforms_size)) {
+ ret = -EFAULT;
+ goto fail;
+--
+2.13.5
+
+From da81d76bce216c160d2924a52e362b160bbb6ca1 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Tue, 25 Jul 2017 11:27:17 -0700
+Subject: [PATCH 4/6] drm/vc4: Add an ioctl for labeling GEM BOs for summary
+ stats
+
+This has proven immensely useful for debugging memory leaks and
+overallocation (which is a rather serious concern on the platform,
+given that we typically run at about 256MB of CMA out of up to 1GB
+total memory, with framebuffers that are about 8MB ecah).
+
+The state of the art without this is to dump debug logs from every GL
+application, guess as to kernel allocations based on bo_stats, and try
+to merge that all together into a global picture of memory allocation
+state. With this, you can add a couple of calls to the debug build of
+the 3D driver and get a pretty detailed view of GPU memory usage from
+/debug/dri/0/bo_stats (or when we debug print to dmesg on allocation
+failure).
+
+The Mesa side currently labels at the gallium resource level (so you
+see that a 1920x20 pixmap has been created, presumably for the window
+system panel), but we could extend that to be even more useful with
+glObjectLabel() names being sent all the way down to the kernel.
+
+(partial) example of sorted debugfs output with Mesa labeling all
+resources:
+
+ kernel BO cache: 16392kb BOs (3)
+ tiling shadow 1920x1080: 8160kb BOs (1)
+ resource 1920x1080@32/0: 8160kb BOs (1)
+scanout resource 1920x1080@32/0: 8100kb BOs (1)
+ kernel: 8100kb BOs (1)
+
+v2: Use strndup_user(), use lockdep assertion instead of just a
+ comment, fix an array[-1] reference, extend comment about name
+ freeing.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170725182718.31468-2-eric@anholt.net
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+---
+ drivers/gpu/drm/vc4/vc4_bo.c | 258 ++++++++++++++++++++++++++++--------
+ drivers/gpu/drm/vc4/vc4_drv.c | 8 +-
+ drivers/gpu/drm/vc4/vc4_drv.h | 39 +++++-
+ drivers/gpu/drm/vc4/vc4_gem.c | 2 +-
+ drivers/gpu/drm/vc4/vc4_render_cl.c | 2 +-
+ drivers/gpu/drm/vc4/vc4_v3d.c | 3 +-
+ include/uapi/drm/vc4_drm.h | 11 ++
+ 7 files changed, 257 insertions(+), 66 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
+index ede80199001d..27c4a927311f 100644
+--- a/drivers/gpu/drm/vc4/vc4_bo.c
++++ b/drivers/gpu/drm/vc4/vc4_bo.c
+@@ -24,21 +24,35 @@
+ #include "vc4_drv.h"
+ #include "uapi/drm/vc4_drm.h"
+
++static const char * const bo_type_names[] = {
++ "kernel",
++ "V3D",
++ "V3D shader",
++ "dumb",
++ "binner",
++ "RCL",
++ "BCL",
++ "kernel BO cache",
++};
++
++static bool is_user_label(int label)
++{
++ return label >= VC4_BO_TYPE_COUNT;
++}
++
+ static void vc4_bo_stats_dump(struct vc4_dev *vc4)
+ {
+- DRM_INFO("num bos allocated: %d\n",
+- vc4->bo_stats.num_allocated);
+- DRM_INFO("size bos allocated: %dkb\n",
+- vc4->bo_stats.size_allocated / 1024);
+- DRM_INFO("num bos used: %d\n",
+- vc4->bo_stats.num_allocated - vc4->bo_stats.num_cached);
+- DRM_INFO("size bos used: %dkb\n",
+- (vc4->bo_stats.size_allocated -
+- vc4->bo_stats.size_cached) / 1024);
+- DRM_INFO("num bos cached: %d\n",
+- vc4->bo_stats.num_cached);
+- DRM_INFO("size bos cached: %dkb\n",
+- vc4->bo_stats.size_cached / 1024);
++ int i;
++
++ for (i = 0; i < vc4->num_labels; i++) {
++ if (!vc4->bo_labels[i].num_allocated)
++ continue;
++
++ DRM_INFO("%30s: %6dkb BOs (%d)\n",
++ vc4->bo_labels[i].name,
++ vc4->bo_labels[i].size_allocated / 1024,
++ vc4->bo_labels[i].num_allocated);
++ }
+ }
+
+ #ifdef CONFIG_DEBUG_FS
+@@ -47,30 +61,103 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *unused)
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+- struct vc4_bo_stats stats;
++ int i;
+
+- /* Take a snapshot of the current stats with the lock held. */
+ mutex_lock(&vc4->bo_lock);
+- stats = vc4->bo_stats;
++ for (i = 0; i < vc4->num_labels; i++) {
++ if (!vc4->bo_labels[i].num_allocated)
++ continue;
++
++ seq_printf(m, "%30s: %6dkb BOs (%d)\n",
++ vc4->bo_labels[i].name,
++ vc4->bo_labels[i].size_allocated / 1024,
++ vc4->bo_labels[i].num_allocated);
++ }
+ mutex_unlock(&vc4->bo_lock);
+
+- seq_printf(m, "num bos allocated: %d\n",
+- stats.num_allocated);
+- seq_printf(m, "size bos allocated: %dkb\n",
+- stats.size_allocated / 1024);
+- seq_printf(m, "num bos used: %d\n",
+- stats.num_allocated - stats.num_cached);
+- seq_printf(m, "size bos used: %dkb\n",
+- (stats.size_allocated - stats.size_cached) / 1024);
+- seq_printf(m, "num bos cached: %d\n",
+- stats.num_cached);
+- seq_printf(m, "size bos cached: %dkb\n",
+- stats.size_cached / 1024);
+-
+ return 0;
+ }
+ #endif
+
++/* Takes ownership of *name and returns the appropriate slot for it in
++ * the bo_labels[] array, extending it as necessary.
++ *
++ * This is inefficient and could use a hash table instead of walking
++ * an array and strcmp()ing. However, the assumption is that user
++ * labeling will be infrequent (scanout buffers and other long-lived
++ * objects, or debug driver builds), so we can live with it for now.
++ */
++static int vc4_get_user_label(struct vc4_dev *vc4, const char *name)
++{
++ int i;
++ int free_slot = -1;
++
++ for (i = 0; i < vc4->num_labels; i++) {
++ if (!vc4->bo_labels[i].name) {
++ free_slot = i;
++ } else if (strcmp(vc4->bo_labels[i].name, name) == 0) {
++ kfree(name);
++ return i;
++ }
++ }
++
++ if (free_slot != -1) {
++ WARN_ON(vc4->bo_labels[free_slot].num_allocated != 0);
++ vc4->bo_labels[free_slot].name = name;
++ return free_slot;
++ } else {
++ u32 new_label_count = vc4->num_labels + 1;
++ struct vc4_label *new_labels =
++ krealloc(vc4->bo_labels,
++ new_label_count * sizeof(*new_labels),
++ GFP_KERNEL);
++
++ if (!new_labels) {
++ kfree(name);
++ return -1;
++ }
++
++ free_slot = vc4->num_labels;
++ vc4->bo_labels = new_labels;
++ vc4->num_labels = new_label_count;
++
++ vc4->bo_labels[free_slot].name = name;
++ vc4->bo_labels[free_slot].num_allocated = 0;
++ vc4->bo_labels[free_slot].size_allocated = 0;
++
++ return free_slot;
++ }
++}
++
++static void vc4_bo_set_label(struct drm_gem_object *gem_obj, int label)
++{
++ struct vc4_bo *bo = to_vc4_bo(gem_obj);
++ struct vc4_dev *vc4 = to_vc4_dev(gem_obj->dev);
++
++ lockdep_assert_held(&vc4->bo_lock);
++
++ if (label != -1) {
++ vc4->bo_labels[label].num_allocated++;
++ vc4->bo_labels[label].size_allocated += gem_obj->size;
++ }
++
++ vc4->bo_labels[bo->label].num_allocated--;
++ vc4->bo_labels[bo->label].size_allocated -= gem_obj->size;
++
++ if (vc4->bo_labels[bo->label].num_allocated == 0 &&
++ is_user_label(bo->label)) {
++ /* Free user BO label slots on last unreference.
++ * Slots are just where we track the stats for a given
++ * name, and once a name is unused we can reuse that
++ * slot.
++ */
++ kfree(vc4->bo_labels[bo->label].name);
++ vc4->bo_labels[bo->label].name = NULL;
++ }
++
++ bo->label = label;
++}
++
+ static uint32_t bo_page_index(size_t size)
+ {
+ return (size / PAGE_SIZE) - 1;
+@@ -80,7 +167,8 @@ static uint32_t bo_page_index(size_t size)
+ static void vc4_bo_destroy(struct vc4_bo *bo)
+ {
+ struct drm_gem_object *obj = &bo->base.base;
+- struct vc4_dev *vc4 = to_vc4_dev(obj->dev);
++
++ vc4_bo_set_label(obj, -1);
+
+ if (bo->validated_shader) {
+ kfree(bo->validated_shader->texture_samples);
+@@ -88,9 +176,6 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
+ bo->validated_shader = NULL;
+ }
+
+- vc4->bo_stats.num_allocated--;
+- vc4->bo_stats.size_allocated -= obj->size;
+-
+ reservation_object_fini(&bo->_resv);
+
+ drm_gem_cma_free_object(obj);
+@@ -99,12 +184,6 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
+ /* Must be called with bo_lock held. */
+ static void vc4_bo_remove_from_cache(struct vc4_bo *bo)
+ {
+- struct drm_gem_object *obj = &bo->base.base;
+- struct vc4_dev *vc4 = to_vc4_dev(obj->dev);
+-
+- vc4->bo_stats.num_cached--;
+- vc4->bo_stats.size_cached -= obj->size;
+-
+ list_del(&bo->unref_head);
+ list_del(&bo->size_head);
+ }
+@@ -165,7 +244,8 @@ static void vc4_bo_cache_purge(struct drm_device *dev)
+ }
+
+ static struct vc4_bo *vc4_bo_get_from_cache(struct drm_device *dev,
+- uint32_t size)
++ uint32_t size,
++ enum vc4_kernel_bo_type type)
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+ uint32_t page_index = bo_page_index(size);
+@@ -186,6 +266,8 @@ static struct vc4_bo *vc4_bo_get_from_cache(struct drm_device *dev,
+ kref_init(&bo->base.base.refcount);
+
+ out:
++ if (bo)
++ vc4_bo_set_label(&bo->base.base, type);
+ mutex_unlock(&vc4->bo_lock);
+ return bo;
+ }
+@@ -208,8 +290,9 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&vc4->bo_lock);
+- vc4->bo_stats.num_allocated++;
+- vc4->bo_stats.size_allocated += size;
++ bo->label = VC4_BO_TYPE_KERNEL;
++ vc4->bo_labels[VC4_BO_TYPE_KERNEL].num_allocated++;
++ vc4->bo_labels[VC4_BO_TYPE_KERNEL].size_allocated += size;
+ mutex_unlock(&vc4->bo_lock);
+ bo->resv = &bo->_resv;
+ reservation_object_init(bo->resv);
+@@ -218,7 +301,7 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
+ }
+
+ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
+- bool allow_unzeroed)
++ bool allow_unzeroed, enum vc4_kernel_bo_type type)
+ {
+ size_t size = roundup(unaligned_size, PAGE_SIZE);
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
+@@ -229,7 +312,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
+ return ERR_PTR(-EINVAL);
+
+ /* First, try to get a vc4_bo from the kernel BO cache. */
+- bo = vc4_bo_get_from_cache(dev, size);
++ bo = vc4_bo_get_from_cache(dev, size, type);
+ if (bo) {
+ if (!allow_unzeroed)
+ memset(bo->base.vaddr, 0, bo->base.base.size);
+@@ -251,7 +334,13 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
+ return ERR_PTR(-ENOMEM);
+ }
+ }
+- return to_vc4_bo(&cma_obj->base);
++ bo = to_vc4_bo(&cma_obj->base);
++
++ mutex_lock(&vc4->bo_lock);
++ vc4_bo_set_label(&cma_obj->base, type);
++ mutex_unlock(&vc4->bo_lock);
++
++ return bo;
+ }
+
+ int vc4_dumb_create(struct drm_file *file_priv,
+@@ -268,7 +357,7 @@ int vc4_dumb_create(struct drm_file *file_priv,
+ if (args->size < args->pitch * args->height)
+ args->size = args->pitch * args->height;
+
+- bo = vc4_bo_create(dev, args->size, false);
++ bo = vc4_bo_create(dev, args->size, false, VC4_BO_TYPE_DUMB);
+ if (IS_ERR(bo))
+ return PTR_ERR(bo);
+
+@@ -348,8 +437,7 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
+ list_add(&bo->size_head, cache_list);
+ list_add(&bo->unref_head, &vc4->bo_cache.time_list);
+
+- vc4->bo_stats.num_cached++;
+- vc4->bo_stats.size_cached += gem_bo->size;
++ vc4_bo_set_label(&bo->base.base, VC4_BO_TYPE_KERNEL_CACHE);
+
+ vc4_bo_cache_free_old(dev);
+
+@@ -483,7 +571,7 @@ int vc4_create_bo_ioctl(struct drm_device *dev, void *data,
+ * We can't allocate from the BO cache, because the BOs don't
+ * get zeroed, and that might leak data between users.
+ */
+- bo = vc4_bo_create(dev, args->size, false);
++ bo = vc4_bo_create(dev, args->size, false, VC4_BO_TYPE_V3D);
+ if (IS_ERR(bo))
+ return PTR_ERR(bo);
+
+@@ -536,7 +624,7 @@ vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data,
+ return -EINVAL;
+ }
+
+- bo = vc4_bo_create(dev, args->size, true);
++ bo = vc4_bo_create(dev, args->size, true, VC4_BO_TYPE_V3D_SHADER);
+ if (IS_ERR(bo))
+ return PTR_ERR(bo);
+
+@@ -651,9 +739,24 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
+ return 0;
+ }
+
+-void vc4_bo_cache_init(struct drm_device *dev)
++int vc4_bo_cache_init(struct drm_device *dev)
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ int i;
++
++ /* Create the initial set of BO labels that the kernel will
++ * use. This lets us avoid a bunch of string reallocation in
++ * the kernel's draw and BO allocation paths.
++ */
++ vc4->bo_labels = kcalloc(VC4_BO_TYPE_COUNT, sizeof(*vc4->bo_labels),
++ GFP_KERNEL);
++ if (!vc4->bo_labels)
++ return -ENOMEM;
++ vc4->num_labels = VC4_BO_TYPE_COUNT;
++
++ BUILD_BUG_ON(ARRAY_SIZE(bo_type_names) != VC4_BO_TYPE_COUNT);
++ for (i = 0; i < VC4_BO_TYPE_COUNT; i++)
++ vc4->bo_labels[i].name = bo_type_names[i];
+
+ mutex_init(&vc4->bo_lock);
+
+@@ -663,19 +766,66 @@ void vc4_bo_cache_init(struct drm_device *dev)
+ setup_timer(&vc4->bo_cache.time_timer,
+ vc4_bo_cache_time_timer,
+ (unsigned long)dev);
++
++ return 0;
+ }
+
+ void vc4_bo_cache_destroy(struct drm_device *dev)
+ {
+ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ int i;
+
+ del_timer(&vc4->bo_cache.time_timer);
+ cancel_work_sync(&vc4->bo_cache.time_work);
+
+ vc4_bo_cache_purge(dev);
+
+- if (vc4->bo_stats.num_allocated) {
+- DRM_ERROR("Destroying BO cache while BOs still allocated:\n");
+- vc4_bo_stats_dump(vc4);
++ for (i = 0; i < vc4->num_labels; i++) {
++ if (vc4->bo_labels[i].num_allocated) {
++ DRM_ERROR("Destroying BO cache with %d %s "
++ "BOs still allocated\n",
++ vc4->bo_labels[i].num_allocated,
++ vc4->bo_labels[i].name);
++ }
++
++ if (is_user_label(i))
++ kfree(vc4->bo_labels[i].name);
+ }
++ kfree(vc4->bo_labels);
++}
++
++int vc4_label_bo_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv)
++{
++ struct vc4_dev *vc4 = to_vc4_dev(dev);
++ struct drm_vc4_label_bo *args = data;
++ char *name;
++ struct drm_gem_object *gem_obj;
++ int ret = 0, label;
++
++ if (!args->len)
++ return -EINVAL;
++
++ name = strndup_user(u64_to_user_ptr(args->name), args->len + 1);
++ if (IS_ERR(name))
++ return PTR_ERR(name);
++
++ gem_obj = drm_gem_object_lookup(file_priv, args->handle);
++ if (!gem_obj) {
++ DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
++ kfree(name);
++ return -ENOENT;
++ }
++
++ mutex_lock(&vc4->bo_lock);
++ label = vc4_get_user_label(vc4, name);
++ if (label != -1)
++ vc4_bo_set_label(gem_obj, label);
++ else
++ ret = -ENOMEM;
++ mutex_unlock(&vc4->bo_lock);
++
++ drm_gem_object_unreference_unlocked(gem_obj);
++
++ return ret;
+ }
+diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
+index c6b487c3d2b7..75c1f50a7b5d 100644
+--- a/drivers/gpu/drm/vc4/vc4_drv.c
++++ b/drivers/gpu/drm/vc4/vc4_drv.c
+@@ -140,6 +140,7 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
+ DRM_IOCTL_DEF_DRV(VC4_GET_PARAM, vc4_get_param_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VC4_SET_TILING, vc4_set_tiling_ioctl, DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VC4_GET_TILING, vc4_get_tiling_ioctl, DRM_RENDER_ALLOW),
++ DRM_IOCTL_DEF_DRV(VC4_LABEL_BO, vc4_label_bo_ioctl, DRM_RENDER_ALLOW),
+ };
+
+ static struct drm_driver vc4_drm_driver = {
+@@ -257,7 +258,9 @@ static int vc4_drm_bind(struct device *dev)
+ vc4->dev = drm;
+ drm->dev_private = vc4;
+
+- vc4_bo_cache_init(drm);
++ ret = vc4_bo_cache_init(drm);
++ if (ret)
++ goto dev_unref;
+
+ drm_mode_config_init(drm);
+
+@@ -281,8 +284,9 @@ static int vc4_drm_bind(struct device *dev)
+ component_unbind_all(dev, drm);
+ gem_destroy:
+ vc4_gem_destroy(drm);
+- drm_dev_unref(drm);
+ vc4_bo_cache_destroy(drm);
++dev_unref:
++ drm_dev_unref(drm);
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
+index df22698d62ee..75d9957cb76d 100644
+--- a/drivers/gpu/drm/vc4/vc4_drv.h
++++ b/drivers/gpu/drm/vc4/vc4_drv.h
+@@ -11,6 +11,24 @@
+ #include <drm/drm_encoder.h>
+ #include <drm/drm_gem_cma_helper.h>
+
++/* Don't forget to update vc4_bo.c: bo_type_names[] when adding to
++ * this.
++ */
++enum vc4_kernel_bo_type {
++ /* Any kernel allocation (gem_create_object hook) before it
++ * gets another type set.
++ */
++ VC4_BO_TYPE_KERNEL,
++ VC4_BO_TYPE_V3D,
++ VC4_BO_TYPE_V3D_SHADER,
++ VC4_BO_TYPE_DUMB,
++ VC4_BO_TYPE_BIN,
++ VC4_BO_TYPE_RCL,
++ VC4_BO_TYPE_BCL,
++ VC4_BO_TYPE_KERNEL_CACHE,
++ VC4_BO_TYPE_COUNT
++};
++
+ struct vc4_dev {
+ struct drm_device *dev;
+
+@@ -46,14 +64,14 @@ struct vc4_dev {
+ struct timer_list time_timer;
+ } bo_cache;
+
+- struct vc4_bo_stats {
++ u32 num_labels;
++ struct vc4_label {
++ const char *name;
+ u32 num_allocated;
+ u32 size_allocated;
+- u32 num_cached;
+- u32 size_cached;
+- } bo_stats;
++ } *bo_labels;
+
+- /* Protects bo_cache and the BO stats. */
++ /* Protects bo_cache and bo_labels. */
+ struct mutex bo_lock;
+
+ uint64_t dma_fence_context;
+@@ -169,6 +187,11 @@ struct vc4_bo {
+ /* normally (resv == &_resv) except for imported bo's */
+ struct reservation_object *resv;
+ struct reservation_object _resv;
++
++ /* One of enum vc4_kernel_bo_type, or VC4_BO_TYPE_COUNT + i
++ * for user-allocated labels.
++ */
++ int label;
+ };
+
+ static inline struct vc4_bo *
+@@ -460,7 +483,7 @@ struct vc4_validated_shader_info {
+ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size);
+ void vc4_free_object(struct drm_gem_object *gem_obj);
+ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size,
+- bool from_cache);
++ bool from_cache, enum vc4_kernel_bo_type type);
+ int vc4_dumb_create(struct drm_file *file_priv,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args);
+@@ -478,6 +501,8 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+ int vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
++int vc4_label_bo_ioctl(struct drm_device *dev, void *data,
++ struct drm_file *file_priv);
+ int vc4_mmap(struct file *filp, struct vm_area_struct *vma);
+ struct reservation_object *vc4_prime_res_obj(struct drm_gem_object *obj);
+ int vc4_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+@@ -485,7 +510,7 @@ struct drm_gem_object *vc4_prime_import_sg_table(struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sgt);
+ void *vc4_prime_vmap(struct drm_gem_object *obj);
+-void vc4_bo_cache_init(struct drm_device *dev);
++int vc4_bo_cache_init(struct drm_device *dev);
+ void vc4_bo_cache_destroy(struct drm_device *dev);
+ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
+
+diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
+index 8b551bc630c4..80f1953b4938 100644
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -774,7 +774,7 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
+ goto fail;
+ }
+
+- bo = vc4_bo_create(dev, exec_size, true);
++ bo = vc4_bo_create(dev, exec_size, true, VC4_BO_TYPE_BCL);
+ if (IS_ERR(bo)) {
+ DRM_ERROR("Couldn't allocate BO for binning\n");
+ ret = PTR_ERR(bo);
+diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c
+index da3bfd53f0bd..e0539731130b 100644
+--- a/drivers/gpu/drm/vc4/vc4_render_cl.c
++++ b/drivers/gpu/drm/vc4/vc4_render_cl.c
+@@ -320,7 +320,7 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
+
+ size += xtiles * ytiles * loop_body_size;
+
+- setup->rcl = &vc4_bo_create(dev, size, true)->base;
++ setup->rcl = &vc4_bo_create(dev, size, true, VC4_BO_TYPE_RCL)->base;
+ if (IS_ERR(setup->rcl))
+ return PTR_ERR(setup->rcl);
+ list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head,
+diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
+index 8c723da71f66..622cd43840b8 100644
+--- a/drivers/gpu/drm/vc4/vc4_v3d.c
++++ b/drivers/gpu/drm/vc4/vc4_v3d.c
+@@ -236,7 +236,8 @@ vc4_allocate_bin_bo(struct drm_device *drm)
+ INIT_LIST_HEAD(&list);
+
+ while (true) {
+- struct vc4_bo *bo = vc4_bo_create(drm, size, true);
++ struct vc4_bo *bo = vc4_bo_create(drm, size, true,
++ VC4_BO_TYPE_BIN);
+
+ if (IS_ERR(bo)) {
+ ret = PTR_ERR(bo);
+diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h
+index 6ac4c5c014cb..551628e571f9 100644
+--- a/include/uapi/drm/vc4_drm.h
++++ b/include/uapi/drm/vc4_drm.h
+@@ -40,6 +40,7 @@ extern "C" {
+ #define DRM_VC4_GET_PARAM 0x07
+ #define DRM_VC4_SET_TILING 0x08
+ #define DRM_VC4_GET_TILING 0x09
++#define DRM_VC4_LABEL_BO 0x0a
+
+ #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl)
+ #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno)
+@@ -51,6 +52,7 @@ extern "C" {
+ #define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param)
+ #define DRM_IOCTL_VC4_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SET_TILING, struct drm_vc4_set_tiling)
+ #define DRM_IOCTL_VC4_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_TILING, struct drm_vc4_get_tiling)
++#define DRM_IOCTL_VC4_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_LABEL_BO, struct drm_vc4_label_bo)
+
+ struct drm_vc4_submit_rcl_surface {
+ __u32 hindex; /* Handle index, or ~0 if not present. */
+@@ -311,6 +313,15 @@ struct drm_vc4_set_tiling {
+ __u64 modifier;
+ };
+
++/**
++ * struct drm_vc4_label_bo - Attach a name to a BO for debug purposes.
++ */
++struct drm_vc4_label_bo {
++ __u32 handle;
++ __u32 len;
++ __u64 name;
++};
++
+ #if defined(__cplusplus)
+ }
+ #endif
+--
+2.13.5
+
+From 34cbed8ed9441caa13017108dac189e09c35f9af Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 2 Aug 2017 13:32:40 -0700
+Subject: [PATCH 5/6] drm/vc4: Fix double destroy of the BO cache on teardown.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's also destroyed from the top level vc4_drv.c initialization, which
+is where the cache was actually initialized from.
+
+This used to just involve duplicate del_timer() and cancel_work_sync()
+being called, but it started causing kmalloc issues once we
+double-freed the new BO label array.
+
+Fixes: 1908a876f909 ("drm/vc4: Add an ioctl for labeling GEM BOs for summary stats")
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170802203242.12815-1-eric@anholt.net
+Tested-by: Noralf Trønnes <noralf@tronnes.org>
+Acked-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+---
+ drivers/gpu/drm/vc4/vc4_gem.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
+index 80f1953b4938..624177b9cce4 100644
+--- a/drivers/gpu/drm/vc4/vc4_gem.c
++++ b/drivers/gpu/drm/vc4/vc4_gem.c
+@@ -1117,6 +1117,4 @@ vc4_gem_destroy(struct drm_device *dev)
+
+ if (vc4->hang_state)
+ vc4_free_hang_state(dev, vc4->hang_state);
+-
+- vc4_bo_cache_destroy(dev);
+ }
+--
+2.13.5
+
+From 4f218eea5be54c8506e6db700750e8b8019dc6af Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Fri, 16 Jun 2017 10:30:33 +0200
+Subject: [PATCH 6/6] drm/vc4: Send a VBLANK event when disabling a CRTC
+
+VBLANK events are missed when the CRTC is being disabled because the
+driver does not wait till the end of the frame before stopping the
+HVS and PV blocks. In this case, we should explicitly issue a VBLANK
+event if there's one waiting.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Link: http://patchwork.freedesktop.org/patch/msgid/1497601833-24588-1-git-send-email-boris.brezillon@free-electrons.com
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
+index a12cc7ea99b6..b0582ad3f459 100644
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -518,6 +518,19 @@ static void vc4_crtc_disable(struct drm_crtc *crtc)
+ WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+ (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+ SCALER_DISPSTATX_EMPTY);
++
++ /*
++ * Make sure we issue a vblank event after disabling the CRTC if
++ * someone was waiting it.
++ */
++ if (crtc->state->event) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->event_lock, flags);
++ drm_crtc_send_vblank_event(crtc, crtc->state->event);
++ crtc->state->event = NULL;
++ spin_unlock_irqrestore(&dev->event_lock, flags);
++ }
+ }
+
+ static void vc4_crtc_update_dlist(struct drm_crtc *crtc)
+--
+2.13.5
+
diff --git a/kernel.spec b/kernel.spec
index d2988597b..3034b9108 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -609,8 +609,7 @@ Patch313: qcom-Force-host-mode-for-USB-on-apq8016-sbc.patch
# https://patchwork.kernel.org/patch/9850189/
Patch314: qcom-msm-ci_hdrc_msm_probe-missing-of_node_get.patch
-# http://www.spinics.net/lists/dri-devel/msg132235.html
-Patch320: bcm283x-vc4-Fix-OOPSes-from-trying-to-cache-a-partially-constructed-BO..patch
+Patch320: bcm283x-vc4-fixes.patch
# Fix USB on the RPi https://patchwork.kernel.org/patch/9879371/
Patch321: bcm283x-dma-mapping-skip-USB-devices-when-configuring-DMA-during-probe.patch