gpu: nvgpu: flags to query specific clk domains

Added NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS to indicate that a
request (get clock info/range) applies only to domains specified
in clock entries. If flag is not set, request returns all clock
domains.

Jira DNVGPU-125

Change-Id: I11bffbdf491ebffa7f47bd327037b0b8cfcbde31
Signed-off-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-on: http://git-master/r/1227998
(cherry picked from commit 7613dd30e120a82d342da402b4e0b070512dddad)
Reviewed-on: http://git-master/r/1243108
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Thomas Fleury
2016-09-26 15:56:43 -07:00
committed by mobile promotions
parent 05805ec65b
commit 94cea420c8
2 changed files with 87 additions and 45 deletions

View File

@@ -917,37 +917,51 @@ static int nvgpu_gpu_clk_get_range(struct gk20a *g,
u32 clk_domains = 0;
u32 num_domains;
u32 i;
int bit;
u16 min_mhz, max_mhz;
int err;
gk20a_dbg_fn("");
if (!session || args->flags)
if (!session)
return -EINVAL;
if (!args->flags) {
clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
num_domains = hweight_long(clk_domains);
if (!args->num_entries) {
args->num_entries = num_domains;
return 0;
}
if (args->num_entries < num_domains)
return -EINVAL;
args->num_entries = 0;
clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
num_domains = hweight_long(clk_domains);
if (!args->max_entries) {
args->max_entries = num_domains;
return 0;
}
if (args->max_entries < num_domains)
} else {
if (args->flags != NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS)
return -EINVAL;
num_domains = args->num_entries;
}
entry = (struct nvgpu_gpu_clk_range __user *)
(uintptr_t)args->clk_range_entries;
memset(&clk_range, 0, sizeof(clk_range));
for (i = 0; i < num_domains; i++, entry++) {
while (clk_domains) {
if (args->flags == NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS) {
if (copy_from_user(&clk_range, (void __user *)entry,
sizeof(clk_range)))
return -EFAULT;
} else {
bit = ffs(clk_domains) - 1;
clk_range.clk_domain = BIT(bit);
clk_domains &= ~BIT(bit);
}
err = nvgpu_clk_arb_get_arbiter_clk_range(g,
clk_range.clk_domain, &min_mhz, &max_mhz);
@@ -956,13 +970,11 @@ static int nvgpu_gpu_clk_get_range(struct gk20a *g,
clk_range.min_mhz = min_mhz;
clk_range.max_mhz = max_mhz;
clk_range.flags = 0;
err = copy_to_user(entry, &clk_range, sizeof(clk_range));
if (err)
return -EFAULT;
entry++;
clk_domains &= ~BIT(bit);
}
args->num_entries = num_domains;
@@ -1043,34 +1055,52 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
u32 num_domains;
u16 actual_mhz;
u16 target_mhz;
int err;
u32 i;
int err;
int bit;
gk20a_dbg_fn("");
if (!session || args->flags)
return -EINVAL;
clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
if (!clk_domains)
if (!session)
return -EINVAL;
args->last_req_nr = nvgpu_clk_arb_get_arbiter_req_nr(g);
if (!args->flags) {
clk_domains = nvgpu_clk_arb_get_arbiter_clk_domains(g);
num_domains = hweight_long(clk_domains);
if (!args->num_entries) {
args->num_entries = num_domains;
return 0;
}
if (args->num_entries < num_domains)
return -EINVAL;
args->num_entries = 0;
} else {
if (args->flags != NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS)
return -EINVAL;
num_domains = args->num_entries;
}
entry = (struct nvgpu_gpu_clk_info __user *)
(uintptr_t)args->clk_info_entries;
for (i = 0; i < args->num_entries; i++, entry++) {
for (i = 0; i < num_domains; i++, entry++) {
if (args->flags == NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS) {
if (copy_from_user(&clk_info, (void __user *)entry,
sizeof(clk_info)))
return -EFAULT;
} else {
bit = ffs(clk_domains) - 1;
clk_info.clk_domain = BIT(bit);
clk_domains &= ~BIT(bit);
}
err = nvgpu_clk_arb_get_arbiter_actual_mhz(g,
clk_info.clk_domain, &actual_mhz);
@@ -1084,6 +1114,7 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
clk_info.actual_mhz = actual_mhz;
clk_info.target_mhz = target_mhz;
clk_info.flags = 0;
err = copy_to_user((void __user *)entry, &clk_info,
sizeof(clk_info));
@@ -1091,6 +1122,8 @@ static int nvgpu_gpu_clk_get_info(struct gk20a *g,
return -EFAULT;
}
args->num_entries = num_domains;
return 0;
}

View File

@@ -524,20 +524,24 @@ struct nvgpu_gpu_clk_range {
__u32 max_mhz;
};
/* Request on specific clock domains */
#define NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS (1UL << 0)
struct nvgpu_gpu_clk_range_args {
/* Flags (not currently used) */
/* Flags. If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS the request will
apply only to domains specified in clock entries. In this case
caller must set clock domain in each entry. Otherwise, the
ioctl will return all clock domains.
*/
__u32 flags;
/* in/out: max number of entries in clk_range_entries buffer. If zero,
NVGPU_GPU_IOCTL_CLK_GET_RANGE will return 0 and max_entries will be
set to the max number of clock domains. If there are more entries
than max_entries, then ioctl will return -EINVAL.
*/
__u16 max_entries;
__u16 pad0;
/* out: number of nvgpu_gpu_clk_range entries contained in
clk_range_entries */
/* in/out: Number of entries in clk_range_entries buffer. If zero,
NVGPU_GPU_IOCTL_CLK_GET_RANGE will return 0 and
num_entries will be set to number of clock domains.
*/
__u16 num_entries;
/* in: Pointer to clock range entries in the caller's address space.
@@ -606,14 +610,18 @@ struct nvgpu_gpu_clk_info {
struct nvgpu_gpu_clk_get_info_args {
/* in: Flags (not currently used). */
/* Flags. If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS the request will
apply only to domains specified in clock entries. In this case
caller must set clock domain in each entry. Otherwise, the
ioctl will return all clock domains.
*/
__u32 flags;
__u16 pad0;
/* in/out: Number of clock info entries contained in clk_info_entries.
If zero, NVGPU_GPU_IOCTL_CLK_GET_INFO will return 0 and
max_entries will be set to number of clock domains. Also,
num_entries will be set to number of clock domains. Also,
last_req_nr will be updated, which allows checking if a given
request has completed. If there are more entries than max_entries,
then ioctl will return -EINVAL.
@@ -623,8 +631,9 @@ struct nvgpu_gpu_clk_get_info_args {
/* in: Pointer to nvgpu_gpu_clk_info entries in the caller's address
space. Buffer size must be at least:
num_entries * sizeof(struct nvgpu_gpu_clk_info)
For each entry, the clk_domain to be queried should be set. Note
that clk_info_entries passed to an NVGPU_GPU_IOCTL_CLK_SET_INFO,
If NVGPU_GPU_CLK_FLAG_SPECIFIC_DOMAINS is set, caller should set
clk_domain to be queried in each entry. With this flag,
clk_info_entries passed to an NVGPU_GPU_IOCTL_CLK_SET_INFO,
can be re-used on completion for a NVGPU_GPU_IOCTL_CLK_GET_INFO.
This allows checking actual_mhz.
*/