staging: vchiq: Move message queue into struct vchiq_service
authorNicolas Saenz Julienne <nsaenzjulienne@suse.de>
Mon, 29 Jun 2020 15:09:21 +0000 (17:09 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 1 Jul 2020 13:47:05 +0000 (15:47 +0200)
This has historically been handled by vchi, but there is no reason why
this couldn't be handled directly in vchiq.

The patch tries to avoid altering any behavior, with the exception of
the msg_queue size, which is now fixed to VCHIQ_MAX_SLOTS (it was set to
VCHIQ_MAX_SLOTS / 2). This is done to match vchiq's user_service message
queue, which could be merged with this one in the future.

Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Link: https://lore.kernel.org/r/20200629150945.10720-24-nsaenzjulienne@suse.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/vc04_services/Makefile
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
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c [deleted file]
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h

index d37f21d1a219da42350624cfbe00a66cceb4c029..922990919c40c5411baa63dda1ac21e7770d4a07 100644 (file)
@@ -7,7 +7,6 @@ vchiq-objs := \
    interface/vchiq_arm/vchiq_2835_arm.o \
    interface/vchiq_arm/vchiq_debugfs.o \
    interface/vchiq_arm/vchiq_shim.o \
-   interface/vchiq_arm/vchiq_util.o \
    interface/vchiq_arm/vchiq_connected.o \
 
 obj-$(CONFIG_SND_BCM2835)              += bcm2835-audio/
index 0a2419bd305bd17e636087072aa99851b0c348d6..fe8ce6880e49c40535403fe616af516bcd00593d 100644 (file)
@@ -2265,6 +2265,47 @@ fail_free_handler_thread:
        return VCHIQ_ERROR;
 }
 
