[virtmagma] Support for magma_poll Change-Id: Iba9ad6ec8a6cd735af46c3b9baca8937c41ff3b6
diff --git a/drivers/virtio/virtio_magma.c b/drivers/virtio/virtio_magma.c index 26ed77bb..6d12129 100644 --- a/drivers/virtio/virtio_magma.c +++ b/drivers/virtio/virtio_magma.c
@@ -1074,6 +1074,45 @@ static int virtmagma_command_magma_wait_semaphores( return virtmagma_check_expected_response_type(request, response); } +static int + virtmagma_command_magma_poll(struct virtmagma_instance *instance, + struct virtmagma_virtio_command *command) +{ + int ret; + size_t items_size; + struct virtio_magma_poll_ctrl *request = command->request_ptr; + struct virtio_magma_poll_resp *response = command->response_ptr; + + if (!COMMAND_OK(command, request, response)) + return -EINVAL; + + /* reallocate request buffer with enough space for the items */ + /* note: request->count is used as the byte count */ + items_size = request->count; + command->request_size = sizeof(*request) + items_size; + command->request_ptr = kzalloc(command->request_size, GFP_KERNEL); + if (!command->request_ptr) + return -ENOMEM; + + memcpy(command->request_ptr, request, sizeof(*request)); + ret = copy_from_user((char *)command->request_ptr + sizeof(*request), + (void *)request->items, items_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 copy_to_user((void *)request->items, + (char *)command->request_ptr + sizeof(*request), + items_size); +} + static int virtmagma_command_magma_read_notification_channel( struct virtmagma_instance *instance, struct virtmagma_virtio_command *command) @@ -1262,7 +1301,7 @@ int virtmagma_ioctl_magma_command(struct file *filp, void __user *ptr) switch (request_type) { case VIRTIO_MAGMA_CMD_CREATE_CONNECTION2: ret = virtmagma_command_magma_create_connection2(instance, - &command); + &command); break; case VIRTIO_MAGMA_CMD_RELEASE_CONNECTION: ret = virtmagma_command_magma_release_connection(instance, @@ -1302,6 +1341,9 @@ int virtmagma_ioctl_magma_command(struct file *filp, void __user *ptr) ret = virtmagma_command_magma_wait_semaphores(instance, &command); break; + case VIRTIO_MAGMA_CMD_POLL: + ret = virtmagma_command_magma_poll(instance, &command); + break; case VIRTIO_MAGMA_CMD_READ_NOTIFICATION_CHANNEL: ret = virtmagma_command_magma_read_notification_channel( instance, &command);
diff --git a/include/uapi/linux/virtio_magma.h b/include/uapi/linux/virtio_magma.h index 451566ea..fcf55b1 100644 --- a/include/uapi/linux/virtio_magma.h +++ b/include/uapi/linux/virtio_magma.h
@@ -62,6 +62,7 @@ enum virtio_magma_ctrl_type { VIRTIO_MAGMA_CMD_QUERY_RETURNS_BUFFER2 = 0x1031, VIRTIO_MAGMA_CMD_CREATE_CONNECTION2 = 0x1032, VIRTIO_MAGMA_CMD_INITIALIZE_LOGGING = 0x1033, + VIRTIO_MAGMA_CMD_POLL = 0x1034, /* magma success responses */ VIRTIO_MAGMA_RESP_RELEASE_CONNECTION = 0x2004, VIRTIO_MAGMA_RESP_GET_ERROR = 0x2005, @@ -107,6 +108,7 @@ enum virtio_magma_ctrl_type { VIRTIO_MAGMA_RESP_QUERY_RETURNS_BUFFER2 = 0x2031, VIRTIO_MAGMA_RESP_CREATE_CONNECTION2 = 0x2032, VIRTIO_MAGMA_RESP_INITIALIZE_LOGGING = 0x2033, + VIRTIO_MAGMA_RESP_POLL = 0x2034, /* magma error responses */ VIRTIO_MAGMA_RESP_ERR_UNIMPLEMENTED = 0x3001, VIRTIO_MAGMA_RESP_ERR_INTERNAL = 0x3002, @@ -206,6 +208,8 @@ inline const char* virtio_magma_ctrl_type_string(enum virtio_magma_ctrl_type typ case VIRTIO_MAGMA_RESP_CREATE_CONNECTION2: return "VIRTIO_MAGMA_RESP_CREATE_CONNECTION2"; case VIRTIO_MAGMA_CMD_INITIALIZE_LOGGING: return "VIRTIO_MAGMA_CMD_INITIALIZE_LOGGING"; case VIRTIO_MAGMA_RESP_INITIALIZE_LOGGING: return "VIRTIO_MAGMA_RESP_INITIALIZE_LOGGING"; + case VIRTIO_MAGMA_CMD_POLL: return "VIRTIO_MAGMA_CMD_POLL"; + case VIRTIO_MAGMA_RESP_POLL: return "VIRTIO_MAGMA_RESP_POLL"; case VIRTIO_MAGMA_RESP_ERR_UNIMPLEMENTED: return "VIRTIO_MAGMA_RESP_ERR_UNIMPLEMENTED"; case VIRTIO_MAGMA_RESP_ERR_INTERNAL: return "VIRTIO_MAGMA_RESP_ERR_INTERNAL"; case VIRTIO_MAGMA_RESP_ERR_HOST_DISCONNECTED: return "VIRTIO_MAGMA_RESP_ERR_HOST_DISCONNECTED"; @@ -262,6 +266,7 @@ inline enum virtio_magma_ctrl_type virtio_magma_expected_response_type(enum virt case VIRTIO_MAGMA_CMD_QUERY_RETURNS_BUFFER2: return VIRTIO_MAGMA_RESP_QUERY_RETURNS_BUFFER2; case VIRTIO_MAGMA_CMD_CREATE_CONNECTION2: return VIRTIO_MAGMA_RESP_CREATE_CONNECTION2; case VIRTIO_MAGMA_CMD_INITIALIZE_LOGGING: return VIRTIO_MAGMA_RESP_INITIALIZE_LOGGING; + case VIRTIO_MAGMA_CMD_POLL: return VIRTIO_MAGMA_RESP_POLL; default: return VIRTIO_MAGMA_RESP_ERR_INVALID_COMMAND; } } @@ -764,4 +769,16 @@ struct virtio_magma_initialize_logging_resp { __le64 result_return; } __attribute((packed)); +struct virtio_magma_poll_ctrl { + struct virtio_magma_ctrl_hdr hdr; + __le64 items; + __le32 count; + __le64 timeout_ns; +} __attribute((packed)); + +struct virtio_magma_poll_resp { + struct virtio_magma_ctrl_hdr hdr; + __le64 result_return; +} __attribute((packed)); + #endif /* _LINUX_VIRTIO_MAGMA_H */