]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Revert "staging: vc04_services: remove vchiq_copy_from_user"
authorpopcornmix <popcornmix@gmail.com>
Tue, 27 Dec 2016 22:13:42 +0000 (22:13 +0000)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 19 Sep 2017 10:07:47 +0000 (12:07 +0200)
This reverts commit 49bec49fd7f273ec114e2e533c1bb8f21a654aaf.

drivers/staging/vc04_services/interface/vchi/vchi.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c

index d6937288210cef102e115f4265471ad9e9da7007..1b17e98f737979eef19906609bc19ecd19455618 100644 (file)
@@ -226,12 +226,25 @@ extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle,
                                        int value);
 
 // Routine to send a message across a service
-extern int32_t
-       vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
-                      ssize_t (*copy_callback)(void *context, void *dest,
-                                               size_t offset, size_t maxsize),
-                      void *context,
-                      uint32_t data_size);
+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
+                               const void *data,
+                               uint32_t data_size,
+                               VCHI_FLAGS_T flags,
+                               void *msg_handle );
+
+// scatter-gather (vector) and send message
+int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle,
+                            VCHI_MSG_VECTOR_EX_T *vector,
+                            uint32_t count,
+                            VCHI_FLAGS_T flags,
+                            void *msg_handle );
+
+// legacy scatter-gather (vector) and send message, only handles pointers
+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,
+                         VCHI_MSG_VECTOR_T *vector,
+                         uint32_t count,
+                         VCHI_FLAGS_T flags,
+                         void *msg_handle );
 
 // Routine to receive a msg from a service
 // Dequeue is equivalent to hold, copy into client buffer, release
index 2b500d85cebc768373a2dd48c779063262b52570..706e7f936c1a97352f7ef3d3fbd3b4a92943165d 100644 (file)
@@ -232,6 +232,17 @@ remote_event_signal(REMOTE_EVENT_T *event)
                writel(0, g_regs + BELL2); /* trigger vc interrupt */
 }
 
+int
+vchiq_copy_from_user(void *dst, const void *src, int size)
+{
+       if ((uint32_t)src < TASK_SIZE) {
+               return copy_from_user(dst, src, size);
+       } else {
+               memcpy(dst, src, size);
+               return 0;
+       }
+}
+
 VCHIQ_STATUS_T
 vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle,
        void *offset, int size, int dir)
index 610e0d6d93bbcb8400f888014d2b4cef064dd976..d5f5c904f15b4fdbf1055befbec0bfe33b805efc 100644 (file)
@@ -402,107 +402,6 @@ static void close_delivered(USER_SERVICE_T *user_service)
        }
 }
 
