drm/vc4/vc4_bo.c: always set bo->resv
authorHans Verkuil <hverkuil@xs4all.nl>
Wed, 7 Jun 2017 19:05:57 +0000 (21:05 +0200)
committerEric Anholt <eric@anholt.net>
Mon, 12 Jun 2017 23:48:03 +0000 (16:48 -0700)
The bo->resv pointer could be NULL, leading to kernel oopses
like the one below.

This patch ensures that bo->resv is always set in vc4_create_object
ensuring that it is never NULL.

Thanks to Eric Anholt for pointing to the correct solution.

[   19.738487] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[   19.746805] pgd = ffff8000275fc000
[   19.750319] [00000000] *pgd=0000000000000000
[   19.754715] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[   19.760369] Modules linked in: smsc95xx usbnet vc4 drm_kms_helper drm pwm_bcm2835 i2c_bcm2835 bcm2835_rng rng_core bcm2835_dma virt_dma
[   19.772767] CPU: 0 PID: 1297 Comm: Xorg Not tainted 4.12.0-rc1-rpi3 #58
[   19.779476] Hardware name: Raspberry Pi 3 Model B (DT)
[   19.784688] task: ffff800028268000 task.stack: ffff800026c08000
[   19.790705] PC is at ww_mutex_lock_interruptible+0x14/0xc0
[   19.796329] LR is at vc4_submit_cl_ioctl+0x4fc/0x998 [vc4]
...
[   20.240855] [<ffff0000088975f4>] ww_mutex_lock_interruptible+0x14/0xc0
[   20.247528] [<ffff0000009b3ea4>] vc4_submit_cl_ioctl+0x4fc/0x998 [vc4]
[   20.254372] [<ffff0000008f75f8>] drm_ioctl+0x180/0x438 [drm]
[   20.260120] [<ffff00000821383c>] do_vfs_ioctl+0xa4/0x7d0
[   20.265510] [<ffff000008213fe4>] SyS_ioctl+0x7c/0x98
[   20.270550] [<ffff000008082f30>] el0_svc_naked+0x24/0x28
[   20.275941] Code: d2800002 d5384103 910003fd f9800011 (c85ffc04)
[   20.282527] ---[ end trace 1f6bd640ff32ae12 ]---

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Link: http://patchwork.freedesktop.org/patch/msgid/14e68768-6c92-2d74-92fd-196dbc50d8f7@xs4all.nl
drivers/gpu/drm/vc4/vc4_bo.c

index 80b2f9e..590c091 100644 (file)
@@ -91,8 +91,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
        vc4->bo_stats.num_allocated--;
        vc4->bo_stats.size_allocated -= obj->size;
 
-       if (bo->resv == &bo->_resv)
-               reservation_object_fini(bo->resv);
+       reservation_object_fini(&bo->_resv);
 
        drm_gem_cma_free_object(obj);
 }
@@ -212,6 +211,8 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
        vc4->bo_stats.num_allocated++;
        vc4->bo_stats.size_allocated += size;
        mutex_unlock(&vc4->bo_lock);
+       bo->resv = &bo->_resv;
+       reservation_object_init(bo->resv);
 
        return &bo->base.base;
 }
@@ -250,12 +251,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
                        return ERR_PTR(-ENOMEM);
                }
        }
-       bo = to_vc4_bo(&cma_obj->base);
-
-       bo->resv = &bo->_resv;
-       reservation_object_init(bo->resv);
-
-       return bo;
+       return to_vc4_bo(&cma_obj->base);
 }
 
 int vc4_dumb_create(struct drm_file *file_priv,