Skip to content

Commit

Permalink
gpu: host1x: Remove wait check support
Browse files Browse the repository at this point in the history
The job submission userspace ABI doesn't support this and there are no
plans to implement it, so all of this code is dead and can be removed.

Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
  • Loading branch information
thierryreding committed May 18, 2018
1 parent 2f8a6da commit 24c94e1
Show file tree
Hide file tree
Showing 9 changed files with 14 additions and 234 deletions.
62 changes: 2 additions & 60 deletions drivers/gpu/drm/tegra/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,46 +321,14 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
return 0;
}

static int host1x_waitchk_copy_from_user(struct host1x_waitchk *dest,
struct drm_tegra_waitchk __user *src,
struct drm_file *file)
{
u32 cmdbuf;
int err;

err = get_user(cmdbuf, &src->handle);
if (err < 0)
return err;

err = get_user(dest->offset, &src->offset);
if (err < 0)
return err;

err = get_user(dest->syncpt_id, &src->syncpt);
if (err < 0)
return err;

err = get_user(dest->thresh, &src->thresh);
if (err < 0)
return err;

dest->bo = host1x_bo_lookup(file, cmdbuf);
if (!dest->bo)
return -ENOENT;

return 0;
}

int tegra_drm_submit(struct tegra_drm_context *context,
struct drm_tegra_submit *args, struct drm_device *drm,
struct drm_file *file)
{
unsigned int num_cmdbufs = args->num_cmdbufs;
unsigned int num_relocs = args->num_relocs;
unsigned int num_waitchks = args->num_waitchks;
struct drm_tegra_cmdbuf __user *user_cmdbufs;
struct drm_tegra_reloc __user *user_relocs;
struct drm_tegra_waitchk __user *user_waitchks;
struct drm_tegra_syncpt __user *user_syncpt;
struct drm_tegra_syncpt syncpt;
struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
Expand All @@ -372,7 +340,6 @@ int tegra_drm_submit(struct tegra_drm_context *context,

user_cmdbufs = u64_to_user_ptr(args->cmdbufs);
user_relocs = u64_to_user_ptr(args->relocs);
user_waitchks = u64_to_user_ptr(args->waitchks);
user_syncpt = u64_to_user_ptr(args->syncpts);

/* We don't yet support other than one syncpt_incr struct per submit */
Expand All @@ -384,12 +351,11 @@ int tegra_drm_submit(struct tegra_drm_context *context,
return -EINVAL;

job = host1x_job_alloc(context->channel, args->num_cmdbufs,
args->num_relocs, args->num_waitchks);
args->num_relocs);
if (!job)
return -ENOMEM;

job->num_relocs = args->num_relocs;
job->num_waitchk = args->num_waitchks;
job->client = (u32)args->context;
job->class = context->client->base.class;
job->serialize = true;
Expand All @@ -398,7 +364,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
* Track referenced BOs so that they can be unreferenced after the
* submission is complete.
*/
num_refs = num_cmdbufs + num_relocs * 2 + num_waitchks;
num_refs = num_cmdbufs + num_relocs * 2;

refs = kmalloc_array(num_refs, sizeof(*refs), GFP_KERNEL);
if (!refs) {
Expand Down Expand Up @@ -489,30 +455,6 @@ int tegra_drm_submit(struct tegra_drm_context *context,
}
}

/* copy and resolve waitchks from submit */
while (num_waitchks--) {
struct host1x_waitchk *wait = &job->waitchk[num_waitchks];
struct tegra_bo *obj;

err = host1x_waitchk_copy_from_user(
wait, &user_waitchks[num_waitchks], file);
if (err < 0)
goto fail;

obj = host1x_to_tegra_bo(wait->bo);
refs[num_refs++] = &obj->gem;

/*
* The unaligned offset will cause an unaligned write during
* of the waitchks patching, corrupting the commands stream.
*/
if (wait->offset & 3 ||
wait->offset >= obj->gem.size) {
err = -EINVAL;
goto fail;
}
}

if (copy_from_user(&syncpt, user_syncpt, sizeof(syncpt))) {
err = -EFAULT;
goto fail;
Expand Down
8 changes: 0 additions & 8 deletions drivers/gpu/host1x/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ struct host1x_syncpt_ops {
void (*load_wait_base)(struct host1x_syncpt *syncpt);
u32 (*load)(struct host1x_syncpt *syncpt);
int (*cpu_incr)(struct host1x_syncpt *syncpt);
int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr);
void (*assign_to_channel)(struct host1x_syncpt *syncpt,
struct host1x_channel *channel);
void (*enable_protection)(struct host1x *host);
Expand Down Expand Up @@ -183,13 +182,6 @@ static inline int host1x_hw_syncpt_cpu_incr(struct host1x *host,
return host->syncpt_op->cpu_incr(sp);
}

static inline int host1x_hw_syncpt_patch_wait(struct host1x *host,
struct host1x_syncpt *sp,
void *patch_addr)
{
return host->syncpt_op->patch_wait(sp, patch_addr);
}

static inline void host1x_hw_syncpt_assign_to_channel(
struct host1x *host, struct host1x_syncpt *sp,
struct host1x_channel *ch)
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/host1x/hw/channel_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ static int channel_submit(struct host1x_job *job)
sp = host->syncpt + job->syncpt_id;
trace_host1x_channel_submit(dev_name(ch->dev),
job->num_gathers, job->num_relocs,
job->num_waitchk, job->syncpt_id,
job->syncpt_incrs);
job->syncpt_id, job->syncpt_incrs);

/* before error checks, return current max */
prev_max = job->syncpt_end = host1x_syncpt_read_max(sp);
Expand Down
11 changes: 0 additions & 11 deletions drivers/gpu/host1x/hw/syncpt_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,6 @@ static int syncpt_cpu_incr(struct host1x_syncpt *sp)
return 0;
}

/* remove a wait pointed to by patch_addr */
static int syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
{
u32 override = host1x_class_host_wait_syncpt(HOST1X_SYNCPT_RESERVED, 0);

*((u32 *)patch_addr) = override;

return 0;
}

/**
* syncpt_assign_to_channel() - Assign syncpoint to channel
* @sp: syncpoint
Expand Down Expand Up @@ -156,7 +146,6 @@ static const struct host1x_syncpt_ops host1x_syncpt_ops = {
.load_wait_base = syncpt_read_wait_base,
.load = syncpt_load,
.cpu_incr = syncpt_cpu_incr,
.patch_wait = syncpt_patch_wait,
.assign_to_channel = syncpt_assign_to_channel,
.enable_protection = syncpt_enable_protection,
};
124 changes: 3 additions & 121 deletions drivers/gpu/host1x/job.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
#define HOST1X_WAIT_SYNCPT_OFFSET 0x8

struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
u32 num_cmdbufs, u32 num_relocs,
u32 num_waitchks)
u32 num_cmdbufs, u32 num_relocs)
{
struct host1x_job *job = NULL;
unsigned int num_unpins = num_cmdbufs + num_relocs;
Expand All @@ -46,7 +45,6 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
total = sizeof(struct host1x_job) +
(u64)num_relocs * sizeof(struct host1x_reloc) +
(u64)num_unpins * sizeof(struct host1x_job_unpin_data) +
(u64)num_waitchks * sizeof(struct host1x_waitchk) +
(u64)num_cmdbufs * sizeof(struct host1x_job_gather) +
(u64)num_unpins * sizeof(dma_addr_t) +
(u64)num_unpins * sizeof(u32 *);
Expand All @@ -66,8 +64,6 @@ struct host1x_job *host1x_job_alloc(struct host1x_channel *ch,
mem += num_relocs * sizeof(struct host1x_reloc);
job->unpins = num_unpins ? mem : NULL;
mem += num_unpins * sizeof(struct host1x_job_unpin_data);
job->waitchk = num_waitchks ? mem : NULL;
mem += num_waitchks * sizeof(struct host1x_waitchk);
job->gathers = num_cmdbufs ? mem : NULL;
mem += num_cmdbufs * sizeof(struct host1x_job_gather);
job->addr_phys = num_unpins ? mem : NULL;
Expand Down Expand Up @@ -111,73 +107,6 @@ void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *bo,
}
EXPORT_SYMBOL(host1x_job_add_gather);

/*
* NULL an already satisfied WAIT_SYNCPT host method, by patching its
* args in the command stream. The method data is changed to reference
* a reserved (never given out or incr) HOST1X_SYNCPT_RESERVED syncpt
* with a matching threshold value of 0, so is guaranteed to be popped
* by the host HW.
*/
static void host1x_syncpt_patch_offset(struct host1x_syncpt *sp,
struct host1x_bo *h, u32 offset)
{
void *patch_addr = NULL;

/* patch the wait */
patch_addr = host1x_bo_kmap(h, offset >> PAGE_SHIFT);
if (patch_addr) {
host1x_syncpt_patch_wait(sp,
patch_addr + (offset & ~PAGE_MASK));
host1x_bo_kunmap(h, offset >> PAGE_SHIFT, patch_addr);
} else
pr_err("Could not map cmdbuf for wait check\n");
}

/*
* Check driver supplied waitchk structs for syncpt thresholds
* that have already been satisfied and NULL the comparison (to
* avoid a wrap condition in the HW).
*/
static int do_waitchks(struct host1x_job *job, struct host1x *host,
struct host1x_job_gather *g)
{
struct host1x_bo *patch = g->bo;
int i;

/* compare syncpt vs wait threshold */
for (i = 0; i < job->num_waitchk; i++) {
struct host1x_waitchk *wait = &job->waitchk[i];
struct host1x_syncpt *sp =
host1x_syncpt_get(host, wait->syncpt_id);

/* validate syncpt id */
if (wait->syncpt_id > host1x_syncpt_nb_pts(host))
continue;

/* skip all other gathers */
if (patch != wait->bo)
continue;

trace_host1x_syncpt_wait_check(wait->bo, wait->offset,
wait->syncpt_id, wait->thresh,
host1x_syncpt_read_min(sp));

if (host1x_syncpt_is_expired(sp, wait->thresh)) {
dev_dbg(host->dev,
"drop WAIT id %u (%s) thresh 0x%x, min 0x%x\n",
wait->syncpt_id, sp->name, wait->thresh,
host1x_syncpt_read_min(sp));

host1x_syncpt_patch_offset(sp, patch,
g->offset + wait->offset);
}

wait->bo = NULL;
}

return 0;
}

static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
{
unsigned int i;
Expand Down Expand Up @@ -331,27 +260,13 @@ static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
return true;
}

static bool check_wait(struct host1x_waitchk *wait, struct host1x_bo *cmdbuf,
unsigned int offset)
{
offset *= sizeof(u32);

if (wait->bo != cmdbuf || wait->offset != offset)
return false;

return true;
}

struct host1x_firewall {
struct host1x_job *job;
struct device *dev;

unsigned int num_relocs;
struct host1x_reloc *reloc;

unsigned int num_waitchks;
struct host1x_waitchk *waitchk;

struct host1x_bo *cmdbuf;
unsigned int offset;

Expand All @@ -378,20 +293,6 @@ static int check_register(struct host1x_firewall *fw, unsigned long offset)
fw->reloc++;
}

if (offset == HOST1X_WAIT_SYNCPT_OFFSET) {
if (fw->class != HOST1X_CLASS_HOST1X)
return -EINVAL;

if (!fw->num_waitchks)
return -EINVAL;

if (!check_wait(fw->waitchk, fw->cmdbuf, fw->offset))
return -EINVAL;

fw->num_waitchks--;
fw->waitchk++;
}

return 0;
}