-struct vchiq_io_copy_callback_context {
-       VCHIQ_ELEMENT_T *current_element;
-       size_t current_element_offset;
-       unsigned long elements_to_go;
-       size_t current_offset;
-};
-
-static ssize_t
-vchiq_ioc_copy_element_data(
-       void *context,
-       void *dest,
-       size_t offset,
-       size_t maxsize)
-{
-       long res;
-       size_t bytes_this_round;
-       struct vchiq_io_copy_callback_context *copy_context =
-               (struct vchiq_io_copy_callback_context *)context;
-
-       if (offset != copy_context->current_offset)
-               return 0;
-
-       if (!copy_context->elements_to_go)
-               return 0;
-
-       /*
-        * Complex logic here to handle the case of 0 size elements
-        * in the middle of the array of elements.
-        *
-        * Need to skip over these 0 size elements.
-        */
-       while (1) {
-               bytes_this_round = min(copy_context->current_element->size -
-                                      copy_context->current_element_offset,
-                                      maxsize);
-
-               if (bytes_this_round)
-                       break;
-
-               copy_context->elements_to_go--;
-               copy_context->current_element++;
-               copy_context->current_element_offset = 0;
-
-               if (!copy_context->elements_to_go)
-                       return 0;
-       }
-
-       res = copy_from_user(dest,
-                            copy_context->current_element->data +
-                            copy_context->current_element_offset,
-                            bytes_this_round);
-
-       if (res != 0)
-               return -EFAULT;
-
-       copy_context->current_element_offset += bytes_this_round;
-       copy_context->current_offset += bytes_this_round;
-
-       /*
-        * Check if done with current element, and if so advance to the next.
-        */
-       if (copy_context->current_element_offset ==
-           copy_context->current_element->size) {
-               copy_context->elements_to_go--;
-               copy_context->current_element++;
-               copy_context->current_element_offset = 0;
-       }
-
-       return bytes_this_round;
-}
-
-/**************************************************************************
- *
- *   vchiq_ioc_queue_message
- *
- **************************************************************************/
-static VCHIQ_STATUS_T
-vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
-                       VCHIQ_ELEMENT_T *elements,
-                       unsigned long count)
-{
-       struct vchiq_io_copy_callback_context context;
-       unsigned long i;
-       size_t total_size = 0;
-
-       context.current_element = elements;
-       context.current_element_offset = 0;
-       context.elements_to_go = count;
-       context.current_offset = 0;
-
-       for (i = 0; i < count; i++) {
-               if (!elements[i].data && elements[i].size != 0)
-                       return -EFAULT;
-
-               total_size += elements[i].size;
-       }
-
-       return vchiq_queue_message(handle, vchiq_ioc_copy_element_data,
-                                  &context, total_size);
-}
-
 /****************************************************************************
 *
 *   vchiq_ioctl
@@ -752,7 +651,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        VCHIQ_ELEMENT_T elements[MAX_ELEMENTS];
                        if (copy_from_user(elements, args.elements,
                                args.count * sizeof(VCHIQ_ELEMENT_T)) == 0)
-                               status = vchiq_ioc_queue_message
+                               status = vchiq_queue_message
                                        (args.handle,
                                        elements, args.count);
                        else
index 028e90bc1cdcc3f305ce5b97b88dd5c6c4613a50..c5b06cc4ca53135ec9491116ca79beaa98f57bcc 100644 (file)
@@ -464,8 +464,8 @@ remote_event_pollall(VCHIQ_STATE_T *state)
 ** enough for a header. This relies on header size being a power of two, which
 ** has been verified earlier by a static assertion. */
 
-static inline size_t
-calc_stride(size_t size)
+static inline unsigned int
+calc_stride(unsigned int size)
 {
        /* Allow room for the header */
        size += sizeof(VCHIQ_HEADER_T);
@@ -544,7 +544,7 @@ request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type)
 /* Called from queue_message, by the slot handler and application threads,
 ** with slot_mutex held */
 static VCHIQ_HEADER_T *
-reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking)
 {
        VCHIQ_SHARED_STATE_T *local = state->local;
        int tx_pos = state->local_tx_pos;
@@ -726,66 +726,18 @@ process_free_queue(VCHIQ_STATE_T *state)
        }
 }
 
-static ssize_t
-memcpy_copy_callback(
-       void *context, void *dest,
-       size_t offset, size_t maxsize)
-{
-       void *src = context;
-
-       memcpy(dest + offset, src + offset, maxsize);
-       return maxsize;
-}
-
-static ssize_t
-copy_message_data(
-       ssize_t (*copy_callback)(void *context, void *dest,
-                                size_t offset, size_t maxsize),
-       void *context,
-       void *dest,
-       size_t size)
-{
-       size_t pos = 0;
-
-       while (pos < size) {
-               ssize_t callback_result;
-               size_t max_bytes = size - pos;
-
-               callback_result =
-                       copy_callback(context, dest + pos,
-                                     pos, max_bytes);
-
-               if (callback_result < 0)
-                       return callback_result;
-
-               if (!callback_result)
-                       return -EIO;
-
-               if (callback_result > max_bytes)
-                       return -EIO;
-
-               pos += callback_result;
-       }
-
-       return size;
-}
-
 /* Called by the slot handler and application threads */
 static VCHIQ_STATUS_T
 queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
