[virtio-magma] Add magma_execute_command_buffer_with_resources Copies the user memory blocks into a single buffer. Change-Id: I959ee174b19e92fde68220af9c420f21975f54f9
diff --git a/drivers/virtio/virtio_magma.c b/drivers/virtio/virtio_magma.c index cd6da57..0a35ff8 100644 --- a/drivers/virtio/virtio_magma.c +++ b/drivers/virtio/virtio_magma.c
@@ -1025,6 +1025,81 @@ static int virtmagma_command_magma_submit_command_buffer( return 0; } +static int virtmagma_command_magma_execute_command_buffer_with_resources( + struct virtmagma_instance *instance, + struct virtmagma_virtio_command *command) +{ + struct virtio_magma_execute_command_buffer_with_resources_ctrl *request = + command->request_ptr; + struct virtio_magma_execute_command_buffer_with_resources_resp + *response = command->response_ptr; + struct virtmagma_connection *connection; + struct virtmagma_command_buffer virt_command_buffer; + char *dst_ptr; + int ret; + + if (!COMMAND_OK(command, request, response)) + return -EINVAL; + + connection = get_connection(instance, request->connection); + if (!connection) + return -EINVAL; + + if (!get_connection_object(connection, request->context_id, + MAGMA_CONTEXT)) + return -EINVAL; + + /* The virtmagma_comand_buffer includes the resources and semaphore data + and their lengths, so we ignore the corresponding members of the request. */ + ret = copy_from_user(&virt_command_buffer, + (void *)request->command_buffer, + sizeof(virt_command_buffer)); + if (ret) + return ret; + + /* reallocate request buffer with enough space for the structures */ + command->request_size = sizeof(*request) + + virt_command_buffer.command_buffer_size + + virt_command_buffer.resource_size + + virt_command_buffer.semaphore_size; + /* memory will be freed by the caller */ + dst_ptr = kzalloc(command->request_size, GFP_KERNEL); + if (!dst_ptr) + return -ENOMEM; + + memcpy(dst_ptr, request, sizeof(*request)); + command->request_ptr = dst_ptr; + + dst_ptr += sizeof(*request); + ret = copy_from_user(dst_ptr, + (void *)virt_command_buffer.command_buffer, + virt_command_buffer.command_buffer_size); + if (ret) + return ret; + + dst_ptr += virt_command_buffer.command_buffer_size; + ret = copy_from_user(dst_ptr, (void *)virt_command_buffer.resources, + virt_command_buffer.resource_size); + if (ret) + return ret; + + dst_ptr += virt_command_buffer.resource_size; + ret = copy_from_user(dst_ptr, (void *)virt_command_buffer.semaphores, + virt_command_buffer.semaphore_size); + if (ret) + return ret; + + ret = vq_out_send_sync(instance->vi, command); + if (ret) + return ret; + + ret = virtmagma_check_expected_response_type(request, response); + if (ret) + return ret; + + return 0; +} + static int virtmagma_command_magma_create_semaphore( struct virtmagma_instance *instance, struct virtmagma_virtio_command *command) @@ -1411,6 +1486,10 @@ int virtmagma_ioctl_magma_command(struct file *filp, void __user *ptr) ret = virtmagma_command_magma_submit_command_buffer(instance, &command); break; + case VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES: + ret = virtmagma_command_magma_execute_command_buffer_with_resources( + instance, &command); + break; case VIRTIO_MAGMA_CMD_CREATE_SEMAPHORE: ret = virtmagma_command_magma_create_semaphore(instance, &command);
diff --git a/include/uapi/linux/virtmagma.h b/include/uapi/linux/virtmagma.h index 5da7a3a..01bf455 100644 --- a/include/uapi/linux/virtmagma.h +++ b/include/uapi/linux/virtmagma.h
@@ -39,6 +39,15 @@ struct virtmagma_ioctl_args_magma_command { __u64 response_size; }; +struct virtmagma_command_buffer { + __u64 command_buffer_size; + __u64 command_buffer; + __u64 resource_size; + __u64 resources; + __u64 semaphore_size; + __u64 semaphores; +}; + #define VIRTMAGMA_IOCTL_HANDSHAKE VIRTMAGMA_IOWR(0x00, struct virtmagma_ioctl_args_handshake) #define VIRTMAGMA_IOCTL_GET_MMFD VIRTMAGMA_IOWR(0x01, struct virtmagma_ioctl_args_get_mmfd) #define VIRTMAGMA_IOCTL_MAGMA_COMMAND VIRTMAGMA_IOWR(0x02, struct virtmagma_ioctl_args_magma_command)