alistair23-linux/drivers/gpu/drm/msm/msm_ringbuffer.c
Rob Clark 774449ebcb drm/msm: fix locking inconsistencies in gpu->destroy()
In error paths, this was being called without struct_mutex held.
Leading to panics like:

  msm 1a00000.qcom,mdss_mdp: No memory protection without IOMMU
  Kernel panic - not syncing: BUG!
  CPU: 0 PID: 1409 Comm: cat Not tainted 4.0.0-dirty #4
  Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
  Call trace:
  [<ffffffc000089c78>] dump_backtrace+0x0/0x118
  [<ffffffc000089da0>] show_stack+0x10/0x20
  [<ffffffc0006686d4>] dump_stack+0x84/0xc4
  [<ffffffc0006678b4>] panic+0xd0/0x210
  [<ffffffc0003e1ce4>] drm_gem_object_free+0x5c/0x60
  [<ffffffc000402870>] adreno_gpu_cleanup+0x60/0x80
  [<ffffffc0004035a0>] a3xx_destroy+0x20/0x70
  [<ffffffc0004036f4>] a3xx_gpu_init+0x84/0x108
  [<ffffffc0004018b8>] adreno_load_gpu+0x58/0x190
  [<ffffffc000419dac>] msm_open+0x74/0x88
  [<ffffffc0003e0a48>] drm_open+0x168/0x400
  [<ffffffc0003e7210>] drm_stub_open+0xa8/0x118
  [<ffffffc0001a0e84>] chrdev_open+0x94/0x198
  [<ffffffc000199f88>] do_dentry_open+0x208/0x310
  [<ffffffc00019a4c4>] vfs_open+0x44/0x50
  [<ffffffc0001aa26c>] do_last.isra.14+0x2c4/0xc10
  [<ffffffc0001aac38>] path_openat+0x80/0x5e8
  [<ffffffc0001ac354>] do_filp_open+0x2c/0x98
  [<ffffffc00019b60c>] do_sys_open+0x13c/0x228
  [<ffffffc00019b72c>] SyS_openat+0xc/0x18
  CPU1: stopping

But there isn't any particularly good reason to hold struct_mutex for
teardown, so just standardize on calling it without the mutex held and
use the _unlocked() versions for GEM obj unref'ing

Signed-off-by: Rob Clark <robdclark@gmail.com>
2015-05-15 09:28:27 -04:00

62 lines
1.5 KiB
C

/*
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "msm_ringbuffer.h"
#include "msm_gpu.h"
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
{
struct msm_ringbuffer *ring;
int ret;
size = ALIGN(size, 4); /* size should be dword aligned */
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring) {
ret = -ENOMEM;
goto fail;
}
ring->gpu = gpu;
ring->bo = msm_gem_new(gpu->dev, size, MSM_BO_WC);
if (IS_ERR(ring->bo)) {
ret = PTR_ERR(ring->bo);
ring->bo = NULL;
goto fail;
}
ring->start = msm_gem_vaddr_locked(ring->bo);
ring->end = ring->start + (size / 4);
ring->cur = ring->start;
ring->size = size;
return ring;
fail:
if (ring)
msm_ringbuffer_destroy(ring);
return ERR_PTR(ret);
}
void msm_ringbuffer_destroy(struct msm_ringbuffer *ring)
{
if (ring->bo)
drm_gem_object_unreference_unlocked(ring->bo);
kfree(ring);
}