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:
Vedashree Vidwans
2022-06-12 19:21:56 -07:00
committed by mobile promotions
parent 4f1e352286
commit d6da34aa7d

View File

@@ -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,
if (ioc_dir & _IOC_READ) { (struct tegra_soc_hwpm_ip_floorsweep_info *)buf);
if (copy_to_user((void __user *)arg, arg_copy, arg_size)) { break;
tegra_hwpm_err(hwpm, "Failed to copy data from kernel" case TEGRA_CTRL_CMD_SOC_HWPM_RESOURCE_INFO:
" struct into userspace struct"); ret = tegra_hwpm_get_resource_info_ioctl(hwpm,
ret = -EFAULT; (struct tegra_soc_hwpm_resource_info *)buf);
goto fail; break;
} case TEGRA_CTRL_CMD_SOC_HWPM_RESERVE_RESOURCE:
} ret = tegra_hwpm_reserve_resource_ioctl(hwpm,
(struct tegra_soc_hwpm_reserve_resource *)buf);
if (ret < 0) 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; goto fail;
}
tegra_hwpm_dbg(hwpm, hwpm_info, "The %s IOCTL completed successfully!", if ((ret == 0) && (_IOC_DIR(cmd) & _IOC_READ)) {
ioctls[ioctl_num].name); if (copy_to_user((void __user *)arg, buf, _IOC_SIZE(cmd))) {
goto cleanup; tegra_hwpm_err(hwpm, "Copy buffer to user failed");
ret = -EFAULT;
goto fail;
}
}
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;
} }