-       int msgid,
-       ssize_t (*copy_callback)(void *context, void *dest,
-                                size_t offset, size_t maxsize),
-       void *context,
-       size_t size,
-       int flags)
+       int msgid, const VCHIQ_ELEMENT_T *elements,
+       int count, int size, int flags)
 {
        VCHIQ_SHARED_STATE_T *local;
        VCHIQ_SERVICE_QUOTA_T *service_quota = NULL;
        VCHIQ_HEADER_T *header;
        int type = VCHIQ_MSG_TYPE(msgid);
 
-       size_t stride;
+       unsigned int stride;
 
        local = state->local;
 
@@ -891,7 +843,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
        }
 
        if (type == VCHIQ_MSG_DATA) {
-               ssize_t callback_result;
+               int i, pos;
                int tx_end_index;
                int slot_use_count;
 
@@ -905,23 +857,27 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
                BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK |
                                 QMFLAGS_NO_MUTEX_UNLOCK)) != 0);
 
-               callback_result =
-                       copy_message_data(copy_callback, context,
-                                         header->data, size);
-
-               if (callback_result < 0) {
-                       mutex_unlock(&state->slot_mutex);
-                       VCHIQ_SERVICE_STATS_INC(service,
+               for (i = 0, pos = 0; i < (unsigned int)count;
+                       pos += elements[i++].size)
+                       if (elements[i].size) {
+                               if (vchiq_copy_from_user
+                                       (header->data + pos, elements[i].data,
+                                       (size_t) elements[i].size) !=
+                                       VCHIQ_SUCCESS) {
+                                       mutex_unlock(&state->slot_mutex);
+                                       VCHIQ_SERVICE_STATS_INC(service,
                                                error_count);
-                       return VCHIQ_ERROR;
-               }
-
-               if (SRVTRACE_ENABLED(service,
-                                    VCHIQ_LOG_INFO))
-                       vchiq_log_dump_mem("Sent", 0,
-                                          header->data,
-                                          min((size_t)64,
-                                              (size_t)callback_result));
+                                       return VCHIQ_ERROR;
+                               }
+                               if (i == 0) {
+                                       if (SRVTRACE_ENABLED(service,
+                                                       VCHIQ_LOG_INFO))
+                                               vchiq_log_dump_mem("Sent", 0,
+                                                       header->data + pos,
+                                                       min(64u,
+                                                       elements[0].size));
+                               }
+                       }
 
                spin_lock(&quota_spinlock);
                service_quota->message_use_count++;
@@ -963,17 +919,9 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
                        header, size, VCHIQ_MSG_SRCPORT(msgid),
                        VCHIQ_MSG_DSTPORT(msgid));
                if (size != 0) {
-                       /* It is assumed for now that this code path
-                        * only happens from calls inside this file.
-                        *
-                        * External callers are through the vchiq_queue_message
-                        * path which always sets the type to be VCHIQ_MSG_DATA
-                        *
-                        * At first glance this appears to be correct but
-                        * more review is needed.
-                        */
-                       copy_message_data(copy_callback, context,
-                                         header->data, size);
+                       WARN_ON(!((count == 1) && (size == elements[0].size)));
+                       memcpy(header->data, elements[0].data,
+                               elements[0].size);
                }
                VCHIQ_STATS_INC(state, ctrl_tx_count);
        }
@@ -1019,16 +967,11 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
 /* Called by the slot handler and application threads */
 static VCHIQ_STATUS_T
 queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
-       int msgid,
-       ssize_t (*copy_callback)(void *context, void *dest,
-                                size_t offset, size_t maxsize),
-       void *context,
-       int size,
-       int is_blocking)
+       int msgid, const VCHIQ_ELEMENT_T *elements,
+       int count, int size, int is_blocking)
 {
        VCHIQ_SHARED_STATE_T *local;
        VCHIQ_HEADER_T *header;
-       ssize_t callback_result;
 
        local = state->local;
 
@@ -1051,34 +994,50 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
                                state->id, oldmsgid);
        }
 
