From 9592a4e6fce8204e9ada54ba00902e792199fec5 Mon Sep 17 00:00:00 2001 From: Deepak Nibade Date: Wed, 28 Oct 2015 16:13:14 +0530 Subject: gpu: nvgpu: IOCTL to set TSG timeslice Add new IOCTL NVGPU_IOCTL_TSG_SET_PRIORITY to allow setting timeslice for entire TSG Return error from channel specific IOCTL_CHANNEL_SET_PRIORITY if the channel is part of TSG Separate out API gk20a_channel_get_timescale_from_timeslice() to get timeslice_timeout and scale from timeslice period Use this API to get timeslice_timeout and scale for TSG and store it in tsg_gk20a structure Then trigger runlist update so that new timeslice values will be re-written to runlist for TSG Bug 200146615 Change-Id: I555467d034f81b372b31372f0835d72b1c159508 Signed-off-by: Deepak Nibade Reviewed-on: http://git-master/r/824206 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 56 +++++++++++++++++++++++---------- drivers/gpu/nvgpu/gk20a/channel_gk20a.h | 5 +++ drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 35 ++++++++++++++++----- drivers/gpu/nvgpu/gk20a/tsg_gk20a.c | 37 +++++++++++++++++++++- drivers/gpu/nvgpu/gk20a/tsg_gk20a.h | 5 ++- include/uapi/linux/nvgpu.h | 6 ++-- 6 files changed, 115 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 5b5da633..688992c6 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -132,24 +132,14 @@ static int channel_gk20a_commit_userd(struct channel_gk20a *c) return 0; } -static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, - u32 timeslice_timeout) +int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g, + int timeslice_period, + int *__timeslice_timeout, int *__timeslice_scale) { - void *inst_ptr; - struct gk20a_platform *platform = platform_get_drvdata(c->g->dev); - int shift = 3; - int value = scale_ptimer(timeslice_timeout, + struct gk20a_platform *platform = platform_get_drvdata(g->dev); + int value = scale_ptimer(timeslice_period, platform->ptimerscaling10x); - - inst_ptr = c->inst_block.cpu_va; - if (!inst_ptr) - return -ENOMEM; - - /* disable channel */ - c->g->ops.fifo.disable_channel(c); - - /* preempt the channel */ - WARN_ON(c->g->ops.fifo.preempt_channel(c->g, c->hw_chid)); + int shift = 3; /* value field is 8 bits long */ while (value >= 1 << 8) { @@ -164,6 +154,31 @@ static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, shift = 10; } + *__timeslice_timeout = value; + *__timeslice_scale = shift; + + return 0; +} + +static int channel_gk20a_set_schedule_params(struct channel_gk20a *c, + u32 timeslice_period) +{ + void *inst_ptr; + int shift = 0, value = 0; + + inst_ptr = c->inst_block.cpu_va; + if (!inst_ptr) + return -ENOMEM; + + gk20a_channel_get_timescale_from_timeslice(c->g, timeslice_period, + &value, &shift); + + /* disable channel */ + c->g->ops.fifo.disable_channel(c); + + /* preempt the channel */ + WARN_ON(c->g->ops.fifo.preempt_channel(c->g, c->hw_chid)); + /* set new timeslice */ gk20a_mem_wr32(inst_ptr, ram_fc_runlist_timeslice_w(), value | (shift << 12) | @@ -2350,6 +2365,13 @@ static int gk20a_channel_set_priority(struct channel_gk20a *ch, u32 priority) { u32 timeslice_timeout; + + if (gk20a_is_channel_marked_as_tsg(ch)) { + gk20a_err(dev_from_gk20a(ch->g), + "invalid operation for TSG!\n"); + return -EINVAL; + } + /* set priority of graphics channel */ switch (priority) { case NVGPU_PRIORITY_LOW: @@ -2714,7 +2736,7 @@ long gk20a_channel_ioctl(struct file *filp, __func__, cmd); break; } - gk20a_channel_set_priority(ch, + err = gk20a_channel_set_priority(ch, ((struct nvgpu_set_priority_args *)buf)->priority); gk20a_idle(dev); break; diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h index 29697b9f..e7809daa 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h @@ -253,4 +253,9 @@ int channel_gk20a_setup_ramfc(struct channel_gk20a *c, u64 gpfifo_base, u32 gpfifo_entries, u32 flags); void channel_gk20a_enable(struct channel_gk20a *ch); void gk20a_channel_timeout_restart_all_channels(struct gk20a *g); + +int gk20a_channel_get_timescale_from_timeslice(struct gk20a *g, + int timeslice_period, + int *__timeslice_timeout, int *__timeslice_scale); + #endif /* CHANNEL_GK20A_H */ diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 39cb1174..5eba9f12 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c @@ -2115,6 +2115,32 @@ static int gk20a_fifo_runlist_wait_pending(struct gk20a *g, u32 runlist_id) return ret; } +static inline u32 gk20a_get_tsg_runlist_entry_0(struct tsg_gk20a *tsg) +{ + u32 runlist_entry_0 = 0; + + if (tsg->timeslice_timeout) + runlist_entry_0 = ram_rl_entry_id_f(tsg->tsgid) | + ram_rl_entry_type_f(ram_rl_entry_type_tsg_f()) | + ram_rl_entry_timeslice_scale_f( + tsg->timeslice_scale) | + ram_rl_entry_timeslice_timeout_f( + tsg->timeslice_timeout) | + ram_rl_entry_tsg_length_f( + tsg->num_active_channels); + else + runlist_entry_0 = ram_rl_entry_id_f(tsg->tsgid) | + ram_rl_entry_type_f(ram_rl_entry_type_tsg_f()) | + ram_rl_entry_timeslice_scale_f( + ram_rl_entry_timeslice_scale_3_f()) | + ram_rl_entry_timeslice_timeout_f( + ram_rl_entry_timeslice_timeout_128_f()) | + ram_rl_entry_tsg_length_f( + tsg->num_active_channels); + + return runlist_entry_0; +} + static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, u32 hw_chid, bool add, bool wait_for_finish) @@ -2201,14 +2227,7 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, tsg = &f->tsg[tsgid]; /* add TSG entry */ gk20a_dbg_info("add TSG %d to runlist", tsg->tsgid); - runlist_entry[0] = ram_rl_entry_id_f(tsg->tsgid) | - ram_rl_entry_type_f(ram_rl_entry_type_tsg_f()) | - ram_rl_entry_timeslice_scale_f( - ram_rl_entry_timeslice_scale_3_f()) | - ram_rl_entry_timeslice_timeout_f( - ram_rl_entry_timeslice_timeout_128_f()) | - ram_rl_entry_tsg_length_f( - tsg->num_active_channels); + runlist_entry[0] = gk20a_get_tsg_runlist_entry_0(tsg); runlist_entry[1] = 0; runlist_entry += 2; count++; diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c index 37a326d2..5cd43329 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -126,6 +126,34 @@ int gk20a_init_tsg_support(struct gk20a *g, u32 tsgid) return 0; } +static int gk20a_tsg_set_priority(struct gk20a *g, struct tsg_gk20a *tsg, + u32 priority) +{ + int timeslice_period; + + switch (priority) { + case NVGPU_PRIORITY_LOW: + timeslice_period = g->timeslice_low_priority_us; + break; + case NVGPU_PRIORITY_MEDIUM: + timeslice_period = g->timeslice_medium_priority_us; + break; + case NVGPU_PRIORITY_HIGH: + timeslice_period = g->timeslice_high_priority_us; + break; + default: + pr_err("Unsupported priority"); + return -EINVAL; + } + + gk20a_channel_get_timescale_from_timeslice(g, timeslice_period, + &tsg->timeslice_timeout, &tsg->timeslice_scale); + + g->ops.fifo.update_runlist(g, 0, ~0, true, true); + + return 0; +} + static void release_used_tsg(struct fifo_gk20a *f, struct tsg_gk20a *tsg) { mutex_lock(&f->tsg_inuse_mutex); @@ -320,6 +348,13 @@ long gk20a_tsg_dev_ioctl(struct file *filp, unsigned int cmd, break; } + case NVGPU_IOCTL_TSG_SET_PRIORITY: + { + err = gk20a_tsg_set_priority(g, tsg, + ((struct nvgpu_set_priority_args *)buf)->priority); + break; + } + default: gk20a_err(dev_from_gk20a(g), "unrecognized tsg gpu ioctl cmd: 0x%x", diff --git a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h index fde33863..6178daa5 100644 --- a/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/tsg_gk20a.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -42,6 +42,9 @@ struct tsg_gk20a { int num_active_channels; struct mutex ch_list_lock; + int timeslice_timeout; + int timeslice_scale; + struct gr_ctx_desc *tsg_gr_ctx; struct vm_gk20a *vm; diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index f55346db..6024edee 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -377,11 +377,13 @@ struct nvgpu_gpu_vsms_mapping { _IO(NVGPU_TSG_IOCTL_MAGIC, 4) #define NVGPU_IOCTL_TSG_PREEMPT \ _IO(NVGPU_TSG_IOCTL_MAGIC, 5) +#define NVGPU_IOCTL_TSG_SET_PRIORITY \ + _IOW(NVGPU_TSG_IOCTL_MAGIC, 6, struct nvgpu_set_priority_args) #define NVGPU_TSG_IOCTL_MAX_ARG_SIZE \ - sizeof(int) + sizeof(struct nvgpu_set_priority_args) #define NVGPU_TSG_IOCTL_LAST \ - _IOC_NR(NVGPU_IOCTL_TSG_PREEMPT) + _IOC_NR(NVGPU_IOCTL_TSG_SET_PRIORITY) /* * /dev/nvhost-dbg-gpu device * -- cgit v1.2.2