Support magma_execute_command_buffer_with_resources2

Change-Id: I76a35ffb577e62e0eb8b2bb911944aaa31c177eb
diff --git a/drivers/virtio/virtio_magma.c b/drivers/virtio/virtio_magma.c
index 49f5b3f..31c7c370 100644
--- a/drivers/virtio/virtio_magma.c
+++ b/drivers/virtio/virtio_magma.c
@@ -1015,6 +1015,81 @@
 	return 0;
 }
 
+static int virtmagma_command_magma_execute_command_buffer_with_resources2(
+	struct virtmagma_instance *instance,
+	struct virtmagma_virtio_command *command)
+{
+	struct virtio_magma_execute_command_buffer_with_resources2_ctrl *request =
+		command->request_ptr;
+	struct virtio_magma_execute_command_buffer_with_resources2_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)
@@ -1727,6 +1802,10 @@
 		ret = virtmagma_command_magma_execute_command_buffer_with_resources(
 			instance, &command);
 		break;
+	case VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2:
+		ret = virtmagma_command_magma_execute_command_buffer_with_resources2(
+			instance, &command);
+		break;
 	case VIRTIO_MAGMA_CMD_CREATE_SEMAPHORE:
 		ret = virtmagma_command_magma_create_semaphore(instance,
 							       &command);
diff --git a/include/uapi/linux/virtio_magma.h b/include/uapi/linux/virtio_magma.h
index 7925f9d..4c93d2e 100644
--- a/include/uapi/linux/virtio_magma.h
+++ b/include/uapi/linux/virtio_magma.h
@@ -72,6 +72,7 @@
 	VIRTIO_MAGMA_CMD_VIRT_CREATE_IMAGE = 0x1047,
 	VIRTIO_MAGMA_CMD_VIRT_GET_IMAGE_INFO = 0x1048,
 	VIRTIO_MAGMA_CMD_SYNC = 0x1049,
+	VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2 = 0x104A,
 	VIRTIO_MAGMA_CMD_INTERNAL_MAP = 0x1044,
 	VIRTIO_MAGMA_CMD_INTERNAL_UNMAP = 0x1045,
 	/* magma success responses
@@ -127,6 +128,7 @@
 	VIRTIO_MAGMA_RESP_VIRT_CREATE_IMAGE = 0x2047,
 	VIRTIO_MAGMA_RESP_VIRT_GET_IMAGE_INFO = 0x2048,
 	VIRTIO_MAGMA_RESP_SYNC = 0x2049,
+	VIRTIO_MAGMA_RESP_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2 = 0x204A,
 	VIRTIO_MAGMA_RESP_INTERNAL_MAP = 0x2044,
 	VIRTIO_MAGMA_RESP_INTERNAL_UNMAP = 0x2045,
 	/* magma error responses
@@ -243,6 +245,8 @@
 		case VIRTIO_MAGMA_RESP_VIRT_GET_IMAGE_INFO: return "VIRTIO_MAGMA_RESP_VIRT_GET_IMAGE_INFO";
 		case VIRTIO_MAGMA_CMD_SYNC: return "VIRTIO_MAGMA_CMD_SYNC";
 		case VIRTIO_MAGMA_RESP_SYNC: return "VIRTIO_MAGMA_RESP_SYNC";
+		case VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2: return "VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2";
+		case VIRTIO_MAGMA_RESP_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2: return "VIRTIO_MAGMA_RESP_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2";
 		case VIRTIO_MAGMA_CMD_INTERNAL_MAP: return "VIRTIO_MAGMA_CMD_INTERNAL_MAP";
 		case VIRTIO_MAGMA_RESP_INTERNAL_MAP: return "VIRTIO_MAGMA_RESP_INTERNAL_MAP";
 		case VIRTIO_MAGMA_CMD_INTERNAL_UNMAP: return "VIRTIO_MAGMA_CMD_INTERNAL_UNMAP";
@@ -310,6 +314,7 @@
 		case VIRTIO_MAGMA_CMD_VIRT_CREATE_IMAGE: return VIRTIO_MAGMA_RESP_VIRT_CREATE_IMAGE;
 		case VIRTIO_MAGMA_CMD_VIRT_GET_IMAGE_INFO: return VIRTIO_MAGMA_RESP_VIRT_GET_IMAGE_INFO;
 		case VIRTIO_MAGMA_CMD_SYNC: return VIRTIO_MAGMA_RESP_SYNC;
+		case VIRTIO_MAGMA_CMD_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2: return VIRTIO_MAGMA_RESP_EXECUTE_COMMAND_BUFFER_WITH_RESOURCES2;
 		case VIRTIO_MAGMA_CMD_INTERNAL_MAP: return VIRTIO_MAGMA_RESP_INTERNAL_MAP;
 		case VIRTIO_MAGMA_CMD_INTERNAL_UNMAP: return VIRTIO_MAGMA_RESP_INTERNAL_UNMAP;
 		default: return VIRTIO_MAGMA_RESP_ERR_INVALID_COMMAND;
@@ -348,6 +353,7 @@
 struct virtio_magma_create_context_resp {
 	struct virtio_magma_ctrl_hdr hdr;
 	uintptr_t context_id_out;
+	__le64 result_return;
 } __attribute((packed));
 
 struct virtio_magma_release_context_ctrl {
@@ -450,6 +456,7 @@
 
 struct virtio_magma_map_buffer_gpu_resp {
 	struct virtio_magma_ctrl_hdr hdr;
+	__le64 result_return;
 } __attribute((packed));
 
 struct virtio_magma_unmap_buffer_gpu_ctrl {
@@ -511,6 +518,7 @@
 
 struct virtio_magma_execute_command_buffer_with_resources_resp {
 	struct virtio_magma_ctrl_hdr hdr;
+	__le64 result_return;
 } __attribute((packed));
 
 struct virtio_magma_execute_immediate_commands2_ctrl {
@@ -523,6 +531,7 @@
 
 struct virtio_magma_execute_immediate_commands2_resp {
 	struct virtio_magma_ctrl_hdr hdr;
+	__le64 result_return;
 } __attribute((packed));
 
 struct virtio_magma_create_semaphore_ctrl {
@@ -904,6 +913,20 @@
 	__le64 result_return;
 } __attribute((packed));
 
+struct virtio_magma_execute_command_buffer_with_resources2_ctrl {
+	struct virtio_magma_ctrl_hdr hdr;
+	__le64 connection;
+	__le32 context_id;
+	uintptr_t command_buffer;
+	uintptr_t resources;
+	uintptr_t semaphore_ids;
+} __attribute((packed));
+
+struct virtio_magma_execute_command_buffer_with_resources2_resp {
+	struct virtio_magma_ctrl_hdr hdr;
+	__le64 result_return;
+} __attribute((packed));
+
 struct virtio_magma_internal_map_ctrl {
 	struct virtio_magma_ctrl_hdr hdr;
 	__le64 connection;