-       vchiq_log_info(vchiq_sync_log_level,
-                      "%d: qms %s@%pK,%x (%d->%d)", state->id,
-                      msg_type_str(VCHIQ_MSG_TYPE(msgid)),
-                      header, size, VCHIQ_MSG_SRCPORT(msgid),
-                      VCHIQ_MSG_DSTPORT(msgid));
-
-       callback_result =
-               copy_message_data(copy_callback, context,
-                                 header->data, size);
+       if (service) {
+               int i, pos;
 
-       if (callback_result < 0) {
-               mutex_unlock(&state->slot_mutex);
-               VCHIQ_SERVICE_STATS_INC(service,
-                                       error_count);
-               return VCHIQ_ERROR;
-       }
+               vchiq_log_info(vchiq_sync_log_level,
+                       "%d: qms %s@%pK,%x (%d->%d)", state->id,
+                       msg_type_str(VCHIQ_MSG_TYPE(msgid)),
+                       header, size, VCHIQ_MSG_SRCPORT(msgid),
+                       VCHIQ_MSG_DSTPORT(msgid));
 
-       if (service) {
-               if (SRVTRACE_ENABLED(service,
-                                    VCHIQ_LOG_INFO))
-                       vchiq_log_dump_mem("Sent", 0,
-                                          header->data,
-                                          min((size_t)64,
-                                              (size_t)callback_result));
+               for (i = 0, pos = 0; i < (unsigned int)count;
+                       pos += elements[i++].size)
+                       if (elements[i].size) {
+                               if (vchiq_copy_from_user
+                                       (header->data + pos, elements[i].data,
+                                       (size_t) elements[i].size) !=
+                                       VCHIQ_SUCCESS) {
+                                       mutex_unlock(&state->sync_mutex);
+                                       VCHIQ_SERVICE_STATS_INC(service,
+                                               error_count);
+                                       return VCHIQ_ERROR;
+                               }
+                               if (i == 0) {
+                                       if (vchiq_sync_log_level >=
+                                               VCHIQ_LOG_TRACE)
+                                               vchiq_log_dump_mem("Sent Sync",
+                                                       0, header->data + pos,
+                                                       min(64u,
+                                                       elements[0].size));
+                               }
+                       }
 
                VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
                VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
        } else {
+               vchiq_log_info(vchiq_sync_log_level,
+                       "%d: qms %s@%pK,%x (%d->%d)", state->id,
+                       msg_type_str(VCHIQ_MSG_TYPE(msgid)),
+                       header, size, VCHIQ_MSG_SRCPORT(msgid),
+                       VCHIQ_MSG_DSTPORT(msgid));
+               if (size != 0) {
+                       WARN_ON(!((count == 1) && (size == elements[0].size)));
+                       memcpy(header->data, elements[0].data,
+                               elements[0].size);
+               }
                VCHIQ_STATS_INC(state, ctrl_tx_count);
        }
 
@@ -1191,16 +1150,11 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,
                                VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE;
                        int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport,
                                service->remoteport);
+                       VCHIQ_ELEMENT_T element = { &bulk->actual, 4 };
                        /* Only reply to non-dummy bulk requests */
                        if (bulk->remote_data) {
-                               status = queue_message(
-                                               service->state,
-                                               NULL,
-                                               msgid,
-                                               memcpy_copy_callback,
-                                               &bulk->actual,
-                                               4,
-                                               0);
+                               status = queue_message(service->state, NULL,
+                                       msgid, &element, 1, 4, 0);
                                if (status != VCHIQ_SUCCESS)
                                        break;
                        }
@@ -1560,6 +1514,10 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)
                                struct vchiq_openack_payload ack_payload = {
                                        service->version
                                };
+                               VCHIQ_ELEMENT_T body = {
+                                       &ack_payload,
+                                       sizeof(ack_payload)
+                               };
 
                                if (state->version_common <
                                    VCHIQ_VERSION_SYNCHRONOUS_MODE)