Expand Down Expand Up @@ -556,8 +457,6 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
fw.dev = dev;
fw.reloc = job->relocarray;
fw.num_relocs = job->num_relocs;
fw.waitchk = job->waitchk;
fw.num_waitchks = job->num_waitchk;
fw.class = job->class;

for (i = 0; i < job->num_gathers; i++) {
Expand Down Expand Up @@ -604,8 +503,8 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
offset += g->words * sizeof(u32);
}

/* No relocs and waitchks should remain at this point */
if (fw.num_relocs || fw.num_waitchks)
/* No relocs should remain at this point */
if (fw.num_relocs)
return -EINVAL;

return 0;
Expand All @@ -616,19 +515,6 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
int err;
unsigned int i, j;
struct host1x *host = dev_get_drvdata(dev->parent);
DECLARE_BITMAP(waitchk_mask, host1x_syncpt_nb_pts(host));

bitmap_zero(waitchk_mask, host1x_syncpt_nb_pts(host));
for (i = 0; i < job->num_waitchk; i++) {
u32 syncpt_id = job->waitchk[i].syncpt_id;

if (syncpt_id < host1x_syncpt_nb_pts(host))
set_bit(syncpt_id, waitchk_mask);
}

/* get current syncpt values for waitchk */
for_each_set_bit(i, waitchk_mask, host1x_syncpt_nb_pts(host))
host1x_syncpt_load(host->syncpt + i);

/* pin memory */
err = pin_job(host, job);
Expand Down Expand Up @@ -663,10 +549,6 @@ int host1x_job_pin(struct host1x_job *job, struct device *dev)
err = do_relocs(job, g);
if (err)
break;

err = do_waitchks(job, host, g);
if (err)
break;
}

out:
Expand Down
6 changes: 0 additions & 6 deletions drivers/gpu/host1x/syncpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,6 @@ bool host1x_syncpt_is_expired(struct host1x_syncpt *sp, u32 thresh)
return (s32)(current_val - thresh) >= 0;
}

/* remove a wait pointed to by patch_addr */
int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
{
return host1x_hw_syncpt_patch_wait(sp->host, sp, patch_addr);
}

int host1x_syncpt_init(struct host1x *host)
{
struct host1x_syncpt_base *bases;
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/host1x/syncpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,4 @@ static inline int host1x_syncpt_is_valid(struct host1x_syncpt *sp)
return sp->id < host1x_syncpt_nb_pts(sp->host);
}

/* Patch a wait by replacing it with a wait for syncpt 0 value 0 */
int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr);

#endif
Loading

0 comments on commit 24c94e1

Please sign in to comment.