[virtio_magma][virtio_wl] Support for magma_import Change-Id: I72b488d6302bfd65f375a9aec2d9bcd5ba4ec725
diff --git a/drivers/virtio/virtio_magma.c b/drivers/virtio/virtio_magma.c index 7f49cb9..dc655cd 100644 --- a/drivers/virtio/virtio_magma.c +++ b/drivers/virtio/virtio_magma.c
@@ -1508,8 +1508,11 @@ static int virtmagma_command_magma_virt_get_image_info( #if IS_ENABLED(CONFIG_VIRTIO_WL) /* use the implementation in the virtio_wl module */ extern int virtwl_create_fd_for_vfd(void *filp_private_data, uint32_t vfd_id); +extern int virtwl_get_vfd_from_fd(void *filp_private_data, int fd, + uint32_t *vfd_id); #else #define virtwl_create_fd_for_vfd(a, b) (-ENODEV) +#define virtwl_get_vfd_from_fd(a, b, c) (-ENODEV) #endif static int @@ -1554,6 +1557,77 @@ static int return 0; } +static int + virtmagma_command_magma_import(struct virtmagma_instance *instance, + struct virtmagma_virtio_command *command) +{ + int ret; + struct virtmagma_connection *connection; + struct virtio_magma_import_ctrl *request = command->request_ptr; + struct virtio_magma_import_resp *response = command->response_ptr; + uint32_t vfd; + uint64_t buffer_size; + + if (!instance->wayland_device_private_data) + return -ENODEV; + + if (!COMMAND_OK(command, request, response)) + return -EINVAL; + + connection = get_connection(instance, request->connection); + if (!connection) + return -EINVAL; + + { + int fd = request->buffer_handle; + ret = virtwl_get_vfd_from_fd( + instance->wayland_device_private_data, fd, &vfd); + if (ret < 0) { + pr_err("virtmagma: failed to get vfd from fd %u", fd); + return ret; + } + } + + request->buffer_handle = vfd; + + ret = vq_out_send_sync(instance->vi, command); + if (ret) + return ret; + + ret = virtmagma_check_expected_response_type(request, response); + if (ret) + return ret; + + /* pass on magma errors without creating a vfd */ + if (response->result_return) { + pr_warn("virtmagma: magma_import returned %d", + (int32_t)response->result_return); + return 0; /* the ioctl is still successful */ + } + + ret = get_buffer_size(instance, response->buffer_out, &buffer_size); + if (ret) + return ret; + + { + struct virtmagma_connection_object *object = + kzalloc(sizeof(*object), GFP_KERNEL); + if (!object) + return -ENOMEM; + + object->parent_connection = connection; + object->host_value = response->buffer_out; + object->type = MAGMA_BUFFER; + object->buffer.size_requested = buffer_size; + object->buffer.size_allocated = buffer_size; + + hash_add(connection->objects, &object->node, + object->host_value); + } + + return 0; +} + static int virtmagma_command_magma_get_buffer_handle( struct virtmagma_instance *instance, struct virtmagma_virtio_command *command) @@ -1733,6 +1807,9 @@ int virtmagma_ioctl_magma_command(struct file *filp, void __user *ptr) case VIRTIO_MAGMA_CMD_EXPORT: ret = virtmagma_command_magma_export(instance, &command); break; + case VIRTIO_MAGMA_CMD_IMPORT: + ret = virtmagma_command_magma_import(instance, &command); + break; case VIRTIO_MAGMA_CMD_GET_BUFFER_HANDLE: ret = virtmagma_command_magma_get_buffer_handle(instance, &command);
diff --git a/drivers/virtio/virtio_wl.c b/drivers/virtio/virtio_wl.c index 3ee6225..5fdf9b7c 100644 --- a/drivers/virtio/virtio_wl.c +++ b/drivers/virtio/virtio_wl.c
@@ -946,6 +946,21 @@ int virtwl_create_fd_for_vfd(void *filp_private_data, uint32_t vfd_id) virtwl_vfd_file_flags(vfd) | O_CLOEXEC); } +int virtwl_get_vfd_from_fd(void *filp_private_data, int fd, uint32_t* vfd_id_out) { + struct fd f = fdget(fd); + + if (!f.file) + return -ENOENT; + + { + struct virtwl_vfd *vfd = f.file->private_data; + *vfd_id_out = vfd->id; + } + + fdput(f); + return 0; +} + static int virtwl_open(struct inode *inodep, struct file *filp) { struct virtwl_info *vi = container_of(inodep->i_cdev,