@@ -1569,28 +1527,21 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header)
                                if (service->sync &&
                                    (state->version_common >=
                                     VCHIQ_VERSION_SYNCHRONOUS_MODE)) {
-                                       if (queue_message_sync(
-                                               state,
-                                               NULL,
+                                       if (queue_message_sync(state, NULL,
                                                VCHIQ_MAKE_MSG(
                                                        VCHIQ_MSG_OPENACK,
                                                        service->localport,
                                                        remoteport),
-                                               memcpy_copy_callback,
-                                               &ack_payload,
-                                               sizeof(ack_payload),
+                                               &body, 1, sizeof(ack_payload),
                                                0) == VCHIQ_RETRY)
                                                goto bail_not_ready;
                                } else {
-                                       if (queue_message(state,
-                                                       NULL,
-                                                       VCHIQ_MAKE_MSG(
+                                       if (queue_message(state, NULL,
+                                               VCHIQ_MAKE_MSG(
                                                        VCHIQ_MSG_OPENACK,
                                                        service->localport,
                                                        remoteport),
-                                               memcpy_copy_callback,
-                                               &ack_payload,
-                                               sizeof(ack_payload),
+                                               &body, 1, sizeof(ack_payload),
                                                0) == VCHIQ_RETRY)
                                                goto bail_not_ready;
                                }
@@ -2680,19 +2631,14 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id)
                service->version,
                service->version_min
        };
+       VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) };
        VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
 
        service->client_id = client_id;
        vchiq_use_service_internal(service);
-       status = queue_message(service->state,
-                              NULL,
-                              VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN,
-                                             service->localport,
-                                             0),
-                              memcpy_copy_callback,
-                              &payload,
-                              sizeof(payload),
-                              QMFLAGS_IS_BLOCKING);
+       status = queue_message(service->state, NULL,
+               VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0),
+               &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING);
        if (status == VCHIQ_SUCCESS) {
                /* Wait for the ACK/NAK */
                if (down_interruptible(&service->remove_event) != 0) {
@@ -3360,18 +3306,15 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
                                VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY);
        } else {
                int payload[2] = { (int)(long)bulk->data, bulk->size };
+               VCHIQ_ELEMENT_T element = { payload, sizeof(payload) };
 
-               status = queue_message(state,
-                                      NULL,
-                                      VCHIQ_MAKE_MSG(dir_msgtype,
-                                                     service->localport,
-                                                     service->remoteport),
-                                      memcpy_copy_callback,
-                                      &payload,
-                                      sizeof(payload),
-                                      QMFLAGS_IS_BLOCKING |
-                                      QMFLAGS_NO_MUTEX_LOCK |
-                                      QMFLAGS_NO_MUTEX_UNLOCK);
+               status = queue_message(state, NULL,
+                       VCHIQ_MAKE_MSG(dir_msgtype,
+                               service->localport, service->remoteport),
+                       &element, 1, sizeof(payload),
+                       QMFLAGS_IS_BLOCKING |
+                       QMFLAGS_NO_MUTEX_LOCK |
+                       QMFLAGS_NO_MUTEX_UNLOCK);
                if (status != VCHIQ_SUCCESS) {
                        goto unlock_both_error_exit;
                }
@@ -3417,22 +3360,26 @@ error_exit:
 
 VCHIQ_STATUS_T
 vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
-                   ssize_t (*copy_callback)(void *context, void *dest,
-                                            size_t offset, size_t maxsize),
-                   void *context,
-                   size_t size)
+       const VCHIQ_ELEMENT_T *elements, unsigned int count)
 {
        VCHIQ_SERVICE_T *service = find_service_by_handle(handle);
        VCHIQ_STATUS_T status = VCHIQ_ERROR;
 
+       unsigned int size = 0;
+       unsigned int i;
+
        if (!service ||
                (vchiq_check_service(service) != VCHIQ_SUCCESS))
                goto error_exit;
 
-       if (!size) {
-               VCHIQ_SERVICE_STATS_INC(service, error_count);
-               goto error_exit;
-
+       for (i = 0; i < (unsigned int)count; i++) {
+               if (elements[i].size) {
+                       if (elements[i].data == NULL) {
+                               VCHIQ_SERVICE_STATS_INC(service, error_count);
+                               goto error_exit;
+                       }
+                       size += elements[i].size;
+               }
        }
 
        if (size > VCHIQ_MAX_MSG_SIZE) {
@@ -3446,14 +3393,14 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
                                VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA,
                                        service->localport,
                                        service->remoteport),
-                               copy_callback, context, size, 1);
+                               elements, count, size, 1);
                break;
        case VCHIQ_SRVSTATE_OPENSYNC:
                status = queue_message_sync(service->state, service,
                                VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA,
                                        service->localport,
                                        service->remoteport),
-                               copy_callback, context, size, 1);
+                               elements, count, size, 1);
                break;
        default:
                status = VCHIQ_ERROR;