+void vchiq_msg_queue_push(unsigned handle, struct vchiq_header *header)
+{
+       struct vchiq_service *service = find_service_by_handle(handle);
+       int pos;
+
+       while (service->msg_queue_write == service->msg_queue_read +
+               VCHIQ_MAX_SLOTS) {
+               if (wait_for_completion_interruptible(&service->msg_queue_pop))
+                       flush_signals(current);
+       }
+
+       pos = service->msg_queue_write++ & (VCHIQ_MAX_SLOTS - 1);
+       service->msg_queue[pos] = header;
+
+       complete(&service->msg_queue_push);
+}
+EXPORT_SYMBOL(vchiq_msg_queue_push);
+
+struct vchiq_header *vchiq_msg_hold(unsigned handle)
+{
+       struct vchiq_service *service = find_service_by_handle(handle);
+       struct vchiq_header *header;
+       int pos;
+
+       if (service->msg_queue_write == service->msg_queue_read)
+               return NULL;
+
+       while (service->msg_queue_write == service->msg_queue_read) {
+               if (wait_for_completion_interruptible(&service->msg_queue_push))
+                       flush_signals(current);
+       }
+
+       pos = service->msg_queue_read++ & (VCHIQ_MAX_SLOTS - 1);
+       header = service->msg_queue[pos];
+
+       complete(&service->msg_queue_pop);
+
+       return header;
+}
+EXPORT_SYMBOL(vchiq_msg_hold);
+
 static int vchiq_validate_params(const struct vchiq_service_params *params)
 {
        if (!params->callback || !params->fourcc) {
@@ -2319,12 +2360,17 @@ vchiq_add_service_internal(struct vchiq_state *state,
        service->state         = state;
        service->instance      = instance;
        service->service_use_count = 0;
+       service->msg_queue_read = 0;
+       service->msg_queue_write = 0;
        init_bulk_queue(&service->bulk_tx);
        init_bulk_queue(&service->bulk_rx);
        init_completion(&service->remove_event);
        init_completion(&service->bulk_remove_event);
+       init_completion(&service->msg_queue_pop);
+       init_completion(&service->msg_queue_push);
        mutex_init(&service->bulk_mutex);
        memset(&service->stats, 0, sizeof(service->stats));
+       memset(&service->msg_queue, 0, sizeof(service->msg_queue));
 
        /* Although it is perfectly possible to use a spinlock
        ** to protect the creation of services, it is overkill as it
index 1fe6cd8b86c02e3ed637de3640d920bb3f4874db..b97b661bea1c20411b9b2a7f53f48bb1faa23bcb 100644 (file)
@@ -297,6 +297,12 @@ struct vchiq_service {
                uint64_t bulk_tx_bytes;
                uint64_t bulk_rx_bytes;
        } stats;
+
+       int msg_queue_read;
+       int msg_queue_write;
+       struct completion msg_queue_pop;
+       struct completion msg_queue_push;
+       struct vchiq_header *msg_queue[VCHIQ_MAX_SLOTS];
 };
 
 /* The quota information is outside struct vchiq_service so that it can
index b62fd6d6f1ac8e215f430e1f7c9110aca58a357d..8fd51d885a181d82de84d9c14ba95911ec9dede4 100644 (file)
@@ -136,5 +136,7 @@ extern enum vchiq_status vchiq_dump_phys_mem(unsigned int service,
 
 extern enum vchiq_status vchiq_get_peer_version(unsigned int handle,
       short *peer_version);
+extern void vchiq_msg_queue_push(unsigned handle, struct vchiq_header *header);
+extern struct vchiq_header *vchiq_msg_hold(unsigned handle);
 
 #endif /* VCHIQ_IF_H */
index 3ce4b7b5d55ee35045cda64e22457fb2982b06d5..fb6f3c052e1185d78fc6a59d1d6fd10cff2dd0dc 100644 (file)
@@ -13,8 +13,6 @@
 struct vchi_service {
        unsigned int handle;
 
-       struct vchiu_queue queue;
-
        vchi_callback callback;
        void *callback_param;
 };
@@ -172,10 +170,9 @@ int32_t vchi_msg_hold(struct vchi_service *service, void **data,
 {
        struct vchiq_header *header;
 
-       if (vchiu_queue_is_empty(&service->queue))
-               return -1;
-
-       header = vchiu_queue_pop(&service->queue);
+       header = vchiq_msg_hold(service->handle);
+       if (!header)
+               return -ENOENT;
 
        *data = header->data;
        *msg_size = header->size;
@@ -272,7 +269,7 @@ static enum vchiq_status shim_callback(enum vchiq_reason reason,
                (struct vchi_service *)VCHIQ_GET_SERVICE_USERDATA(handle);
 
        if (reason == VCHIQ_MESSAGE_AVAILABLE)
-               vchiu_queue_push(&service->queue, header);
+               vchiq_msg_queue_push(service->handle, header);
 
        service->callback(service->callback_param, reason, bulk_user);
 
@@ -285,13 +282,8 @@ static struct vchi_service *service_alloc(struct vchiq_instance *instance,
        struct vchi_service *service = kzalloc(sizeof(struct vchi_service), GFP_KERNEL);
 
        if (service) {
-               if (!vchiu_queue_init(&service->queue, 64)) {
-                       service->callback = setup->callback;
-                       service->callback_param = setup->callback_param;
-               } else {
-                       kfree(service);
-                       service = NULL;
-               }
+               service->callback = setup->callback;
+               service->callback_param = setup->callback_param;
        }
 
        return service;
@@ -299,10 +291,8 @@ static struct vchi_service *service_alloc(struct vchiq_instance *instance,
 
 static void service_free(struct vchi_service *service)
 {
-       if (service) {
-               vchiu_queue_delete(&service->queue);
+       if (service)
                kfree(service);
-       }
 }
 
 int32_t vchi_service_open(struct vchiq_instance *instance,
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c
deleted file mode 100644 (file)
index c1c81f9..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-
-#include "vchiq_util.h"
-
-static inline int is_pow2(int i)
-{
-       return i && !(i & (i - 1));
-}
-
-int vchiu_queue_init(struct vchiu_queue *queue, int size)
-{
-       WARN_ON(!is_pow2(size));
-
-       queue->size = size;
-       queue->read = 0;
-       queue->write = 0;
-       queue->initialized = 1;
-
-       init_completion(&queue->pop);
-       init_completion(&queue->push);
-
-       queue->storage = kcalloc(size, sizeof(struct vchiq_header *),
-                                GFP_KERNEL);
-       if (!queue->storage) {
-               vchiu_queue_delete(queue);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-void vchiu_queue_delete(struct vchiu_queue *queue)
-{
-       kfree(queue->storage);
-}
-
-int vchiu_queue_is_empty(struct vchiu_queue *queue)
-{
-       return queue->read == queue->write;
-}
-
-void vchiu_queue_push(struct vchiu_queue *queue, struct vchiq_header *header)
-{
-       if (!queue->initialized)
-               return;
-
-       while (queue->write == queue->read + queue->size) {
-               if (wait_for_completion_interruptible(&queue->pop))
-                       flush_signals(current);
-       }
-
-       queue->storage[queue->write & (queue->size - 1)] = header;
-       queue->write++;
-
-       complete(&queue->push);
-}
-
-struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue)
-{
-       struct vchiq_header *header;
-
-       while (queue->write == queue->read) {
-               if (wait_for_completion_interruptible(&queue->push))
-                       flush_signals(current);
-       }
-
-       header = queue->storage[queue->read & (queue->size - 1)];
-       queue->read++;
-
-       complete(&queue->pop);
-
-       return header;
-}
index 1c90a8da1a92fbea3abb81b25dca7ac221e02a0d..dcf081079c39a8c9d28a8d97ce5e9a99cead0ea8 100644 (file)
 
 #include "vchiq_if.h"
 
-struct vchiu_queue {
-       int size;
-       int read;
-       int write;
-       int initialized;
-
-       struct completion pop;
-       struct completion push;
-
-       struct vchiq_header **storage;
-};
-
-extern int  vchiu_queue_init(struct vchiu_queue *queue, int size);
-extern void vchiu_queue_delete(struct vchiu_queue *queue);
-
-extern int vchiu_queue_is_empty(struct vchiu_queue *queue);
-
-extern void vchiu_queue_push(struct vchiu_queue *queue,
-                            struct vchiq_header *header);
-
-extern struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue);
-
 #endif