summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-08-21 17:37:33 +1000
committerDave Airlie <airlied@redhat.com>2017-08-21 17:37:33 +1000
commit3aadb888b1b62ba04798414cae431d3c3bd5f452 (patch)
tree3fac632c260090c711c766339eaa1fca31447f4c /drivers
parente5fa05b96b02f45a91a364d2121451a4da05cd84 (diff)
parentec73c4cfe7de6229e49989f7d7754a7039cd5c28 (diff)
Merge tag 'drm/tegra/for-4.14-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v4.14-rc1 This contains a couple of fixes and improvements for host1x, with some preparatory work for Tegra186 support. The remainder is cleanup and minor bugfixes for Tegra DRM along with enhancements to debuggability. There have also been some enhancements to the kernel interfaces for host1x job submissions and support for mmap'ing PRIME buffers directly, all of which get the interfaces very close to ready for serious work. * tag 'drm/tegra/for-4.14-rc1' of git://anongit.freedesktop.org/tegra/linux: (21 commits) drm/tegra: Prevent BOs from being freed during job submission drm/tegra: gem: Implement mmap() for PRIME buffers drm/tegra: Support render node drm/tegra: sor: Trace register accesses drm/tegra: dpaux: Trace register accesses drm/tegra: dsi: Trace register accesses drm/tegra: hdmi: Trace register accesses drm/tegra: dc: Trace register accesses drm/tegra: sor: Use unsigned int for register offsets drm/tegra: hdmi: Use unsigned int for register offsets drm/tegra: dsi: Use unsigned int for register offsets drm/tegra: dpaux: Use unsigned int for register offsets drm/tegra: dc: Use unsigned int for register offsets drm/tegra: Fix NULL deref in debugfs/iova drm/tegra: switch to drm_*_get(), drm_*_put() helpers drm/tegra: Set MODULE_FIRMWARE for the VIC drm/tegra: Add CONFIG_OF dependency gpu: host1x: Support sub-devices recursively gpu: host1x: fix error return code in host1x_probe() gpu: host1x: Fix bitshift/mask multipliers ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/Makefile2
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c12
-rw-r--r--drivers/gpu/drm/tegra/drm.c102
-rw-r--r--drivers/gpu/drm/tegra/drm.h12
-rw-r--r--drivers/gpu/drm/tegra/dsi.c14
-rw-r--r--drivers/gpu/drm/tegra/fb.c8
-rw-r--r--drivers/gpu/drm/tegra/gem.c57
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c12
-rw-r--r--drivers/gpu/drm/tegra/sor.c12
-rw-r--r--drivers/gpu/drm/tegra/trace.c2
-rw-r--r--drivers/gpu/drm/tegra/trace.h68
-rw-r--r--drivers/gpu/drm/tegra/vic.c15
-rw-r--r--drivers/gpu/host1x/bus.c18
-rw-r--r--drivers/gpu/host1x/dev.c4
-rw-r--r--drivers/gpu/host1x/hw/intr_hw.c24
-rw-r--r--drivers/gpu/host1x/hw/syncpt_hw.c2
-rw-r--r--drivers/gpu/host1x/job.c8
18 files changed, 276 insertions, 97 deletions
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 2db29d67193d..dc58ab140151 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -3,6 +3,7 @@ config DRM_TEGRA
depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
depends on COMMON_CLK
depends on DRM
+ depends on OF
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index 6af3a9ad6565..8927784396e8 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -17,4 +17,6 @@ tegra-drm-y := \
falcon.o \
vic.o
+tegra-drm-y += trace.o
+
obj-$(CONFIG_DRM_TEGRA) += tegra-drm.o
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 2fde44c3a1b3..e4da041ba89b 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -25,6 +25,7 @@
#include "dpaux.h"
#include "drm.h"
+#include "trace.h"
static DEFINE_MUTEX(dpaux_lock);
static LIST_HEAD(dpaux_list);
@@ -65,14 +66,19 @@ static inline struct tegra_dpaux *work_to_dpaux(struct work_struct *work)
}
static inline u32 tegra_dpaux_readl(struct tegra_dpaux *dpaux,
- unsigned long offset)
+ unsigned int offset)
{
- return readl(dpaux->regs + (offset << 2));
+ u32 value = readl(dpaux->regs + (offset << 2));
+
+ trace_dpaux_readl(dpaux->dev, offset, value);
+
+ return value;
}
static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
- u32 value, unsigned long offset)
+ u32 value, unsigned int offset)
{
+ trace_dpaux_writel(dpaux->dev, offset, value);
writel(value, dpaux->regs + (offset << 2));
}
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 224ce1dbb1cb..597d563d636a 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -306,8 +306,6 @@ host1x_bo_lookup(struct drm_file *file, u32 handle)
if (!gem)
return NULL;
- drm_gem_object_unreference_unlocked(gem);
-
bo = to_tegra_bo(gem);
return &bo->base;
}
@@ -396,8 +394,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
(void __user *)(uintptr_t)args->waitchks;
struct drm_tegra_syncpt syncpt;
struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
+ struct drm_gem_object **refs;
struct host1x_syncpt *sp;
struct host1x_job *job;
+ unsigned int num_refs;
int err;
/* We don't yet support other than one syncpt_incr struct per submit */
@@ -419,6 +419,21 @@ int tegra_drm_submit(struct tegra_drm_context *context,
job->class = context->client->base.class;
job->serialize = true;
+ /*
+ * Track referenced BOs so that they can be unreferenced after the
+ * submission is complete.
+ */
+ num_refs = num_cmdbufs + num_relocs * 2 + num_waitchks;
+
+ refs = kmalloc_array(num_refs, sizeof(*refs), GFP_KERNEL);
+ if (!refs) {
+ err = -ENOMEM;
+ goto put;
+ }
+
+ /* reuse as an iterator later */
+ num_refs = 0;
+
while (num_cmdbufs) {
struct drm_tegra_cmdbuf cmdbuf;
struct host1x_bo *bo;
@@ -447,6 +462,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32);
obj = host1x_to_tegra_bo(bo);
+ refs[num_refs++] = &obj->gem;
/*
* Gather buffer base address must be 4-bytes aligned,
@@ -476,6 +492,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
reloc = &job->relocarray[num_relocs];
obj = host1x_to_tegra_bo(reloc->cmdbuf.bo);
+ refs[num_refs++] = &obj->gem;
/*
* The unaligned cmdbuf offset will cause an unaligned write
@@ -489,6 +506,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
}
obj = host1x_to_tegra_bo(reloc->target.bo);
+ refs[num_refs++] = &obj->gem;
if (reloc->target.offset >= obj->gem.size) {
err = -EINVAL;
@@ -508,6 +526,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
goto fail;
obj = host1x_to_tegra_bo(wait->bo);
+ refs[num_refs++] = &obj->gem;
/*
* The unaligned offset will cause an unaligned write during
@@ -547,17 +566,20 @@ int tegra_drm_submit(struct tegra_drm_context *context,
goto fail;
err = host1x_job_submit(job);
- if (err)
- goto fail_submit;
+ if (err) {
+ host1x_job_unpin(job);
+ goto fail;
+ }
args->fence = job->syncpt_end;
- host1x_job_put(job);
- return 0;
-
-fail_submit:
- host1x_job_unpin(job);
fail:
+ while (num_refs--)
+ drm_gem_object_put_unlocked(refs[num_refs]);
+
+ kfree(refs);
+
+put:
host1x_job_put(job);
return err;
}
@@ -593,7 +615,7 @@ static int tegra_gem_mmap(struct drm_device *drm, void *data,
args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
- drm_gem_object_unreference_unlocked(gem);
+ drm_gem_object_put_unlocked(gem);
return 0;
}
@@ -860,7 +882,7 @@ static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
bo->tiling.mode = mode;
bo->tiling.value = value;
- drm_gem_object_unreference_unlocked(gem);
+ drm_gem_object_put_unlocked(gem);
return 0;
}
@@ -900,7 +922,7 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
break;
}
- drm_gem_object_unreference_unlocked(gem);
+ drm_gem_object_put_unlocked(gem);
return err;
}
@@ -925,7 +947,7 @@ static int tegra_gem_set_flags(struct drm_device *drm, void *data,
if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP;
- drm_gem_object_unreference_unlocked(gem);
+ drm_gem_object_put_unlocked(gem);
return 0;
}
@@ -947,7 +969,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
if (bo->flags & TEGRA_BO_BOTTOM_UP)
args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
- drm_gem_object_unreference_unlocked(gem);
+ drm_gem_object_put_unlocked(gem);
return 0;
}
@@ -955,20 +977,34 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, 0),
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, 0),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags,
+ DRM_UNLOCKED | DRM_RENDER_ALLOW),
#endif
};
@@ -1035,9 +1071,11 @@ static int tegra_debugfs_iova(struct seq_file *s, void *data)
struct tegra_drm *tegra = drm->dev_private;
struct drm_printer p = drm_seq_file_printer(s);
- mutex_lock(&tegra->mm_lock);
- drm_mm_print(&tegra->mm, &p);
- mutex_unlock(&tegra->mm_lock);
+ if (tegra->domain) {
+ mutex_lock(&tegra->mm_lock);
+ drm_mm_print(&tegra->mm, &p);
+ mutex_unlock(&tegra->mm_lock);
+ }
return 0;
}
@@ -1057,7 +1095,7 @@ static int tegra_debugfs_init(struct drm_minor *minor)
static struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
- DRIVER_ATOMIC,
+ DRIVER_ATOMIC | DRIVER_RENDER,
.load = tegra_drm_load,
.unload = tegra_drm_unload,
.open = tegra_drm_open,
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 6d6da01282f3..063f5d397526 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -23,6 +23,7 @@
#include <drm/drm_fixed.h>
#include "gem.h"
+#include "trace.h"
struct reset_control;
@@ -172,14 +173,19 @@ static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc)
}
static inline void tegra_dc_writel(struct tegra_dc *dc, u32 value,
- unsigned long offset)
+ unsigned int offset)
{
+ trace_dc_writel(dc->dev, offset, value);
writel(value, dc->regs + (offset << 2));
}
-static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned long offset)
+static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned int offset)
{
- return readl(dc->regs + (offset << 2));
+ u32 value = readl(dc->regs + (offset << 2));
+
+ trace_dc_readl(dc->dev, offset, value);
+
+ return value;
}
struct tegra_dc_window {
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index e4b5aedfdbd4..046649ec9441 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -28,6 +28,7 @@
#include "drm.h"
#include "dsi.h"
#include "mipi-phy.h"
+#include "trace.h"
struct tegra_dsi_state {
struct drm_connector_state base;
@@ -105,15 +106,20 @@ static struct tegra_dsi_state *tegra_dsi_get_state(struct tegra_dsi *dsi)
return to_dsi_state(dsi->output.connector.state);
}
-static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned long reg)
+static inline u32 tegra_dsi_readl(struct tegra_dsi *dsi, unsigned int offset)
{
- return readl(dsi->regs + (reg << 2));
+ u32 value = readl(dsi->regs + (offset << 2));
+
+ trace_dsi_readl(dsi->dev, offset, value);
+
+ return value;
}
static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value,
- unsigned long reg)
+ unsigned int offset)
{
- writel(value, dsi->regs + (reg << 2));
+ trace_dsi_writel(dsi->dev, offset, value);
+ writel(value, dsi->regs + (offset << 2));
}
static int tegra_dsi_show_regs(struct seq_file *s, void *data)
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 25acb73ee728..80540c1c66dc 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -88,7 +88,7 @@ static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
if (bo->pages)
vunmap(bo->vaddr);
- drm_gem_object_unreference_unlocked(&bo->gem);
+ drm_gem_object_put_unlocked(&bo->gem);
}
}
@@ -195,7 +195,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
unreference:
while (i--)
- drm_gem_object_unreference_unlocked(&planes[i]->gem);
+ drm_gem_object_put_unlocked(&planes[i]->gem);
return ERR_PTR(err);
}
@@ -242,7 +242,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) {
dev_err(drm->dev, "failed to allocate framebuffer info\n");
- drm_gem_object_unreference_unlocked(&bo->gem);
+ drm_gem_object_put_unlocked(&bo->gem);
return PTR_ERR(info);
}
@@ -251,7 +251,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
err = PTR_ERR(fbdev->fb);
dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n",
err);
- drm_gem_object_unreference_unlocked(&bo->gem);
+ drm_gem_object_put_unlocked(&bo->gem);
return PTR_ERR(fbdev->fb);
}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index c6079affe642..ab1e53d434e8 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -24,7 +24,7 @@ static void tegra_bo_put(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- drm_gem_object_unreference_unlocked(&obj->gem);
+ drm_gem_object_put_unlocked(&obj->gem);
}
static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
@@ -95,7 +95,7 @@ static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- drm_gem_object_reference(&obj->gem);
+ drm_gem_object_get(&obj->gem);
return bo;
}
@@ -325,7 +325,7 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
return ERR_PTR(err);
}
- drm_gem_object_unreference_unlocked(&bo->gem);
+ drm_gem_object_put_unlocked(&bo->gem);
return bo;
}
@@ -460,30 +460,28 @@ const struct vm_operations_struct tegra_bo_vm_ops = {
.close = drm_gem_vm_close,
};
-int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
+static int tegra_gem_mmap(struct drm_gem_object *gem,
+ struct vm_area_struct *vma)
{
- struct drm_gem_object *gem;
- struct tegra_bo *bo;
- int ret;
-
- ret = drm_gem_mmap(file, vma);
- if (ret)
- return ret;
-
- gem = vma->vm_private_data;
- bo = to_tegra_bo(gem);
+ struct tegra_bo *bo = to_tegra_bo(gem);
if (!bo->pages) {
unsigned long vm_pgoff = vma->vm_pgoff;
+ int err;
+ /*
+ * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(),
+ * and set the vm_pgoff (used as a fake buffer offset by DRM)
+ * to 0 as we want to map the whole buffer.
+ */
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_pgoff = 0;
- ret = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr,
+ err = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr,
gem->size);
- if (ret) {
+ if (err < 0) {
drm_gem_vm_close(vma);
- return ret;
+ return err;
}
vma->vm_pgoff = vm_pgoff;
@@ -499,6 +497,20 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
+int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct drm_gem_object *gem;
+ int err;
+
+ err = drm_gem_mmap(file, vma);
+ if (err < 0)
+ return err;
+
+ gem = vma->vm_private_data;
+
+ return tegra_gem_mmap(gem, vma);
+}
+
static struct sg_table *
tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
@@ -582,7 +594,14 @@ static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page,
static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
{
- return -EINVAL;
+ struct drm_gem_object *gem = buf->priv;
+ int err;
+
+ err = drm_gem_mmap_obj(gem, gem->size, vma);
+ if (err < 0)
+ return err;
+
+ return tegra_gem_mmap(gem, vma);
}
static void *tegra_gem_prime_vmap(struct dma_buf *buf)
@@ -633,7 +652,7 @@ struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
struct drm_gem_object *gem = buf->priv;
if (gem->dev == drm) {
- drm_gem_object_reference(gem);
+ drm_gem_object_get(gem);
return gem;
}
}
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index a621b0da4092..5b9d83b71943 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -24,6 +24,7 @@
#include "hdmi.h"
#include "drm.h"
#include "dc.h"
+#include "trace.h"
#define HDMI_ELD_BUFFER_SIZE 96
@@ -100,14 +101,19 @@ enum {
};
static inline u32 tegra_hdmi_readl(struct tegra_hdmi *hdmi,
- unsigned long offset)
+ unsigned int offset)
{
- return readl(hdmi->regs + (offset << 2));
+ u32 value = readl(hdmi->regs + (offset << 2));
+
+ trace_hdmi_readl(hdmi->dev, offset, value);
+
+ return value;
}
static inline void tegra_hdmi_writel(struct tegra_hdmi *hdmi, u32 value,
- unsigned long offset)
+ unsigned int offset)
{
+ trace_hdmi_writel(hdmi->dev, offset, value);
writel(value, hdmi->regs + (offset << 2));
}
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index e0642d05a8d3..7ab1d1dc7cd7 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -26,6 +26,7 @@
#include "dc.h"
#include "drm.h"
#include "sor.h"
+#include "trace.h"
#define SOR_REKEY 0x38
@@ -232,14 +233,19 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
return container_of(output, struct tegra_sor, output);
}
-static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned long offset)
+static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
{
- return readl(sor->regs + (offset << 2));
+ u32 value = readl(sor->regs + (offset << 2));
+
+ trace_sor_readl(sor->dev, offset, value);
+
+ return value;
}
static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value,
- unsigned long offset)
+ unsigned int offset)
{
+ trace_sor_writel(sor->dev, offset, value);
writel(value, sor->regs + (offset << 2));
}
diff --git a/drivers/gpu/drm/tegra/trace.c b/drivers/gpu/drm/tegra/trace.c
new file mode 100644
index 000000000000..006f65c72a34
--- /dev/null
+++ b/drivers/gpu/drm/tegra/trace.c
@@ -0,0 +1,2 @@
+#define CREATE_TRACE_POINTS
+#include "trace.h"
diff --git a/drivers/gpu/drm/tegra/trace.h b/drivers/gpu/drm/tegra/trace.h
new file mode 100644
index 000000000000..e9b7cdad5c4c
--- /dev/null
+++ b/drivers/gpu/drm/tegra/trace.h
@@ -0,0 +1,68 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM tegra
+
+#if !defined(DRM_TEGRA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define DRM_TEGRA_TRACE_H 1
+
+#include <linux/device.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(register_access,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value),
+ TP_STRUCT__entry(
+ __field(struct device *, dev)
+ __field(unsigned int, offset)
+ __field(u32, value)
+ ),
+ TP_fast_assign(
+ __entry->dev = dev;
+ __entry->offset = offset;
+ __entry->value = value;
+ ),
+ TP_printk("%s %04x %08x", dev_name(__entry->dev), __entry->offset,
+ __entry->value)
+);
+
+DEFINE_EVENT(register_access, dc_writel,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+DEFINE_EVENT(register_access, dc_readl,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+
+DEFINE_EVENT(register_access, hdmi_writel,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+DEFINE_EVENT(register_access, hdmi_readl,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+
+DEFINE_EVENT(register_access, dsi_writel,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+DEFINE_EVENT(register_access, dsi_readl,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+
+DEFINE_EVENT(register_access, dpaux_writel,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+DEFINE_EVENT(register_access, dpaux_readl,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+
+DEFINE_EVENT(register_access, sor_writel,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+DEFINE_EVENT(register_access, sor_readl,
+ TP_PROTO(struct device *dev, unsigned int offset, u32 value),
+ TP_ARGS(dev, offset, value));
+
+#endif /* DRM_TEGRA_TRACE_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 47cb1aaa58b1..2448229fa653 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -258,12 +258,16 @@ static const struct tegra_drm_client_ops vic_ops = {
.submit = tegra_drm_submit,
};
+#define NVIDIA_TEGRA_124_VIC_FIRMWARE "nvidia/tegra124/vic03_ucode.bin"
+
static const struct vic_config vic_t124_config = {
- .firmware = "nvidia/tegra124/vic03_ucode.bin",
+ .firmware = NVIDIA_TEGRA_124_VIC_FIRMWARE,
};
+#define NVIDIA_TEGRA_210_VIC_FIRMWARE "nvidia/tegra210/vic04_ucode.bin"
+
static const struct vic_config vic_t210_config = {
- .firmware = "nvidia/tegra210/vic04_ucode.bin",
+ .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE,
};
static const struct of_device_id vic_match[] = {
@@ -394,3 +398,10 @@ struct platform_driver tegra_vic_driver = {
.probe = vic_probe,
.remove = vic_remove,
};
+
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC)
+MODULE_FIRMWARE(NVIDIA_TEGRA_124_VIC_FIRMWARE);
+#endif
+#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
+MODULE_FIRMWARE(NVIDIA_TEGRA_210_VIC_FIRMWARE);
+#endif
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 7ece0e9058c6..f9cde03030fd 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -44,9 +44,12 @@ struct host1x_subdev {
* @np: device node
*/
static int host1x_subdev_add(struct host1x_device *device,
+ struct host1x_driver *driver,
struct device_node *np)
{
struct host1x_subdev *subdev;
+ struct device_node *child;
+ int err;
subdev = kzalloc(sizeof(*subdev), GFP_KERNEL);
if (!subdev)
@@ -59,6 +62,19 @@ static int host1x_subdev_add(struct host1x_device *device,
list_add_tail(&subdev->list, &device->subdevs);
mutex_unlock(&device->subdevs_lock);
+ /* recursively add children */
+ for_each_child_of_node(np, child) {
+ if (of_match_node(driver->subdevs, child) &&
+ of_device_is_available(child)) {
+ err = host1x_subdev_add(device, driver, child);
+ if (err < 0) {
+ /* XXX cleanup? */
+ of_node_put(child);
+ return err;
+ }
+ }
+ }
+
return 0;
}
@@ -87,7 +103,7 @@ static int host1x_device_parse_dt(struct host1x_device *device,
for_each_child_of_node(device->dev.parent->of_node, np) {
if (of_match_node(driver->subdevs, np) &&
of_device_is_available(np)) {
- err = host1x_subdev_add(device, np);
+ err = host1x_subdev_add(device, driver, np);
if (err < 0) {
of_node_put(np);
return err;
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index 778272514164..7f22c5c37660 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -134,8 +134,8 @@ static int host1x_probe(struct platform_device *pdev)
syncpt_irq = platform_get_irq(pdev, 0);
if (syncpt_irq < 0) {
- dev_err(&pdev->dev, "failed to get IRQ\n");
- return -ENXIO;
+ dev_err(&pdev->dev, "failed to get IRQ: %d\n", syncpt_irq);
+ return syncpt_irq;
}
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c
index dacb8009a605..37ebb51703fa 100644
--- a/drivers/gpu/host1x/hw/intr_hw.c
+++ b/drivers/gpu/host1x/hw/intr_hw.c
@@ -33,10 +33,10 @@ static void host1x_intr_syncpt_handle(struct host1x_syncpt *syncpt)
unsigned int id = syncpt->id;
struct host1x *host = syncpt->host;
- host1x_sync_writel(host, BIT_MASK(id),
- HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id)));
- host1x_sync_writel(host, BIT_MASK(id),
- HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id)));
+ host1x_sync_writel(host, BIT(id % 32),
+ HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
+ host1x_sync_writel(host, BIT(id % 32),
+ HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
schedule_work(&syncpt->intr.work);
}
@@ -50,9 +50,9 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id)
for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) {
reg = host1x_sync_readl(host,
HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i));
- for_each_set_bit(id, &reg, BITS_PER_LONG) {
+ for_each_set_bit(id, &reg, 32) {
struct host1x_syncpt *syncpt =
- host->syncpt + (i * BITS_PER_LONG + id);
+ host->syncpt + (i * 32 + id);
host1x_intr_syncpt_handle(syncpt);
}
}
@@ -117,17 +117,17 @@ static void _host1x_intr_set_syncpt_threshold(struct host1x *host,
static void _host1x_intr_enable_syncpt_intr(struct host1x *host,
unsigned int id)
{
- host1x_sync_writel(host, BIT_MASK(id),
- HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(BIT_WORD(id)));
+ host1x_sync_writel(host, BIT(id % 32),
+ HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id / 32));
}
static void _host1x_intr_disable_syncpt_intr(struct host1x *host,
unsigned int id)
{
- host1x_sync_writel(host, BIT_MASK(id),
- HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(BIT_WORD(id)));
- host1x_sync_writel(host, BIT_MASK(id),
- HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(BIT_WORD(id)));
+ host1x_sync_writel(host, BIT(id % 32),
+ HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id / 32));
+ host1x_sync_writel(host, BIT(id % 32),
+ HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id / 32));
}
static int _host1x_free_syncpt_irq(struct host1x *host)
diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c
index c93f74fcce72..7b0270d60742 100644
--- a/drivers/gpu/host1x/hw/syncpt_hw.c
+++ b/drivers/gpu/host1x/hw/syncpt_hw.c
@@ -89,7 +89,7 @@ static int syncpt_cpu_incr(struct host1x_syncpt *sp)
host1x_syncpt_idle(sp))
return -EINVAL;
- host1x_sync_writel(host, BIT_MASK(sp->id),
+ host1x_sync_writel(host, BIT(sp->id % 32),
HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
wmb();
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index bee504406cfc..db509ab8874e 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -197,10 +197,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
}
phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
- if (!phys_addr) {
- err = -EINVAL;
- goto unpin;
- }
job->addr_phys[job->num_unpins] = phys_addr;
job->unpins[job->num_unpins].bo = reloc->target.bo;
@@ -225,10 +221,6 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
}
phys_addr = host1x_bo_pin(g->bo, &sgt);
- if (!phys_addr) {
- err = -EINVAL;
- goto unpin;
- }
if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) {
for_each_sg(sgt->sgl, sg, sgt->nents, j)