index 9e164652548a42bac2646166e16961b88bc80594..1c2b1b5b8cc998f6f0490dc6460d8408e85f624b 100644 (file)
@@ -634,6 +634,9 @@ vchiq_transfer_bulk(VCHIQ_BULK_T *bulk);
 extern void
 vchiq_complete_bulk(VCHIQ_BULK_T *bulk);
 
+extern VCHIQ_STATUS_T
+vchiq_copy_from_user(void *dst, const void *src, int size);
+
 extern void
 remote_event_signal(REMOTE_EVENT_T *event);
 
index 377e8e48bb540465b34f2d4697504cb188d83e3b..8067bbe7ce8d70c41b2e6e0466d20a4612e39d93 100644 (file)
@@ -141,12 +141,9 @@ extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service);
 extern VCHIQ_STATUS_T vchiq_use_service_no_resume(
        VCHIQ_SERVICE_HANDLE_T service);
 extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service);
-extern VCHIQ_STATUS_T
-vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle,
-                   ssize_t (*copy_callback)(void *context, void *dest,
-                                            size_t offset, size_t maxsize),
-                   void *context,
-                   size_t size);
+
+extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service,
+       const VCHIQ_ELEMENT_T *elements, unsigned int count);
 extern void           vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service,
        VCHIQ_HEADER_T *header);
 extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,
index d9771394a041bbb55daacd7744ac57758ae198d1..7694627b925c743552b093ce51d15c2f2fe71a69 100644 (file)
@@ -148,10 +148,10 @@ EXPORT_SYMBOL(vchi_msg_remove);
  * Name: vchi_msg_queue
  *
  * Arguments:  VCHI_SERVICE_HANDLE_T handle,
- *             ssize_t (*copy_callback)(void *context, void *dest,
- *                                     size_t offset, size_t maxsize),
- *            void *context,
- *             uint32_t data_size
+ *             const void *data,
+ *             uint32_t data_size,
+ *             VCHI_FLAGS_T flags,
+ *             void *msg_handle,
  *
  * Description: Thin wrapper to queue a message onto a connection
  *
@@ -159,19 +159,21 @@ EXPORT_SYMBOL(vchi_msg_remove);
  *
  ***********************************************************/
 int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
-       ssize_t (*copy_callback)(void *context, void *dest,
-                                size_t offset, size_t maxsize),
-       void *context,
-       uint32_t data_size)
+       const void *data,
+       uint32_t data_size,
+       VCHI_FLAGS_T flags,
+       void *msg_handle)
 {
        SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
+       VCHIQ_ELEMENT_T element = {data, data_size};
        VCHIQ_STATUS_T status;
 
+       (void)msg_handle;
+
+       WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
+
        while (1) {
-               status = vchiq_queue_message(service->handle,
-                                            copy_callback,
-                                            context,
-                                            data_size);
+               status = vchiq_queue_message(service->handle, &element, 1);
 
                /*
                 * vchiq_queue_message() may return VCHIQ_RETRY, so we need to
@@ -353,6 +355,44 @@ int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
 }
 EXPORT_SYMBOL(vchi_msg_dequeue);
 
+/***********************************************************
+ * Name: vchi_msg_queuev
+ *
+ * Arguments:  VCHI_SERVICE_HANDLE_T handle,
+ *             VCHI_MSG_VECTOR_T *vector,
+ *             uint32_t count,
+ *             VCHI_FLAGS_T flags,
+ *             void *msg_handle
+ *
+ * Description: Thin wrapper to queue a message onto a connection
+ *
+ * Returns: int32_t - success == 0
+ *
+ ***********************************************************/
+
+vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) ==
+       offsetof(VCHIQ_ELEMENT_T, data));
+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) ==
+       offsetof(VCHIQ_ELEMENT_T, size));
+
+int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle,
+       VCHI_MSG_VECTOR_T *vector,
+       uint32_t count,
+       VCHI_FLAGS_T flags,
+       void *msg_handle)
+{
+       SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
+
+       (void)msg_handle;
+
+       WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
+
+       return vchiq_status_to_vchi(vchiq_queue_message(service->handle,
+               (const VCHIQ_ELEMENT_T *)vector, count));
+}
+EXPORT_SYMBOL(vchi_msg_queuev);
+
 /***********************************************************
  * Name: vchi_held_msg_release
  *