Commit 4a009085 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm/for-next' of git://anongit.freedesktop.org/tegra/linux into drm-next

These changes are mostly minor fixes to things introduced in 3.10. The
biggest chunk is updates to the host1x firewall which checks job
submissions from userspace and wasn't working properly. All other
patches are mostly one-liners. Nothing new or too exciting this time
around.

* 'drm/for-next' of git://anongit.freedesktop.org/tegra/linux:
  gpu: host1x: Rework CPU syncpoint increment
  gpu: host1x: Fix client_managed type
  gpu: host1x: Fix memory access in syncpt request
  gpu: host1x: Copy gathers before verification
  gpu: host1x: Don't reset firewall between gathers
  gpu: host1x: Check reloc table before usage
  gpu: host1x: Check INCR opcode correctly
  drm/tegra: Remove DRIVER_BUS_PLATFORM from driver_features
  drm/tegra: Fix return value
  drm/tegra: Include header drm/drm.h
  MAINTAINERS: Update Tegra DRM entry
  drm/tegra: fix error return code in gr2d_submit()
  drm/tegra: fix missing unlock on error
  drm/tegra: Honor pixel-format changes
  drm/tegra: Explicitly set irq_enabled
  drm/tegra: Don't disable unused planes
parents c0a60802 ebae30b1
...@@ -2697,12 +2697,14 @@ F: include/drm/exynos* ...@@ -2697,12 +2697,14 @@ F: include/drm/exynos*
F: include/uapi/drm/exynos* F: include/uapi/drm/exynos*
DRM DRIVERS FOR NVIDIA TEGRA DRM DRIVERS FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@avionic-design.de> M: Thierry Reding <thierry.reding@gmail.com>
M: Terje Bergström <tbergstrom@nvidia.com>
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
L: linux-tegra@vger.kernel.org L: linux-tegra@vger.kernel.org
T: git git://gitorious.org/thierryreding/linux.git T: git git://anongit.freedesktop.org/tegra/linux.git
S: Maintained S: Maintained
F: drivers/gpu/drm/tegra/ F: drivers/gpu/host1x/
F: include/uapi/drm/tegra_drm.h
F: Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt F: Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
DSBR100 USB FM RADIO DRIVER DSBR100 USB FM RADIO DRIVER
......
...@@ -73,7 +73,7 @@ struct host1x_syncpt_ops { ...@@ -73,7 +73,7 @@ struct host1x_syncpt_ops {
void (*restore_wait_base)(struct host1x_syncpt *syncpt); void (*restore_wait_base)(struct host1x_syncpt *syncpt);
void (*load_wait_base)(struct host1x_syncpt *syncpt); void (*load_wait_base)(struct host1x_syncpt *syncpt);
u32 (*load)(struct host1x_syncpt *syncpt); u32 (*load)(struct host1x_syncpt *syncpt);
void (*cpu_incr)(struct host1x_syncpt *syncpt); int (*cpu_incr)(struct host1x_syncpt *syncpt);
int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr); int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr);
}; };
...@@ -157,10 +157,10 @@ static inline u32 host1x_hw_syncpt_load(struct host1x *host, ...@@ -157,10 +157,10 @@ static inline u32 host1x_hw_syncpt_load(struct host1x *host,
return host->syncpt_op->load(sp); return host->syncpt_op->load(sp);
} }
static inline void host1x_hw_syncpt_cpu_incr(struct host1x *host, static inline int host1x_hw_syncpt_cpu_incr(struct host1x *host,
struct host1x_syncpt *sp) struct host1x_syncpt *sp)
{ {
host->syncpt_op->cpu_incr(sp); return host->syncpt_op->cpu_incr(sp);
} }
static inline int host1x_hw_syncpt_patch_wait(struct host1x *host, static inline int host1x_hw_syncpt_patch_wait(struct host1x *host,
......
...@@ -79,6 +79,9 @@ static int tegra_plane_disable(struct drm_plane *plane) ...@@ -79,6 +79,9 @@ static int tegra_plane_disable(struct drm_plane *plane)
struct tegra_plane *p = to_tegra_plane(plane); struct tegra_plane *p = to_tegra_plane(plane);
unsigned long value; unsigned long value;
if (!plane->crtc)
return 0;
value = WINDOW_A_SELECT << p->index; value = WINDOW_A_SELECT << p->index;
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER);
...@@ -140,6 +143,7 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) ...@@ -140,6 +143,7 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
struct drm_framebuffer *fb) struct drm_framebuffer *fb)
{ {
unsigned int format = tegra_dc_format(fb->pixel_format);
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
unsigned long value; unsigned long value;
...@@ -150,6 +154,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, ...@@ -150,6 +154,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR); tegra_dc_writel(dc, bo->paddr + value, DC_WINBUF_START_ADDR);
tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE);
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
value = GENERAL_UPDATE | WIN_A_UPDATE; value = GENERAL_UPDATE | WIN_A_UPDATE;
tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
......
...@@ -148,6 +148,7 @@ int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm) ...@@ -148,6 +148,7 @@ int host1x_drm_init(struct host1x_drm *host1x, struct drm_device *drm)
dev_err(host1x->dev, dev_err(host1x->dev,
"DRM setup failed for %s: %d\n", "DRM setup failed for %s: %d\n",
dev_name(client->dev), err); dev_name(client->dev), err);
mutex_unlock(&host1x->clients_lock);
return err; return err;
} }
} }
...@@ -175,6 +176,7 @@ int host1x_drm_exit(struct host1x_drm *host1x) ...@@ -175,6 +176,7 @@ int host1x_drm_exit(struct host1x_drm *host1x)
dev_err(host1x->dev, dev_err(host1x->dev,
"DRM cleanup failed for %s: %d\n", "DRM cleanup failed for %s: %d\n",
dev_name(client->dev), err); dev_name(client->dev), err);
mutex_unlock(&host1x->clients_lock);
return err; return err;
} }
} }
...@@ -257,6 +259,13 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) ...@@ -257,6 +259,13 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
if (err < 0) if (err < 0)
return err; return err;
/*
* We don't use the drm_irq_install() helpers provided by the DRM
* core, so we need to set this manually in order to allow the
* DRM_IOCTL_WAIT_VBLANK to operate correctly.
*/
drm->irq_enabled = 1;
err = drm_vblank_init(drm, drm->mode_config.num_crtc); err = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (err < 0) if (err < 0)
return err; return err;
...@@ -378,8 +387,7 @@ static int tegra_syncpt_incr(struct drm_device *drm, void *data, ...@@ -378,8 +387,7 @@ static int tegra_syncpt_incr(struct drm_device *drm, void *data,
if (!sp) if (!sp)
return -EINVAL; return -EINVAL;
host1x_syncpt_incr(sp); return host1x_syncpt_incr(sp);
return 0;
} }
static int tegra_syncpt_wait(struct drm_device *drm, void *data, static int tegra_syncpt_wait(struct drm_device *drm, void *data,
...@@ -605,7 +613,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor) ...@@ -605,7 +613,7 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
#endif #endif
struct drm_driver tegra_drm_driver = { struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM, .driver_features = DRIVER_MODESET | DRIVER_GEM,
.load = tegra_drm_load, .load = tegra_drm_load,
.unload = tegra_drm_unload, .unload = tegra_drm_unload,
.open = tegra_drm_open, .open = tegra_drm_open,
......
...@@ -84,7 +84,7 @@ static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm, ...@@ -84,7 +84,7 @@ static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm,
gem = drm_gem_object_lookup(drm, file, handle); gem = drm_gem_object_lookup(drm, file, handle);
if (!gem) if (!gem)
return 0; return NULL;
mutex_lock(&drm->struct_mutex); mutex_lock(&drm->struct_mutex);
drm_gem_object_unreference(gem); drm_gem_object_unreference(gem);
...@@ -135,8 +135,10 @@ static int gr2d_submit(struct host1x_drm_context *context, ...@@ -135,8 +135,10 @@ static int gr2d_submit(struct host1x_drm_context *context,
goto fail; goto fail;
bo = host1x_bo_lookup(drm, file, cmdbuf.handle); bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
if (!bo) if (!bo) {
err = -ENOENT;
goto fail; goto fail;
}
host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset);
num_cmdbufs--; num_cmdbufs--;
...@@ -158,9 +160,11 @@ static int gr2d_submit(struct host1x_drm_context *context, ...@@ -158,9 +160,11 @@ static int gr2d_submit(struct host1x_drm_context *context,
reloc->cmdbuf = cmdbuf; reloc->cmdbuf = cmdbuf;
reloc->target = target; reloc->target = target;
if (!reloc->target || !reloc->cmdbuf) if (!reloc->target || !reloc->cmdbuf) {
err = -ENOENT;
goto fail; goto fail;
} }
}
err = copy_from_user(job->waitchk, waitchks, err = copy_from_user(job->waitchk, waitchks,
sizeof(*waitchks) * num_waitchks); sizeof(*waitchks) * num_waitchks);
...@@ -281,7 +285,7 @@ static int gr2d_probe(struct platform_device *pdev) ...@@ -281,7 +285,7 @@ static int gr2d_probe(struct platform_device *pdev)
if (!gr2d->channel) if (!gr2d->channel)
return -ENOMEM; return -ENOMEM;
*syncpts = host1x_syncpt_request(dev, 0); *syncpts = host1x_syncpt_request(dev, false);
if (!(*syncpts)) { if (!(*syncpts)) {
host1x_channel_free(gr2d->channel); host1x_channel_free(gr2d->channel);
return -ENOMEM; return -ENOMEM;
......
...@@ -44,7 +44,7 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr, ...@@ -44,7 +44,7 @@ static void cdma_timeout_cpu_incr(struct host1x_cdma *cdma, u32 getptr,
u32 i; u32 i;
for (i = 0; i < syncpt_incrs; i++) for (i = 0; i < syncpt_incrs; i++)
host1x_syncpt_cpu_incr(cdma->timeout.syncpt); host1x_syncpt_incr(cdma->timeout.syncpt);
/* after CPU incr, ensure shadow is up to date */ /* after CPU incr, ensure shadow is up to date */
host1x_syncpt_load(cdma->timeout.syncpt); host1x_syncpt_load(cdma->timeout.syncpt);
......
...@@ -77,21 +77,19 @@ static u32 syncpt_load(struct host1x_syncpt *sp) ...@@ -77,21 +77,19 @@ static u32 syncpt_load(struct host1x_syncpt *sp)
* Write a cpu syncpoint increment to the hardware, without touching * Write a cpu syncpoint increment to the hardware, without touching
* the cache. * the cache.
*/ */
static void syncpt_cpu_incr(struct host1x_syncpt *sp) static int syncpt_cpu_incr(struct host1x_syncpt *sp)
{ {
struct host1x *host = sp->host; struct host1x *host = sp->host;
u32 reg_offset = sp->id / 32; u32 reg_offset = sp->id / 32;
if (!host1x_syncpt_client_managed(sp) && if (!host1x_syncpt_client_managed(sp) &&
host1x_syncpt_idle(sp)) { host1x_syncpt_idle(sp))
dev_err(host->dev, "Trying to increment syncpoint id %d beyond max\n", return -EINVAL;
sp->id);
host1x_debug_dump(sp->host);
return;
}
host1x_sync_writel(host, BIT_MASK(sp->id), host1x_sync_writel(host, BIT_MASK(sp->id),
HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset)); HOST1X_SYNC_SYNCPT_CPU_INCR(reg_offset));
wmb(); wmb();
return 0;
} }
/* remove a wait pointed to by patch_addr */ /* remove a wait pointed to by patch_addr */
......
...@@ -228,17 +228,15 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) ...@@ -228,17 +228,15 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
void *cmdbuf_page_addr = NULL; void *cmdbuf_page_addr = NULL;
/* pin & patch the relocs for one gather */ /* pin & patch the relocs for one gather */
while (i < job->num_relocs) { for (i = 0; i < job->num_relocs; i++) {
struct host1x_reloc *reloc = &job->relocarray[i]; struct host1x_reloc *reloc = &job->relocarray[i];
u32 reloc_addr = (job->reloc_addr_phys[i] + u32 reloc_addr = (job->reloc_addr_phys[i] +
reloc->target_offset) >> reloc->shift; reloc->target_offset) >> reloc->shift;
u32 *target; u32 *target;
/* skip all other gathers */ /* skip all other gathers */
if (!(reloc->cmdbuf && cmdbuf == reloc->cmdbuf)) { if (cmdbuf != reloc->cmdbuf)
i++;
continue; continue;
}
if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) { if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) {
if (cmdbuf_page_addr) if (cmdbuf_page_addr)
...@@ -257,9 +255,6 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) ...@@ -257,9 +255,6 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK); target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK);
*target = reloc_addr; *target = reloc_addr;
/* mark this gather as handled */
reloc->cmdbuf = 0;
} }
if (cmdbuf_page_addr) if (cmdbuf_page_addr)
...@@ -268,15 +263,15 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) ...@@ -268,15 +263,15 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
return 0; return 0;
} }
static int check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
unsigned int offset) unsigned int offset)
{ {
offset *= sizeof(u32); offset *= sizeof(u32);
if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset) if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset)
return -EINVAL; return false;
return 0; return true;
} }
struct host1x_firewall { struct host1x_firewall {
...@@ -307,10 +302,10 @@ static int check_mask(struct host1x_firewall *fw) ...@@ -307,10 +302,10 @@ static int check_mask(struct host1x_firewall *fw)
if (mask & 1) { if (mask & 1) {
if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) {
bool bad_reloc = check_reloc(fw->reloc, if (!fw->num_relocs)
fw->cmdbuf_id, return -EINVAL;
fw->offset); if (!check_reloc(fw->reloc, fw->cmdbuf_id,
if (!fw->num_relocs || bad_reloc) fw->offset))
return -EINVAL; return -EINVAL;
fw->reloc++; fw->reloc++;
fw->num_relocs--; fw->num_relocs--;
...@@ -330,14 +325,14 @@ static int check_incr(struct host1x_firewall *fw) ...@@ -330,14 +325,14 @@ static int check_incr(struct host1x_firewall *fw)
u32 count = fw->count; u32 count = fw->count;
u32 reg = fw->reg; u32 reg = fw->reg;
while (fw) { while (count) {
if (fw->words == 0) if (fw->words == 0)
return -EINVAL; return -EINVAL;
if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) { if (fw->job->is_addr_reg(fw->dev, fw->class, reg)) {
bool bad_reloc = check_reloc(fw->reloc, fw->cmdbuf_id, if (!fw->num_relocs)
fw->offset); return -EINVAL;
if (!fw->num_relocs || bad_reloc) if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset))
return -EINVAL; return -EINVAL;
fw->reloc++; fw->reloc++;
fw->num_relocs--; fw->num_relocs--;
...@@ -361,9 +356,9 @@ static int check_nonincr(struct host1x_firewall *fw) ...@@ -361,9 +356,9 @@ static int check_nonincr(struct host1x_firewall *fw)
return -EINVAL; return -EINVAL;
if (is_addr_reg) { if (is_addr_reg) {
bool bad_reloc = check_reloc(fw->reloc, fw->cmdbuf_id, if (!fw->num_relocs)
fw->offset); return -EINVAL;
if (!fw->num_relocs || bad_reloc) if (!check_reloc(fw->reloc, fw->cmdbuf_id, fw->offset))
return -EINVAL; return -EINVAL;
fw->reloc++; fw->reloc++;
fw->num_relocs--; fw->num_relocs--;
...@@ -376,69 +371,58 @@ static int check_nonincr(struct host1x_firewall *fw) ...@@ -376,69 +371,58 @@ static int check_nonincr(struct host1x_firewall *fw)
return 0; return 0;
} }
static int validate(struct host1x_job *job, struct device *dev, static int validate(struct host1x_firewall *fw, struct host1x_job_gather *g)
struct host1x_job_gather *g)
{ {
u32 *cmdbuf_base; u32 *cmdbuf_base = (u32 *)fw->job->gather_copy_mapped +
(g->offset / sizeof(u32));
int err = 0; int err = 0;
struct host1x_firewall fw;
fw.job = job; if (!fw->job->is_addr_reg)
fw.dev = dev;
fw.reloc = job->relocarray;
fw.num_relocs = job->num_relocs;
fw.cmdbuf_id = g->bo;
fw.offset = 0;
fw.class = 0;
if (!job->is_addr_reg)
return 0; return 0;
cmdbuf_base = host1x_bo_mmap(g->bo); fw->words = g->words;
if (!cmdbuf_base) fw->cmdbuf_id = g->bo;
return -ENOMEM; fw->offset = 0;
fw.words = g->words; while (fw->words && !err) {
while (fw.words && !err) { u32 word = cmdbuf_base[fw->offset];
u32 word = cmdbuf_base[fw.offset];
u32 opcode = (word & 0xf0000000) >> 28; u32 opcode = (word & 0xf0000000) >> 28;
fw.mask = 0; fw->mask = 0;
fw.reg = 0; fw->reg = 0;
fw.count = 0; fw->count = 0;
fw.words--; fw->words--;
fw.offset++; fw->offset++;
switch (opcode) { switch (opcode) {
case 0: case 0:
fw.class = word >> 6 & 0x3ff; fw->class = word >> 6 & 0x3ff;
fw.mask = word & 0x3f; fw->mask = word & 0x3f;
fw.reg = word >> 16 & 0xfff; fw->reg = word >> 16 & 0xfff;
err = check_mask(&fw); err = check_mask(fw);
if (err) if (err)
goto out; goto out;
break; break;
case 1: case 1:
fw.reg = word >> 16 & 0xfff; fw->reg = word >> 16 & 0xfff;
fw.count = word & 0xffff; fw->count = word & 0xffff;
err = check_incr(&fw); err = check_incr(fw);
if (err) if (err)
goto out; goto out;
break; break;
case 2: case 2:
fw.reg = word >> 16 & 0xfff; fw->reg = word >> 16 & 0xfff;
fw.count = word & 0xffff; fw->count = word & 0xffff;
err = check_nonincr(&fw); err = check_nonincr(fw);
if (err) if (err)
goto out; goto out;
break; break;
case 3: case 3:
fw.mask = word & 0xffff; fw->mask = word & 0xffff;
fw.reg = word >> 16 & 0xfff; fw->reg = word >> 16 & 0xfff;
err = check_mask(&fw); err = check_mask(fw);
if (err) if (err)
goto out; goto out;
break; break;
...@@ -453,21 +437,26 @@ static int validate(struct host1x_job *job, struct device *dev, ...@@ -453,21 +437,26 @@ static int validate(struct host1x_job *job, struct device *dev,
} }
/* No relocs should remain at this point */ /* No relocs should remain at this point */
if (fw.num_relocs) if (fw->num_relocs)
err = -EINVAL; err = -EINVAL;
out: out:
host1x_bo_munmap(g->bo, cmdbuf_base);
return err; return err;
} }
static inline int copy_gathers(struct host1x_job *job, struct device *dev) static inline int copy_gathers(struct host1x_job *job, struct device *dev)
{ {
struct host1x_firewall fw;
size_t size = 0; size_t size = 0;
size_t offset = 0; size_t offset = 0;
int i; int i;
fw.job = job;
fw.dev = dev;
fw.reloc = job->relocarray;
fw.num_relocs = job->num_relocs;
fw.class = 0;
for (i = 0; i < job->num_gathers; i++) { for (i = 0; i < job->num_gathers; i++) {
struct host1x_job_gather *g = &job->gathers[i]; struct host1x_job_gather *g = &job->gathers[i];
size += g->words * sizeof(u32); size += g->words * sizeof(u32);
...@@ -488,14 +477,19 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev) ...@@ -488,14 +477,19 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
struct host1x_job_gather *g = &job->gathers[i]; struct host1x_job_gather *g = &job->gathers[i];
void *gather; void *gather;
/* Copy the gather */
gather = host1x_bo_mmap(g->bo); gather = host1x_bo_mmap(g->bo);
memcpy(job->gather_copy_mapped + offset, gather + g->offset, memcpy(job->gather_copy_mapped + offset, gather + g->offset,
g->words * sizeof(u32)); g->words * sizeof(u32));
host1x_bo_munmap(g->bo, gather); host1x_bo_munmap(g->bo, gather);
/* Store the location in the buffer */
g->base = job->gather_copy; g->base = job->gather_copy;
g->offset = offset; g->offset = offset;
g->bo = NULL;
/* Validate the job */
if (validate(&fw, g))
return -EINVAL;
offset += g->words * sizeof(u32); offset += g->words * sizeof(u32);
} }
...@@ -540,20 +534,11 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev) ...@@ -540,20 +534,11 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
if (job->gathers[j].bo == g->bo) if (job->gathers[j].bo == g->bo)
job->gathers[j].handled = true; job->gathers[j].handled = true;
err = 0;
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
err = validate(job, dev, g);
if (err)
dev_err(dev, "Job invalid (err=%d)\n", err);
if (!err)
err = do_relocs(job, g->bo); err = do_relocs(job, g->bo);
if (err)
break;
if (!err)
err = do_waitchks(job, host, g->bo); err = do_waitchks(job, host, g->bo);
if (err) if (err)
break; break;
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host, static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
struct device *dev, struct device *dev,
int client_managed) bool client_managed)
{ {
int i; int i;
struct host1x_syncpt *sp = host->syncpt; struct host1x_syncpt *sp = host->syncpt;
...@@ -40,7 +40,8 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host, ...@@ -40,7 +40,8 @@ static struct host1x_syncpt *_host1x_syncpt_alloc(struct host1x *host,
for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++) for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++)
; ;
if (sp->dev)
if (i >= host->info->nb_pts)
return NULL; return NULL;
name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id, name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,
...@@ -127,23 +128,12 @@ u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp) ...@@ -127,23 +128,12 @@ u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp)
return val; return val;
} }
/*
* Write a cpu syncpoint increment to the hardware, without touching
* the cache. Caller is responsible for host being powered.
*/
void host1x_syncpt_cpu_incr(struct host1x_syncpt *sp)
{
host1x_hw_syncpt_cpu_incr(sp->host, sp);
}
/* /*
* Increment syncpoint value from cpu, updating cache * Increment syncpoint value from cpu, updating cache
*/ */
void host1x_syncpt_incr(struct host1x_syncpt *sp) int host1x_syncpt_incr(struct host1x_syncpt *sp)
{ {
if (host1x_syncpt_client_managed(sp)) return host1x_hw_syncpt_cpu_incr(sp->host, sp);
host1x_syncpt_incr_max(sp, 1);
host1x_syncpt_cpu_incr(sp);
} }
/* /*
...@@ -331,7 +321,7 @@ int host1x_syncpt_init(struct host1x *host) ...@@ -331,7 +321,7 @@ int host1x_syncpt_init(struct host1x *host)
host1x_syncpt_restore(host); host1x_syncpt_restore(host);
/* Allocate sync point to use for clearing waits for expired fences */ /* Allocate sync point to use for clearing waits for expired fences */
host->nop_sp = _host1x_syncpt_alloc(host, NULL, 0); host->nop_sp = _host1x_syncpt_alloc(host, NULL, false);
if (!host->nop_sp) if (!host->nop_sp)
return -ENOMEM; return -ENOMEM;
...@@ -339,7 +329,7 @@ int host1x_syncpt_init(struct host1x *host) ...@@ -339,7 +329,7 @@ int host1x_syncpt_init(struct host1x *host)
} }
struct host1x_syncpt *host1x_syncpt_request(struct device *dev, struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
int client_managed) bool client_managed)
{ {
struct host1x *host = dev_get_drvdata(dev->parent); struct host1x *host = dev_get_drvdata(dev->parent);
return _host1x_syncpt_alloc(host, dev, client_managed); return _host1x_syncpt_alloc(host, dev, client_managed);
...@@ -353,7 +343,7 @@ void host1x_syncpt_free(struct host1x_syncpt *sp) ...@@ -353,7 +343,7 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
kfree(sp->name); kfree(sp->name);
sp->dev = NULL; sp->dev = NULL;
sp->name = NULL; sp->name = NULL;
sp->client_managed = 0; sp->client_managed = false;
} }
void host1x_syncpt_deinit(struct host1x *host) void host1x_syncpt_deinit(struct host1x *host)
......
...@@ -36,7 +36,7 @@ struct host1x_syncpt { ...@@ -36,7 +36,7 @@ struct host1x_syncpt {
atomic_t max_val; atomic_t max_val;
u32 base_val; u32 base_val;
const char *name; const char *name;
int client_managed; bool client_managed;
struct host1x *host; struct host1x *host;
struct device *dev; struct device *dev;
...@@ -94,7 +94,7 @@ static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real) ...@@ -94,7 +94,7 @@ static inline bool host1x_syncpt_check_max(struct host1x_syncpt *sp, u32 real)
} }
/* Return true if sync point is client managed. */ /* Return true if sync point is client managed. */
static inline int host1x_syncpt_client_managed(struct host1x_syncpt *sp) static inline bool host1x_syncpt_client_managed(struct host1x_syncpt *sp)
{ {
return sp->client_managed; return sp->client_managed;
} }
...@@ -115,9 +115,6 @@ static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp) ...@@ -115,9 +115,6 @@ static inline bool host1x_syncpt_idle(struct host1x_syncpt *sp)
/* Return pointer to struct denoting sync point id. */ /* Return pointer to struct denoting sync point id. */
struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id); struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
/* Request incrementing a sync point. */
void host1x_syncpt_cpu_incr(struct host1x_syncpt *sp);
/* Load current value from hardware to the shadow register. */ /* Load current value from hardware to the shadow register. */
u32 host1x_syncpt_load(struct host1x_syncpt *sp); u32 host1x_syncpt_load(struct host1x_syncpt *sp);
...@@ -133,8 +130,8 @@ void host1x_syncpt_restore(struct host1x *host); ...@@ -133,8 +130,8 @@ void host1x_syncpt_restore(struct host1x *host);
/* Read current wait base value into shadow register and return it. */ /* Read current wait base value into shadow register and return it. */
u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp); u32 host1x_syncpt_load_wait_base(struct host1x_syncpt *sp);
/* Increment sync point and its max. */ /* Request incrementing a sync point. */
void host1x_syncpt_incr(struct host1x_syncpt *sp); int host1x_syncpt_incr(struct host1x_syncpt *sp);
/* Indicate future operations by incrementing the sync point max. */ /* Indicate future operations by incrementing the sync point max. */
u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
...@@ -157,7 +154,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp); ...@@ -157,7 +154,7 @@ u32 host1x_syncpt_id(struct host1x_syncpt *sp);
/* Allocate a sync point for a device. */ /* Allocate a sync point for a device. */
struct host1x_syncpt *host1x_syncpt_request(struct device *dev, struct host1x_syncpt *host1x_syncpt_request(struct device *dev,
int client_managed); bool client_managed);
/* Free a sync point. */ /* Free a sync point. */
void host1x_syncpt_free(struct host1x_syncpt *sp); void host1x_syncpt_free(struct host1x_syncpt *sp);
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#ifndef _UAPI_TEGRA_DRM_H_ #ifndef _UAPI_TEGRA_DRM_H_
#define _UAPI_TEGRA_DRM_H_ #define _UAPI_TEGRA_DRM_H_
#include <drm/drm.h>
struct drm_tegra_gem_create { struct drm_tegra_gem_create {
__u64 size; __u64 size;
__u32 flags; __u32 flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment