mirror of
git://nv-tegra.nvidia.com/linux-hwpm.git
synced 2025-12-22 17:30:40 +03:00
tegra: hwpm: rearrange ioctl function calls
- Add macro to define maximum hwpm ioctl structure size. - Use switch-case logic for ioctl command to invoke corresponding functions. - Remove structure and array describing hwpm ioctl commands. Jira THWPM-58 Change-Id: I6c274123c82af928c3fdc82d7b1fb4b805704156 Signed-off-by: Vedashree Vidwans <vvidwans@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2729470 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Vasuki Shankar <vasukis@nvidia.com> Reviewed-by: Seema Khowala <seemaj@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
mobile promotions
parent
4f1e352286
commit
d6da34aa7d
244
os/linux/ioctl.c
244
os/linux/ioctl.c
@@ -32,85 +32,9 @@
|
|||||||
|
|
||||||
#define LA_CLK_RATE 625000000UL
|
#define LA_CLK_RATE 625000000UL
|
||||||
|
|
||||||
struct tegra_soc_hwpm_ioctl {
|
static int tegra_hwpm_get_device_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
const char *const name;
|
struct tegra_soc_hwpm_device_info *device_info)
|
||||||
const size_t struct_size;
|
|
||||||
int (*handler)(struct tegra_soc_hwpm *, void *);
|
|
||||||
};
|
|
||||||
|
|
||||||
static int device_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int floorsweep_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int resource_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int reserve_resource_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int alloc_pma_stream_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int bind_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int query_allowlist_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int exec_reg_ops_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
static int update_get_put_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct);
|
|
||||||
|
|
||||||
static const struct tegra_soc_hwpm_ioctl ioctls[] = {
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_DEVICE_INFO] = {
|
|
||||||
.name = "device_info",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_device_info),
|
|
||||||
.handler = device_info_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_FLOORSWEEP_INFO] = {
|
|
||||||
.name = "floorsweep_info",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_ip_floorsweep_info),
|
|
||||||
.handler = floorsweep_info_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_RESOURCE_INFO] = {
|
|
||||||
.name = "resource_info",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_resource_info),
|
|
||||||
.handler = resource_info_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_RESERVE_RESOURCE] = {
|
|
||||||
.name = "reserve_resource",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_reserve_resource),
|
|
||||||
.handler = reserve_resource_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_ALLOC_PMA_STREAM] = {
|
|
||||||
.name = "alloc_pma_stream",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_alloc_pma_stream),
|
|
||||||
.handler = alloc_pma_stream_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_BIND] = {
|
|
||||||
.name = "bind",
|
|
||||||
.struct_size = 0,
|
|
||||||
.handler = bind_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_QUERY_ALLOWLIST] = {
|
|
||||||
.name = "query_allowlist",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_query_allowlist),
|
|
||||||
.handler = query_allowlist_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_EXEC_REG_OPS] = {
|
|
||||||
.name = "exec_reg_ops",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_exec_reg_ops),
|
|
||||||
.handler = exec_reg_ops_ioctl,
|
|
||||||
},
|
|
||||||
[TEGRA_SOC_HWPM_IOCTL_UPDATE_GET_PUT] = {
|
|
||||||
.name = "update_get_put",
|
|
||||||
.struct_size = sizeof(struct tegra_soc_hwpm_update_get_put),
|
|
||||||
.handler = update_get_put_ioctl,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int device_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|
||||||
void *ioctl_struct)
|
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_device_info *device_info =
|
|
||||||
(struct tegra_soc_hwpm_device_info *)ioctl_struct;
|
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
device_info->chip = hwpm->device_info.chip;
|
device_info->chip = hwpm->device_info.chip;
|
||||||
@@ -130,12 +54,9 @@ static int device_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int floorsweep_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_get_floorsweep_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_ip_floorsweep_info *fs_info)
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_ip_floorsweep_info *fs_info =
|
|
||||||
(struct tegra_soc_hwpm_ip_floorsweep_info *)ioctl_struct;
|
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
if (fs_info->num_queries > TEGRA_SOC_HWPM_IP_QUERIES_MAX) {
|
if (fs_info->num_queries > TEGRA_SOC_HWPM_IP_QUERIES_MAX) {
|
||||||
@@ -147,12 +68,9 @@ static int floorsweep_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return tegra_hwpm_get_floorsweep_info(hwpm, fs_info);
|
return tegra_hwpm_get_floorsweep_info(hwpm, fs_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int resource_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_get_resource_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_resource_info *rsrc_info)
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_resource_info *rsrc_info =
|
|
||||||
(struct tegra_soc_hwpm_resource_info *)ioctl_struct;
|
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
if (rsrc_info->num_queries > TEGRA_SOC_HWPM_RESOURCE_QUERIES_MAX) {
|
if (rsrc_info->num_queries > TEGRA_SOC_HWPM_RESOURCE_QUERIES_MAX) {
|
||||||
@@ -165,11 +83,9 @@ static int resource_info_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reserve_resource_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_reserve_resource_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_reserve_resource *reserve_resource)
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_reserve_resource *reserve_resource =
|
|
||||||
(struct tegra_soc_hwpm_reserve_resource *)ioctl_struct;
|
|
||||||
u32 resource = reserve_resource->resource;
|
u32 resource = reserve_resource->resource;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -195,11 +111,9 @@ static int reserve_resource_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_pma_stream_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_alloc_pma_stream_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream)
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_alloc_pma_stream *alloc_pma_stream =
|
|
||||||
(struct tegra_soc_hwpm_alloc_pma_stream *)ioctl_struct;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
@@ -231,8 +145,7 @@ static int alloc_pma_stream_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bind_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_bind_ioctl(struct tegra_soc_hwpm *hwpm)
|
||||||
void *ioctl_struct)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -248,12 +161,10 @@ static int bind_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int query_allowlist_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_query_allowlist_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_query_allowlist *query_allowlist)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct tegra_soc_hwpm_query_allowlist *query_allowlist =
|
|
||||||
(struct tegra_soc_hwpm_query_allowlist *)ioctl_struct;
|
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
@@ -287,8 +198,8 @@ static int query_allowlist_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int exec_reg_ops_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_exec_reg_ops_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_exec_reg_ops *exec_reg_ops)
|
||||||
{
|
{
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
@@ -298,16 +209,12 @@ static int exec_reg_ops_ioctl(struct tegra_soc_hwpm *hwpm,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tegra_hwpm_exec_regops(hwpm,
|
return tegra_hwpm_exec_regops(hwpm, exec_reg_ops);
|
||||||
(struct tegra_soc_hwpm_exec_reg_ops *)ioctl_struct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update_get_put_ioctl(struct tegra_soc_hwpm *hwpm,
|
static int tegra_hwpm_update_get_put_ioctl(struct tegra_soc_hwpm *hwpm,
|
||||||
void *ioctl_struct)
|
struct tegra_soc_hwpm_update_get_put *update_get_put)
|
||||||
{
|
{
|
||||||
struct tegra_soc_hwpm_update_get_put *update_get_put =
|
|
||||||
(struct tegra_soc_hwpm_update_get_put *)ioctl_struct;
|
|
||||||
|
|
||||||
tegra_hwpm_fn(hwpm, " ");
|
tegra_hwpm_fn(hwpm, " ");
|
||||||
|
|
||||||
if (!hwpm->bind_completed) {
|
if (!hwpm->bind_completed) {
|
||||||
@@ -330,18 +237,16 @@ static long tegra_hwpm_ioctl(struct file *file,
|
|||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
enum tegra_soc_hwpm_ioctl_num ioctl_num = _IOC_NR(cmd);
|
|
||||||
u32 ioc_dir = _IOC_DIR(cmd);
|
|
||||||
u32 arg_size = _IOC_SIZE(cmd);
|
|
||||||
struct tegra_soc_hwpm *hwpm = NULL;
|
struct tegra_soc_hwpm *hwpm = NULL;
|
||||||
void *arg_copy = NULL;
|
u8 *buf;
|
||||||
|
|
||||||
if ((_IOC_TYPE(cmd) != TEGRA_SOC_HWPM_IOC_MAGIC) ||
|
if ((_IOC_TYPE(cmd) != TEGRA_SOC_HWPM_IOC_MAGIC) ||
|
||||||
(ioctl_num < 0) ||
|
(_IOC_NR(cmd) < 0) ||
|
||||||
(ioctl_num >= TERGA_SOC_HWPM_NUM_IOCTLS)) {
|
(_IOC_NR(cmd) >= TERGA_SOC_HWPM_NUM_IOCTLS) ||
|
||||||
tegra_hwpm_err(hwpm, "Unsupported IOCTL call");
|
(_IOC_SIZE(cmd) > TEGRA_SOC_HWPM_MAX_ARG_SIZE)) {
|
||||||
|
tegra_hwpm_err(hwpm, "Invalid IOCTL call");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto end;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
@@ -350,12 +255,6 @@ static long tegra_hwpm_ioctl(struct file *file,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_size != ioctls[ioctl_num].struct_size) {
|
|
||||||
tegra_hwpm_err(hwpm, "Invalid userspace struct");
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
hwpm = file->private_data;
|
hwpm = file->private_data;
|
||||||
if (!hwpm) {
|
if (!hwpm) {
|
||||||
tegra_hwpm_err(hwpm, "Invalid hwpm struct");
|
tegra_hwpm_err(hwpm, "Invalid hwpm struct");
|
||||||
@@ -371,57 +270,84 @@ static long tegra_hwpm_ioctl(struct file *file,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only allocate a buffer if the IOCTL needs a buffer */
|
if (!(_IOC_DIR(cmd) & _IOC_NONE)) {
|
||||||
if (!(ioc_dir & _IOC_NONE)) {
|
buf = kzalloc(TEGRA_SOC_HWPM_MAX_ARG_SIZE, GFP_KERNEL);
|
||||||
arg_copy = kzalloc(arg_size, GFP_KERNEL);
|
if (!buf) {
|
||||||
if (!arg_copy) {
|
tegra_hwpm_err(hwpm, "Kernel buf allocation failed");
|
||||||
tegra_hwpm_err(hwpm,
|
|
||||||
"Can't allocate memory for kernel struct");
|
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioc_dir & _IOC_WRITE) {
|
if (_IOC_DIR(cmd) & _IOC_WRITE) {
|
||||||
if (copy_from_user(arg_copy, (void __user *)arg, arg_size)) {
|
if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd))) {
|
||||||
tegra_hwpm_err(hwpm,
|
tegra_hwpm_err(hwpm, "Copy data from userspace failed");
|
||||||
"Failed to copy data from userspace"
|
|
||||||
" struct into kernel struct");
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
switch (cmd) {
|
||||||
* We don't goto fail here because even if the IOCTL fails, we have to
|
case TEGRA_CTRL_CMD_SOC_HWPM_DEVICE_INFO:
|
||||||
* call copy_to_user() to pass back any valid output params to
|
ret = tegra_hwpm_get_device_info_ioctl(hwpm,
|
||||||
* userspace.
|
(struct tegra_soc_hwpm_device_info *)buf);
|
||||||
*/
|
break;
|
||||||
ret = ioctls[ioctl_num].handler(hwpm, arg_copy);
|
case TEGRA_CTRL_CMD_SOC_HWPM_IP_FLOORSWEEP_INFO:
|
||||||
|
ret = tegra_hwpm_get_floorsweep_info_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_ip_floorsweep_info *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_RESOURCE_INFO:
|
||||||
|
ret = tegra_hwpm_get_resource_info_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_resource_info *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_RESERVE_RESOURCE:
|
||||||
|
ret = tegra_hwpm_reserve_resource_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_reserve_resource *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_ALLOC_PMA_STREAM:
|
||||||
|
ret = tegra_hwpm_alloc_pma_stream_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_alloc_pma_stream *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_BIND:
|
||||||
|
ret = tegra_hwpm_bind_ioctl(hwpm);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_QUERY_ALLOWLIST:
|
||||||
|
ret = tegra_hwpm_query_allowlist_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_query_allowlist *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_EXEC_REG_OPS:
|
||||||
|
ret = tegra_hwpm_exec_reg_ops_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_exec_reg_ops *)buf);
|
||||||
|
break;
|
||||||
|
case TEGRA_CTRL_CMD_SOC_HWPM_UPDATE_GET_PUT:
|
||||||
|
ret = tegra_hwpm_update_get_put_ioctl(hwpm,
|
||||||
|
(struct tegra_soc_hwpm_update_get_put *)buf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tegra_hwpm_err(hwpm, "Unknown IOCTL command");
|
||||||
|
ret = -ENOTTY;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (ioc_dir & _IOC_READ) {
|
if ((ret == 0) && (_IOC_DIR(cmd) & _IOC_READ)) {
|
||||||
if (copy_to_user((void __user *)arg, arg_copy, arg_size)) {
|
if (copy_to_user((void __user *)arg, buf, _IOC_SIZE(cmd))) {
|
||||||
tegra_hwpm_err(hwpm, "Failed to copy data from kernel"
|
tegra_hwpm_err(hwpm, "Copy buffer to user failed");
|
||||||
" struct into userspace struct");
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
tegra_hwpm_dbg(hwpm, hwpm_info, "The %s IOCTL completed successfully!",
|
|
||||||
ioctls[ioctl_num].name);
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
tegra_hwpm_err(hwpm, "The %s IOCTL failed(%d)!",
|
if (buf) {
|
||||||
ioctls[ioctl_num].name, ret);
|
kfree(buf);
|
||||||
cleanup:
|
}
|
||||||
if (arg_copy)
|
|
||||||
kfree(arg_copy);
|
if (ret < 0) {
|
||||||
end:
|
tegra_hwpm_err(hwpm, "IOCTL cmd %d failed(%d)!", cmd, ret);
|
||||||
|
} else {
|
||||||
|
tegra_hwpm_dbg(hwpm, hwpm_info,
|
||||||
|
"IOCTL cmd %d completed successfully!", cmd);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user