diff options
author | Will McVicker <willmcvicker@google.com> | 2023-11-03 16:42:29 -0700 |
---|---|---|
committer | Will McVicker <willmcvicker@google.com> | 2023-11-03 16:42:29 -0700 |
commit | 977b13f4ba89796735bd59e8bf23b61483c44b22 (patch) | |
tree | 2cb0f2b86975de9bd1544edee86713a82af0b050 | |
parent | 8a9fc759ede7a96e44845122f0b21406d2f8fda7 (diff) | |
download | lwis-android-gs-raviole-mainline.tar.gz |
Remove unused fileandroid-gs-raviole-mainline
Change-Id: I74009a659820e07a6106d9a8fec1e9a86e14ff6a
Signed-off-by: Will McVicker <willmcvicker@google.com>
-rw-r--r-- | lwis_cmd.c | 1433 |
1 files changed, 0 insertions, 1433 deletions
diff --git a/lwis_cmd.c b/lwis_cmd.c deleted file mode 100644 index 9e82632..0000000 --- a/lwis_cmd.c +++ /dev/null @@ -1,1433 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Google LWIS Command packets - * - * Copyright (c) 2022 Google, LLC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "lwis_cmd.h" - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/uaccess.h> - -#include "lwis_allocator.h" -#include "lwis_buffer.h" -#include "lwis_commands.h" -#include "lwis_device.h" -#include "lwis_device_dpm.h" -#include "lwis_device_i2c.h" -#include "lwis_device_ioreg.h" -#include "lwis_event.h" -#include "lwis_fence.h" -#include "lwis_i2c.h" -#include "lwis_io_entry.h" -#include "lwis_ioctl.h" -#include "lwis_ioreg.h" -#include "lwis_periodic_io.h" -#include "lwis_platform.h" -#include "lwis_transaction.h" -#include "lwis_util.h" - -static int copy_pkt_to_user(struct lwis_device *lwis_dev, void __user *u_msg, void *k_msg, - size_t size) -{ - if (copy_to_user(u_msg, k_msg, size)) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes to user\n", size); - return -EFAULT; - } - - return 0; -} - -static int cmd_echo(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_echo __user *u_msg) -{ - struct lwis_cmd_echo echo_msg; - char *buffer = NULL; - - if (copy_from_user((void *)&echo_msg, (void __user *)u_msg, sizeof(echo_msg))) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes from user\n", sizeof(echo_msg)); - return -EFAULT; - } - - if (echo_msg.msg.size == 0) { - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - buffer = kmalloc(echo_msg.msg.size + 1, GFP_KERNEL); - if (!buffer) { - dev_err(lwis_dev->dev, "Failed to allocate buffer for echo message\n"); - header->ret_code = -ENOMEM; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - if (copy_from_user(buffer, (void __user *)echo_msg.msg.msg, echo_msg.msg.size)) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes echo message from user\n", - echo_msg.msg.size); - kfree(buffer); - header->ret_code = -EFAULT; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - buffer[echo_msg.msg.size] = '\0'; - - if (echo_msg.msg.kernel_log) { - dev_info(lwis_dev->dev, "LWIS_ECHO: %s\n", buffer); - } - kfree(buffer); - - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_time_query(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_time_query __user *u_msg) -{ - struct lwis_cmd_time_query time_query; - time_query.timestamp_ns = ktime_to_ns(lwis_get_time()); - time_query.header.cmd_id = header->cmd_id; - time_query.header.next = header->next; - time_query.header.ret_code = 0; - - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&time_query, sizeof(time_query)); -} - -static int cmd_get_device_info(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_device_info __user *u_msg) -{ - int i; - struct lwis_cmd_device_info k_info = { .header.cmd_id = header->cmd_id, - .header.next = header->next, - .info.id = lwis_dev->id, - .info.type = lwis_dev->type, - .info.num_clks = 0, - .info.num_regs = 0, - .info.transaction_worker_thread_pid = -1, - .info.periodic_io_thread_pid = -1 }; - strscpy(k_info.info.name, lwis_dev->name, LWIS_MAX_NAME_STRING_LEN); - - if (lwis_dev->clocks) { - k_info.info.num_clks = lwis_dev->clocks->count; - for (i = 0; i < lwis_dev->clocks->count; i++) { - if (i >= LWIS_MAX_CLOCK_NUM) { - dev_err(lwis_dev->dev, - "Clock count larger than LWIS_MAX_CLOCK_NUM\n"); - break; - } - strscpy(k_info.info.clks[i].name, lwis_dev->clocks->clk[i].name, - LWIS_MAX_NAME_STRING_LEN); - k_info.info.clks[i].clk_index = i; - k_info.info.clks[i].frequency = 0; - } - } - - if (lwis_dev->type == DEVICE_TYPE_IOREG) { - struct lwis_ioreg_device *ioreg_dev; - ioreg_dev = container_of(lwis_dev, struct lwis_ioreg_device, base_dev); - if (ioreg_dev->reg_list.count > 0) { - k_info.info.num_regs = ioreg_dev->reg_list.count; - for (i = 0; i < ioreg_dev->reg_list.count; i++) { - if (i >= LWIS_MAX_REG_NUM) { - dev_err(lwis_dev->dev, - "Reg count larger than LWIS_MAX_REG_NUM\n"); - break; - } - strscpy(k_info.info.regs[i].name, ioreg_dev->reg_list.block[i].name, - LWIS_MAX_NAME_STRING_LEN); - k_info.info.regs[i].reg_index = i; - k_info.info.regs[i].start = ioreg_dev->reg_list.block[i].start; - k_info.info.regs[i].size = ioreg_dev->reg_list.block[i].size; - } - } - } - - if (lwis_dev->transaction_worker_thread) { - k_info.info.transaction_worker_thread_pid = - lwis_dev->transaction_worker_thread->pid; - } - - k_info.header.ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&k_info, sizeof(k_info)); -} - -static int cmd_device_enable(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_pkt __user *u_msg) -{ - int ret = 0; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (lwis_client->is_enabled) { - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - mutex_lock(&lwis_dev->client_lock); - if (lwis_dev->enabled > 0 && lwis_dev->enabled < INT_MAX) { - lwis_dev->enabled++; - lwis_client->is_enabled = true; - ret = 0; - goto exit_locked; - } else if (lwis_dev->enabled == INT_MAX) { - dev_err(lwis_dev->dev, "Enable counter overflow\n"); - ret = -EINVAL; - goto exit_locked; - } - - /* Clear event queues to make sure there is no stale event from - * previous session */ - lwis_client_event_queue_clear(lwis_client); - lwis_client_error_event_queue_clear(lwis_client); - - ret = lwis_dev_power_up_locked(lwis_dev); - if (ret < 0) { - dev_err(lwis_dev->dev, "Failed to power up device\n"); - goto exit_locked; - } - - lwis_dev->enabled++; - lwis_client->is_enabled = true; - lwis_dev->is_suspended = false; - dev_info(lwis_dev->dev, "Device enabled\n"); -exit_locked: - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_device_disable(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_pkt __user *u_msg) -{ - int ret = 0; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (!lwis_client->is_enabled) { - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - mutex_lock(&lwis_dev->client_lock); - /* Clear event states for this client */ - lwis_client_event_states_clear(lwis_client); - mutex_unlock(&lwis_dev->client_lock); - - /* Flush all periodic io to complete */ - ret = lwis_periodic_io_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to wait for in-process periodic io to complete\n"); - } - - /* Flush all pending transactions */ - ret = lwis_transaction_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to flush pending transactions\n"); - } - - /* Run cleanup transactions. */ - lwis_transaction_client_cleanup(lwis_client); - - mutex_lock(&lwis_dev->client_lock); - if (lwis_dev->enabled > 1) { - lwis_dev->enabled--; - lwis_client->is_enabled = false; - ret = 0; - goto exit_locked; - } else if (lwis_dev->enabled <= 0) { - dev_err(lwis_dev->dev, "Disabling a device that is already disabled\n"); - ret = -EINVAL; - goto exit_locked; - } - - ret = lwis_dev_power_down_locked(lwis_dev); - if (ret < 0) { - dev_err(lwis_dev->dev, "Failed to power down device\n"); - goto exit_locked; - } - lwis_device_event_states_clear_locked(lwis_dev); - - lwis_dev->enabled--; - lwis_client->is_enabled = false; - lwis_dev->is_suspended = false; - dev_info(lwis_dev->dev, "Device disabled\n"); -exit_locked: - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int copy_io_entries_from_cmd(struct lwis_device *lwis_dev, - struct lwis_cmd_io_entries __user *u_msg, - struct lwis_cmd_io_entries *k_msg, - struct lwis_io_entry **k_entries) -{ - struct lwis_io_entry *io_entries; - uint32_t buf_size; - - /* Register io is not supported for the lwis device, return */ - if (!lwis_dev->vops.register_io) { - dev_err(lwis_dev->dev, "Register IO not supported on this LWIS device\n"); - return -EINVAL; - } - - /* Copy io_entries from userspace */ - if (copy_from_user(k_msg, (void __user *)u_msg, sizeof(*k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy io_entries header from userspace.\n"); - return -EFAULT; - } - buf_size = sizeof(struct lwis_io_entry) * k_msg->io.num_io_entries; - if (buf_size / sizeof(struct lwis_io_entry) != k_msg->io.num_io_entries) { - dev_err(lwis_dev->dev, "Failed to copy io_entries due to integer overflow.\n"); - return -EOVERFLOW; - } - io_entries = lwis_allocator_allocate(lwis_dev, buf_size); - if (!io_entries) { - dev_err(lwis_dev->dev, "Failed to allocate io_entries buffer\n"); - return -ENOMEM; - } - if (copy_from_user(io_entries, (void __user *)k_msg->io.io_entries, buf_size)) { - dev_err(lwis_dev->dev, "Failed to copy io_entries from userspace.\n"); - lwis_allocator_free(lwis_dev, io_entries); - return -EFAULT; - } - *k_entries = io_entries; - - return 0; -} - -static int cmd_device_reset(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_io_entries __user *u_msg) -{ - int ret = 0; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - struct lwis_cmd_io_entries k_msg; - struct lwis_io_entry *k_entries = NULL; - unsigned long flags; - bool device_enabled = false; - - ret = copy_io_entries_from_cmd(lwis_dev, u_msg, &k_msg, &k_entries); - if (ret) { - goto soft_reset_exit; - } - - /* Clear event states, event queues and transactions for this client */ - mutex_lock(&lwis_dev->client_lock); - lwis_client_event_states_clear(lwis_client); - lwis_client_event_queue_clear(lwis_client); - lwis_client_error_event_queue_clear(lwis_client); - device_enabled = lwis_dev->enabled; - mutex_unlock(&lwis_dev->client_lock); - - /* Flush all periodic io to complete */ - ret = lwis_periodic_io_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to wait for in-process periodic io to complete\n"); - } - - /* Flush all pending transactions */ - ret = lwis_transaction_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to flush all pending transactions\n"); - } - - /* Perform reset routine defined by the io_entries */ - if (device_enabled) { - ret = lwis_ioctl_util_synchronous_process_io_entries( - lwis_dev, k_msg.io.num_io_entries, k_entries, k_msg.io.io_entries); - } else { - dev_warn(lwis_dev->dev, - "Device is not enabled, IoEntries will not be executed in DEVICE_RESET\n"); - } - - spin_lock_irqsave(&lwis_dev->lock, flags); - lwis_device_event_states_clear_locked(lwis_dev); - spin_unlock_irqrestore(&lwis_dev->lock, flags); -soft_reset_exit: - if (k_entries) { - lwis_allocator_free(lwis_dev, k_entries); - } - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_device_suspend(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_pkt __user *u_msg) -{ - int ret = 0; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (!lwis_dev->suspend_sequence) { - dev_err(lwis_dev->dev, "No suspend sequence defined\n"); - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - if (!lwis_client->is_enabled) { - dev_err(lwis_dev->dev, "Trying to suspend a disabled device\n"); - header->ret_code = -EINVAL; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - if (lwis_dev->is_suspended) { - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - mutex_lock(&lwis_dev->client_lock); - /* Clear event states for this client */ - lwis_client_event_states_clear(lwis_client); - mutex_unlock(&lwis_dev->client_lock); - - /* Flush all periodic io to complete */ - ret = lwis_periodic_io_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to wait for in-process periodic io to complete\n"); - } - - /* Flush all pending transactions */ - ret = lwis_transaction_client_flush(lwis_client); - if (ret) { - dev_err(lwis_dev->dev, "Failed to flush pending transactions\n"); - } - - /* Run cleanup transactions. */ - lwis_transaction_client_cleanup(lwis_client); - - mutex_lock(&lwis_dev->client_lock); - ret = lwis_dev_process_power_sequence(lwis_dev, lwis_dev->suspend_sequence, - /*set_active=*/false, /*skip_error=*/false); - if (ret) { - dev_err(lwis_dev->dev, "Error lwis_dev_process_power_sequence (%d)\n", ret); - goto exit_locked; - } - - lwis_device_event_states_clear_locked(lwis_dev); - - lwis_dev->is_suspended = true; - dev_info(lwis_dev->dev, "Device suspended\n"); -exit_locked: - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_device_resume(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_pkt __user *u_msg) -{ - int ret = 0; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (!lwis_dev->resume_sequence) { - dev_err(lwis_dev->dev, "No resume sequence defined\n"); - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - if (!lwis_dev->is_suspended) { - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - mutex_lock(&lwis_dev->client_lock); - /* Clear event queues to make sure there is no stale event from - * previous session */ - lwis_client_event_queue_clear(lwis_client); - lwis_client_error_event_queue_clear(lwis_client); - - ret = lwis_dev_process_power_sequence(lwis_dev, lwis_dev->resume_sequence, - /*set_active=*/true, /*skip_error=*/false); - if (ret) { - dev_err(lwis_dev->dev, "Error lwis_dev_process_power_sequence (%d)\n", ret); - goto exit_locked; - } - - lwis_dev->is_suspended = false; - dev_info(lwis_dev->dev, "Device resumed\n"); -exit_locked: - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dump_debug_state(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_pkt __user *u_msg) -{ - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - mutex_lock(&lwis_dev->client_lock); - /* Dump lwis device crash info */ - lwis_device_crash_info_dump(lwis_dev); - mutex_unlock(&lwis_dev->client_lock); - - header->ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dma_buffer_enroll(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_dma_buffer_enroll __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_dma_buffer_enroll buf_info; - struct lwis_enrolled_buffer *buffer; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - buffer = kmalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - dev_err(lwis_dev->dev, "Failed to allocate lwis_enrolled_buffer struct\n"); - header->ret_code = -ENOMEM; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - if (copy_from_user((void *)&buf_info, (void __user *)u_msg, sizeof(buf_info))) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes from user\n", sizeof(buf_info)); - ret = -EFAULT; - goto error_enroll; - } - - buffer->info.fd = buf_info.info.fd; - buffer->info.dma_read = buf_info.info.dma_read; - buffer->info.dma_write = buf_info.info.dma_write; - - ret = lwis_buffer_enroll(lwis_client, buffer); - if (ret) { - dev_err(lwis_dev->dev, "Failed to enroll buffer\n"); - goto error_enroll; - } - - buf_info.info.dma_vaddr = buffer->info.dma_vaddr; - buf_info.header.cmd_id = header->cmd_id; - buf_info.header.next = header->next; - buf_info.header.ret_code = ret; - ret = copy_pkt_to_user(lwis_dev, u_msg, (void *)&buf_info, sizeof(buf_info)); - if (ret) { - lwis_buffer_disenroll(lwis_client, buffer); - goto error_enroll; - } - - return ret; - -error_enroll: - kfree(buffer); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dma_buffer_disenroll(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_dma_buffer_disenroll __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_dma_buffer_disenroll info; - struct lwis_enrolled_buffer *buffer; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (copy_from_user((void *)&info, (void __user *)u_msg, sizeof(info))) { - dev_err(lwis_dev->dev, "Failed to copy DMA virtual address from user\n"); - return -EFAULT; - } - - buffer = lwis_client_enrolled_buffer_find(lwis_client, info.info.fd, info.info.dma_vaddr); - if (!buffer) { - dev_err(lwis_dev->dev, "Failed to find dma buffer for fd %d vaddr %pad\n", - info.info.fd, &info.info.dma_vaddr); - header->ret_code = -ENOENT; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - ret = lwis_buffer_disenroll(lwis_client, buffer); - if (ret) { - dev_err(lwis_dev->dev, "Failed to disenroll dma buffer for fd %d vaddr %pad\n", - info.info.fd, &info.info.dma_vaddr); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - kfree(buffer); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dma_buffer_cpu_access(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_dma_buffer_cpu_access __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_dma_buffer_cpu_access op; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (copy_from_user((void *)&op, (void __user *)u_msg, sizeof(op))) { - dev_err(lwis_dev->dev, "Failed to copy buffer CPU access operation from user\n"); - return -EFAULT; - } - - ret = lwis_buffer_cpu_access(lwis_client, &op.op); - if (ret) { - dev_err(lwis_dev->dev, "Failed to prepare for cpu access for fd %d\n", op.op.fd); - } - - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dma_buffer_alloc(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_dma_buffer_alloc __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_dma_buffer_alloc alloc_info; - struct lwis_allocated_buffer *buffer; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - buffer = kmalloc(sizeof(*buffer), GFP_KERNEL); - if (!buffer) { - dev_err(lwis_dev->dev, "Failed to allocated lwis_allocated_buffer\n"); - return -ENOMEM; - } - - if (copy_from_user((void *)&alloc_info, (void __user *)u_msg, sizeof(alloc_info))) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes from user\n", sizeof(alloc_info)); - ret = -EFAULT; - goto error_alloc; - } - - ret = lwis_buffer_alloc(lwis_client, &alloc_info.info, buffer); - if (ret) { - dev_err(lwis_dev->dev, "Failed to allocate buffer\n"); - goto error_alloc; - } - - alloc_info.header.ret_code = 0; - ret = copy_pkt_to_user(lwis_dev, u_msg, (void *)&alloc_info, sizeof(alloc_info)); - if (ret) { - lwis_buffer_free(lwis_client, buffer); - ret = -EFAULT; - goto error_alloc; - } - - return ret; - -error_alloc: - kfree(buffer); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dma_buffer_free(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_dma_buffer_free __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_dma_buffer_free info; - struct lwis_allocated_buffer *buffer; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (copy_from_user((void *)&info, (void __user *)u_msg, sizeof(info))) { - dev_err(lwis_dev->dev, "Failed to copy file descriptor from user\n"); - return -EFAULT; - } - - buffer = lwis_client_allocated_buffer_find(lwis_client, info.fd); - if (!buffer) { - dev_err(lwis_dev->dev, "Cannot find allocated buffer FD %d\n", info.fd); - header->ret_code = -ENOENT; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - ret = lwis_buffer_free(lwis_client, buffer); - if (ret) { - dev_err(lwis_dev->dev, "Failed to free buffer FD %d\n", info.fd); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - kfree(buffer); - - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_reg_io(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_io_entries __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_io_entries k_msg; - struct lwis_io_entry *k_entries = NULL; - - ret = copy_io_entries_from_cmd(lwis_dev, u_msg, &k_msg, &k_entries); - if (ret) { - goto reg_io_exit; - } - - /* Walk through and execute the entries */ - ret = lwis_ioctl_util_synchronous_process_io_entries(lwis_dev, k_msg.io.num_io_entries, - k_entries, k_msg.io.io_entries); - -reg_io_exit: - if (k_entries) { - lwis_allocator_free(lwis_dev, k_entries); - } - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_event_control_get(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_event_control_get __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_event_control_get control; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - - if (copy_from_user((void *)&control, (void __user *)u_msg, sizeof(control))) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes from user\n", sizeof(control)); - return -EFAULT; - } - - ret = lwis_client_event_control_get(lwis_client, control.ctl.event_id, &control.ctl); - if (ret) { - dev_err(lwis_dev->dev, "Failed to get event: %lld (err:%d)\n", control.ctl.event_id, - ret); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - control.header.ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&control, sizeof(control)); -} - -static int cmd_event_control_set(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_event_control_set __user *u_msg) -{ - struct lwis_cmd_event_control_set k_msg; - struct lwis_event_control *k_event_controls; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - int ret = 0; - int i; - size_t buf_size; - - if (copy_from_user((void *)&k_msg, (void __user *)u_msg, sizeof(k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy ioctl message from user\n"); - return -EFAULT; - } - - /* Copy event controls from user buffer. */ - buf_size = sizeof(struct lwis_event_control) * k_msg.list.num_event_controls; - if (buf_size / sizeof(struct lwis_event_control) != k_msg.list.num_event_controls) { - dev_err(lwis_dev->dev, "Failed to copy event controls due to integer overflow.\n"); - header->ret_code = -EOVERFLOW; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - k_event_controls = kmalloc(buf_size, GFP_KERNEL); - if (!k_event_controls) { - dev_err(lwis_dev->dev, "Failed to allocate event controls\n"); - header->ret_code = -ENOMEM; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - if (copy_from_user(k_event_controls, (void __user *)k_msg.list.event_controls, buf_size)) { - dev_err(lwis_dev->dev, "Failed to copy event controls from user\n"); - ret = -EFAULT; - goto exit; - } - - for (i = 0; i < k_msg.list.num_event_controls; i++) { - ret = lwis_client_event_control_set(lwis_client, &k_event_controls[i]); - if (ret) { - dev_err(lwis_dev->dev, "Failed to apply event control 0x%llx\n", - k_event_controls[i].event_id); - goto exit; - } - } -exit: - kfree(k_event_controls); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_event_dequeue(struct lwis_client *lwis_client, struct lwis_cmd_pkt *header, - struct lwis_cmd_event_dequeue __user *u_msg) -{ - struct lwis_cmd_event_dequeue info; - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - struct lwis_event_entry *event; - int ret = 0; - int err = 0; - bool is_error_event = false; - - if (copy_from_user((void *)&info, (void __user *)u_msg, sizeof(info))) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes from user\n", sizeof(info)); - return -EFAULT; - } - - mutex_lock(&lwis_dev->client_lock); - /* Peek at the front element of error event queue first */ - ret = lwis_client_error_event_peek_front(lwis_client, &event); - if (ret == 0) { - is_error_event = true; - } else if (ret != -ENOENT) { - dev_err(lwis_dev->dev, "Error dequeueing error event: %d\n", ret); - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } else { - /* Nothing at error event queue, continue to check normal - * event queue */ - ret = lwis_client_event_peek_front(lwis_client, &event); - if (ret) { - if (ret != -ENOENT) { - dev_err(lwis_dev->dev, "Error dequeueing event: %d\n", ret); - } - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - } - - /* We need to check if we have an adequate payload buffer */ - if (event->event_info.payload_size > info.info.payload_buffer_size) { - /* Nope, we don't. Let's inform the user and bail */ - info.info.payload_size = event->event_info.payload_size; - err = -EAGAIN; - } else { - info.info.event_id = event->event_info.event_id; - info.info.event_counter = event->event_info.event_counter; - info.info.timestamp_ns = event->event_info.timestamp_ns; - info.info.payload_size = event->event_info.payload_size; - - /* Here we have a payload and the buffer is big enough */ - if (event->event_info.payload_size > 0 && info.info.payload_buffer) { - /* Copy over the payload buffer to userspace */ - if (copy_to_user((void __user *)info.info.payload_buffer, - (void *)event->event_info.payload_buffer, - event->event_info.payload_size)) { - dev_err(lwis_dev->dev, "Failed to copy %zu bytes to user\n", - event->event_info.payload_size); - mutex_unlock(&lwis_dev->client_lock); - return -EFAULT; - } - } - } - /* If we didn't -EAGAIN up above, we can pop and discard the front of - * the event queue because we're done dealing with it. If we got the - * -EAGAIN case, we didn't actually dequeue this event and userspace - * should try again with a bigger payload_buffer. - */ - if (!err) { - if (is_error_event) { - ret = lwis_client_error_event_pop_front(lwis_client, NULL); - } else { - ret = lwis_client_event_pop_front(lwis_client, NULL); - } - if (ret) { - dev_err(lwis_dev->dev, "Error dequeueing event: %d\n", ret); - mutex_unlock(&lwis_dev->client_lock); - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - } - mutex_unlock(&lwis_dev->client_lock); - /* Now let's copy the actual info struct back to user */ - info.header.ret_code = err; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&info, sizeof(info)); -} - -static int construct_transaction_from_cmd(struct lwis_client *client, - struct lwis_cmd_transaction_info __user *u_msg, - struct lwis_transaction **transaction) -{ - int ret; - struct lwis_cmd_transaction_info k_info; - struct lwis_transaction *k_transaction; - struct lwis_device *lwis_dev = client->lwis_dev; - - k_transaction = kmalloc(sizeof(*k_transaction), GFP_KERNEL); - if (!k_transaction) { - dev_err(lwis_dev->dev, "Failed to allocate transaction info\n"); - return -ENOMEM; - } - - if (copy_from_user((void *)&k_info, (void __user *)u_msg, sizeof(k_info))) { - dev_err(lwis_dev->dev, "Failed to copy transaction info from user\n"); - ret = -EFAULT; - goto error_free_transaction; - } - - memcpy(&k_transaction->info, &k_info.info, sizeof(k_transaction->info)); - - ret = lwis_ioctl_util_construct_io_entry(client, k_transaction->info.io_entries, - k_transaction->info.num_io_entries, - &k_transaction->info.io_entries); - if (ret) { - dev_err(lwis_dev->dev, "Failed to prepare lwis io entries for transaction\n"); - goto error_free_transaction; - } - - k_transaction->resp = NULL; - k_transaction->is_weak_transaction = false; - INIT_LIST_HEAD(&k_transaction->event_list_node); - INIT_LIST_HEAD(&k_transaction->process_queue_node); - INIT_LIST_HEAD(&k_transaction->completion_fence_list); - - *transaction = k_transaction; - return 0; - -error_free_transaction: - kfree(k_transaction); - return ret; -} - -static int cmd_transaction_submit(struct lwis_client *client, struct lwis_cmd_pkt *header, - struct lwis_cmd_transaction_info __user *u_msg) -{ - struct lwis_transaction *k_transaction = NULL; - struct lwis_cmd_transaction_info k_transaction_info; - struct lwis_device *lwis_dev = client->lwis_dev; - int ret = 0; - unsigned long flags; - - if (lwis_dev->type == DEVICE_TYPE_SLC || lwis_dev->type == DEVICE_TYPE_DPM) { - dev_err(lwis_dev->dev, "not supported device type: %d\n", lwis_dev->type); - ret = -EINVAL; - goto err_exit; - } - - ret = construct_transaction_from_cmd(client, u_msg, &k_transaction); - if (ret) { - goto err_exit; - } - - ret = lwis_initialize_transaction_fences(client, k_transaction); - if (ret) { - lwis_transaction_free(lwis_dev, k_transaction); - goto err_exit; - } - - spin_lock_irqsave(&client->transaction_lock, flags); - ret = lwis_transaction_submit_locked(client, k_transaction); - k_transaction_info.info = k_transaction->info; - spin_unlock_irqrestore(&client->transaction_lock, flags); - if (ret) { - k_transaction_info.info.id = LWIS_ID_INVALID; - lwis_transaction_free(lwis_dev, k_transaction); - } - - k_transaction_info.header.cmd_id = header->cmd_id; - k_transaction_info.header.next = header->next; - k_transaction_info.header.ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&k_transaction_info, - sizeof(k_transaction_info)); - -err_exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_transaction_cancel(struct lwis_client *client, struct lwis_cmd_pkt *header, - struct lwis_cmd_transaction_cancel __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_transaction_cancel k_msg; - struct lwis_device *lwis_dev = client->lwis_dev; - - if (copy_from_user((void *)&k_msg, (void __user *)u_msg, sizeof(k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy transaction ID from user\n"); - return -EFAULT; - } - - ret = lwis_transaction_cancel(client, k_msg.id); - if (ret) { - dev_info_ratelimited( - lwis_dev->dev, - "Transaction id 0x%llx does not exist or is already done, not available for cancel(%d)\n", - k_msg.id, ret); - } - - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_transaction_replace(struct lwis_client *client, struct lwis_cmd_pkt *header, - struct lwis_cmd_transaction_info __user *u_msg) -{ - struct lwis_transaction *k_transaction = NULL; - struct lwis_cmd_transaction_info k_transaction_info; - struct lwis_device *lwis_dev = client->lwis_dev; - int ret = 0; - unsigned long flags; - - ret = construct_transaction_from_cmd(client, u_msg, &k_transaction); - if (ret) { - goto err_exit; - } - - ret = lwis_initialize_transaction_fences(client, k_transaction); - if (ret) { - lwis_transaction_free(lwis_dev, k_transaction); - goto err_exit; - } - - spin_lock_irqsave(&client->transaction_lock, flags); - ret = lwis_transaction_replace_locked(client, k_transaction); - k_transaction_info.info = k_transaction->info; - spin_unlock_irqrestore(&client->transaction_lock, flags); - if (ret) { - k_transaction_info.info.id = LWIS_ID_INVALID; - lwis_transaction_free(lwis_dev, k_transaction); - } - - k_transaction_info.header.cmd_id = header->cmd_id; - k_transaction_info.header.next = header->next; - k_transaction_info.header.ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&k_transaction_info, - sizeof(k_transaction_info)); - -err_exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int construct_periodic_io_from_cmd(struct lwis_client *client, - struct lwis_cmd_periodic_io_info __user *u_msg, - struct lwis_periodic_io **periodic_io) -{ - int ret = 0; - struct lwis_periodic_io *k_periodic_io; - struct lwis_cmd_periodic_io_info k_info; - struct lwis_device *lwis_dev = client->lwis_dev; - - k_periodic_io = kmalloc(sizeof(struct lwis_periodic_io), GFP_KERNEL); - if (!k_periodic_io) { - dev_err(lwis_dev->dev, "Failed to allocate periodic io\n"); - return -ENOMEM; - } - - if (copy_from_user((void *)&k_info, (void __user *)u_msg, sizeof(k_info))) { - dev_err(lwis_dev->dev, "Failed to copy periodic io info from user\n"); - ret = -EFAULT; - goto error_free_periodic_io; - } - - memcpy(&k_periodic_io->info, &k_info.info, sizeof(k_periodic_io->info)); - - ret = lwis_ioctl_util_construct_io_entry(client, k_periodic_io->info.io_entries, - k_periodic_io->info.num_io_entries, - &k_periodic_io->info.io_entries); - if (ret) { - dev_err(lwis_dev->dev, "Failed to prepare lwis io entries for periodic io\n"); - goto error_free_periodic_io; - } - - k_periodic_io->resp = NULL; - k_periodic_io->periodic_io_list = NULL; - - *periodic_io = k_periodic_io; - return 0; - -error_free_periodic_io: - kfree(k_periodic_io); - return ret; -} - -static int cmd_periodic_io_submit(struct lwis_client *client, struct lwis_cmd_pkt *header, - struct lwis_cmd_periodic_io_info __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_periodic_io_info k_periodic_io_info; - struct lwis_periodic_io *k_periodic_io = NULL; - struct lwis_device *lwis_dev = client->lwis_dev; - - ret = construct_periodic_io_from_cmd(client, u_msg, &k_periodic_io); - if (ret) { - goto err_exit; - } - - ret = lwis_periodic_io_submit(client, k_periodic_io); - k_periodic_io_info.info = k_periodic_io->info; - if (ret) { - k_periodic_io_info.info.id = LWIS_ID_INVALID; - lwis_periodic_io_free(lwis_dev, k_periodic_io); - goto err_exit; - } - - k_periodic_io_info.header.cmd_id = header->cmd_id; - k_periodic_io_info.header.next = header->next; - k_periodic_io_info.header.ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&k_periodic_io_info, - sizeof(k_periodic_io_info)); - -err_exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_periodic_io_cancel(struct lwis_client *client, struct lwis_cmd_pkt *header, - struct lwis_cmd_periodic_io_cancel __user *u_msg) -{ - int ret = 0; - struct lwis_cmd_periodic_io_cancel k_msg; - struct lwis_device *lwis_dev = client->lwis_dev; - - if (copy_from_user((void *)&k_msg, (void __user *)u_msg, sizeof(k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy periodic io ID from user\n"); - return -EFAULT; - } - - ret = lwis_periodic_io_cancel(client, k_msg.id); - if (ret) { - dev_err_ratelimited(lwis_dev->dev, "Failed to clear periodic io id 0x%llx\n", - k_msg.id); - } - - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dpm_clk_update(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_dpm_clk_update __user *u_msg) -{ - int ret; - struct lwis_cmd_dpm_clk_update k_msg; - struct lwis_clk_setting *clk_settings; - size_t buf_size; - - if (copy_from_user((void *)&k_msg, (void __user *)u_msg, sizeof(k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy ioctl message from user\n"); - return -EFAULT; - } - - buf_size = sizeof(struct lwis_clk_setting) * k_msg.settings.num_settings; - if (buf_size / sizeof(struct lwis_clk_setting) != k_msg.settings.num_settings) { - dev_err(lwis_dev->dev, "Failed to copy clk settings due to integer overflow.\n"); - ret = -EOVERFLOW; - goto exit; - } - clk_settings = kmalloc(buf_size, GFP_KERNEL); - if (!clk_settings) { - dev_err(lwis_dev->dev, "Failed to allocate clock settings\n"); - ret = -ENOMEM; - goto exit; - } - - if (copy_from_user(clk_settings, (void __user *)k_msg.settings.settings, buf_size)) { - dev_err(lwis_dev->dev, "Failed to copy clk settings from user\n"); - kfree(clk_settings); - ret = -EFAULT; - goto exit; - } - - ret = lwis_dpm_update_clock(lwis_dev, clk_settings, k_msg.settings.num_settings); - kfree(clk_settings); -exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dpm_qos_update(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_dpm_qos_update __user *u_msg) -{ - struct lwis_cmd_dpm_qos_update k_msg; - struct lwis_qos_setting *k_qos_settings; - int ret = 0; - int i; - size_t buf_size; - - if (lwis_dev->type != DEVICE_TYPE_DPM) { - dev_err(lwis_dev->dev, "not supported device type: %d\n", lwis_dev->type); - ret = -EINVAL; - goto exit; - } - - if (copy_from_user((void *)&k_msg, (void __user *)u_msg, sizeof(k_msg))) { - dev_err(lwis_dev->dev, "Failed to copy ioctl message from user\n"); - return -EFAULT; - } - - // Copy qos settings from user buffer. - buf_size = sizeof(struct lwis_qos_setting) * k_msg.reqs.num_settings; - if (buf_size / sizeof(struct lwis_qos_setting) != k_msg.reqs.num_settings) { - dev_err(lwis_dev->dev, "Failed to copy qos settings due to integer overflow.\n"); - ret = -EOVERFLOW; - goto exit; - } - k_qos_settings = kmalloc(buf_size, GFP_KERNEL); - if (!k_qos_settings) { - dev_err(lwis_dev->dev, "Failed to allocate qos settings\n"); - ret = -ENOMEM; - goto exit; - } - if (copy_from_user(k_qos_settings, (void __user *)k_msg.reqs.qos_settings, buf_size)) { - dev_err(lwis_dev->dev, "Failed to copy clk settings from user\n"); - kfree(k_qos_settings); - ret = -EFAULT; - goto exit; - } - - for (i = 0; i < k_msg.reqs.num_settings; i++) { - ret = lwis_dpm_update_qos(lwis_dev, &k_qos_settings[i]); - if (ret) { - dev_err(lwis_dev->dev, "Failed to apply qos setting, ret: %d\n", ret); - kfree(k_qos_settings); - goto exit; - } - } - kfree(k_qos_settings); -exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -static int cmd_dpm_get_clock(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_dpm_clk_get __user *u_msg) -{ - struct lwis_cmd_dpm_clk_get current_setting; - struct lwis_device *target_device; - int ret = 0; - - if (lwis_dev->type != DEVICE_TYPE_DPM) { - dev_err(lwis_dev->dev, "not supported device type: %d\n", lwis_dev->type); - ret = -EINVAL; - goto err_exit; - } - - if (copy_from_user((void *)¤t_setting, (void __user *)u_msg, - sizeof(current_setting))) { - dev_err(lwis_dev->dev, "failed to copy from user\n"); - return -EFAULT; - } - - target_device = lwis_find_dev_by_id(current_setting.setting.device_id); - if (!target_device) { - dev_err(lwis_dev->dev, "could not find lwis device by id %d\n", - current_setting.setting.device_id); - ret = -ENODEV; - goto err_exit; - } - - if (target_device->enabled == 0 && target_device->type != DEVICE_TYPE_DPM) { - dev_warn(target_device->dev, "%s disabled, can't get clk\n", target_device->name); - ret = -EPERM; - goto err_exit; - } - - current_setting.setting.frequency_hz = (int64_t)lwis_dpm_read_clock(target_device); - current_setting.header.ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)¤t_setting, sizeof(current_setting)); - -err_exit: - header->ret_code = ret; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); -} - -#ifdef LWIS_FENCE_ENABLED -static int cmd_fence_create(struct lwis_device *lwis_dev, struct lwis_cmd_pkt *header, - struct lwis_cmd_fence_create __user *u_msg) -{ - int32_t fd_or_err; - struct lwis_cmd_fence_create fence_create; - - if (copy_from_user((void *)&fence_create, (void __user *)u_msg, sizeof(fence_create))) { - dev_err(lwis_dev->dev, "failed to copy from user\n"); - return -EFAULT; - } - - fd_or_err = lwis_fence_create(lwis_dev); - if (fd_or_err < 0) { - header->ret_code = fd_or_err; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)header, sizeof(*header)); - } - - fence_create.fd = fd_or_err; - fence_create.header.ret_code = 0; - return copy_pkt_to_user(lwis_dev, u_msg, (void *)&fence_create, sizeof(fence_create)); -} -#endif - -int lwis_ioctl_handle_cmd_pkt(struct lwis_client *lwis_client, struct lwis_cmd_pkt __user *user_msg) -{ - struct lwis_device *lwis_dev = lwis_client->lwis_dev; - struct lwis_cmd_pkt header; - int ret = 0; - - while (user_msg) { - /* Copy cmd packet header from userspace */ - if (copy_from_user(&header, (void __user *)user_msg, sizeof(header))) { - dev_err(lwis_dev->dev, - "Failed to copy cmd packet header from userspace.\n"); - return -EFAULT; - } - - switch (header.cmd_id) { - case LWIS_CMD_ID_ECHO: - ret = cmd_echo(lwis_dev, &header, (struct lwis_cmd_echo __user *)user_msg); - break; - case LWIS_CMD_ID_TIME_QUERY: - ret = cmd_time_query(lwis_dev, &header, - (struct lwis_cmd_time_query __user *)user_msg); - break; - case LWIS_CMD_ID_GET_DEVICE_INFO: - mutex_lock(&lwis_client->lock); - ret = cmd_get_device_info(lwis_dev, &header, - (struct lwis_cmd_device_info __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DEVICE_ENABLE: - mutex_lock(&lwis_client->lock); - ret = cmd_device_enable(lwis_client, &header, - (struct lwis_cmd_pkt __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DEVICE_DISABLE: - mutex_lock(&lwis_client->lock); - ret = cmd_device_disable(lwis_client, &header, - (struct lwis_cmd_pkt __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DEVICE_RESET: - mutex_lock(&lwis_client->lock); - ret = cmd_device_reset(lwis_client, &header, - (struct lwis_cmd_io_entries __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DEVICE_SUSPEND: - mutex_lock(&lwis_client->lock); - ret = cmd_device_suspend(lwis_client, &header, - (struct lwis_cmd_pkt __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DEVICE_RESUME: - mutex_lock(&lwis_client->lock); - ret = cmd_device_resume(lwis_client, &header, - (struct lwis_cmd_pkt __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DUMP_DEBUG_STATE: - ret = cmd_dump_debug_state(lwis_client, &header, - (struct lwis_cmd_pkt __user *)user_msg); - break; - case LWIS_CMD_ID_DMA_BUFFER_ENROLL: - mutex_lock(&lwis_client->lock); - ret = cmd_dma_buffer_enroll( - lwis_client, &header, - (struct lwis_cmd_dma_buffer_enroll __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DMA_BUFFER_DISENROLL: - mutex_lock(&lwis_client->lock); - ret = cmd_dma_buffer_disenroll( - lwis_client, &header, - (struct lwis_cmd_dma_buffer_disenroll __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DMA_BUFFER_CPU_ACCESS: - mutex_lock(&lwis_client->lock); - ret = cmd_dma_buffer_cpu_access( - lwis_client, &header, - (struct lwis_cmd_dma_buffer_cpu_access __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DMA_BUFFER_ALLOC: - mutex_lock(&lwis_client->lock); - ret = cmd_dma_buffer_alloc( - lwis_client, &header, - (struct lwis_cmd_dma_buffer_alloc __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DMA_BUFFER_FREE: - mutex_lock(&lwis_client->lock); - ret = cmd_dma_buffer_free( - lwis_client, &header, - (struct lwis_cmd_dma_buffer_free __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_REG_IO: - mutex_lock(&lwis_client->lock); - ret = cmd_reg_io(lwis_dev, &header, - (struct lwis_cmd_io_entries __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_EVENT_CONTROL_GET: - mutex_lock(&lwis_client->lock); - ret = cmd_event_control_get( - lwis_client, &header, - (struct lwis_cmd_event_control_get __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_EVENT_CONTROL_SET: - mutex_lock(&lwis_client->lock); - ret = cmd_event_control_set( - lwis_client, &header, - (struct lwis_cmd_event_control_set __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_EVENT_DEQUEUE: - ret = cmd_event_dequeue(lwis_client, &header, - (struct lwis_cmd_event_dequeue __user *)user_msg); - break; - case LWIS_CMD_ID_TRANSACTION_SUBMIT: - mutex_lock(&lwis_client->lock); - ret = cmd_transaction_submit( - lwis_client, &header, - (struct lwis_cmd_transaction_info __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_TRANSACTION_CANCEL: - mutex_lock(&lwis_client->lock); - ret = cmd_transaction_cancel( - lwis_client, &header, - (struct lwis_cmd_transaction_cancel __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_TRANSACTION_REPLACE: - mutex_lock(&lwis_client->lock); - ret = cmd_transaction_replace( - lwis_client, &header, - (struct lwis_cmd_transaction_info __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_PERIODIC_IO_SUBMIT: - mutex_lock(&lwis_client->lock); - ret = cmd_periodic_io_submit( - lwis_client, &header, - (struct lwis_cmd_periodic_io_info __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_PERIODIC_IO_CANCEL: - mutex_lock(&lwis_client->lock); - ret = cmd_periodic_io_cancel( - lwis_client, &header, - (struct lwis_cmd_periodic_io_cancel __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DPM_CLK_UPDATE: - mutex_lock(&lwis_client->lock); - ret = cmd_dpm_clk_update(lwis_dev, &header, - (struct lwis_cmd_dpm_clk_update __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DPM_QOS_UPDATE: - mutex_lock(&lwis_client->lock); - ret = cmd_dpm_qos_update(lwis_dev, &header, - (struct lwis_cmd_dpm_qos_update __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; - case LWIS_CMD_ID_DPM_GET_CLOCK: - mutex_lock(&lwis_client->lock); - ret = cmd_dpm_get_clock(lwis_dev, &header, - (struct lwis_cmd_dpm_clk_get __user *)user_msg); - mutex_unlock(&lwis_client->lock); - break; -#ifdef LWIS_FENCE_ENABLED - case LWIS_CMD_ID_FENCE_CREATE: - ret = cmd_fence_create(lwis_dev, &header, - (struct lwis_cmd_fence_create __user *)user_msg); - break; -#endif - default: - dev_err_ratelimited(lwis_dev->dev, "Unknown command id\n"); - header.ret_code = -EINVAL; - ret = copy_pkt_to_user(lwis_dev, user_msg, (void *)&header, sizeof(header)); - } - if (ret) { - return ret; - } - user_msg = header.next; - } - - return ret; -} |