]> www.infradead.org Git - linux.git/commitdiff
staging: vchiq_core: Factor out bulk transfer for blocking mode
authorUmang Jain <umang.jain@ideasonboard.com>
Tue, 10 Sep 2024 05:10:03 +0000 (10:40 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 11 Sep 2024 13:54:04 +0000 (15:54 +0200)
Factor out bulk transfer for blocking mode into a separate dedicated
function bulk_xfer_blocking_interruptible(). It is suffixed by
"_interruptible" to denote that it can be interrupted and -EAGAIN
can be returned. It would be up to the users of the function to retry
the call in those cases.

Adjust the calls to vchiq-dev.c ioctl interface and vchiq_arm.c
for blocking bulk transfers.

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Tested-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20240910051007.297227-4-umang.jain@ideasonboard.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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_dev.c

index c4d97dbf6ba8367d5c45b585b0263a9138594c64..688c9b1be868e8c74b1d5c54d598e41a26f15d08 100644 (file)
@@ -968,9 +968,8 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
                        return -ENOMEM;
        }
 
-       ret = vchiq_bulk_transfer(instance, handle, data, NULL, size,
-                                 &waiter->bulk_waiter,
-                                 VCHIQ_BULK_MODE_BLOCKING, dir);
+       ret = vchiq_bulk_xfer_blocking_interruptible(instance, handle, data, NULL, size,
+                                                    &waiter->bulk_waiter, dir);
        if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) {
                struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk;
 
index 9c774fbd38416a4d5969270df217d1db1f2d86f2..b93b7e2ba0c73ab53c74634fa71cae51548136e1 100644 (file)
@@ -2669,6 +2669,7 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
                                        enum vchiq_bulk_dir dir)
 {
        struct vchiq_bulk_queue *queue;
+       struct bulk_waiter *bulk_waiter = NULL;
        struct vchiq_bulk *bulk;
        struct vchiq_state *state = service->state;
        const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
@@ -2677,6 +2678,13 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
        int status = -EINVAL;
        int payload[2];
 
+       if (mode == VCHIQ_BULK_MODE_BLOCKING) {
+               bulk_waiter = userdata;
+               init_completion(&bulk_waiter->event);
+               bulk_waiter->actual = 0;
+               bulk_waiter->bulk = NULL;
+       }
+
        queue = (dir == VCHIQ_BULK_TRANSMIT) ?
                &service->bulk_tx : &service->bulk_rx;
 
@@ -2753,6 +2761,14 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
                state->id, service->localport, dir_char, queue->local_insert,
                queue->remote_insert, queue->process);
 
+        if (bulk_waiter) {
+                bulk_waiter->bulk = bulk;
+                if (wait_for_completion_interruptible(&bulk_waiter->event))
+                        status = -EAGAIN;
+                else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
+                        status = -EINVAL;
+        }
+
        return status;
 
 unlock_both_error_exit:
@@ -3088,6 +3104,37 @@ vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle)
        return status;
 }
 
+int
+vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
+                                      void *offset, void __user *uoffset, int size,
+                                      void __user *userdata, enum vchiq_bulk_dir dir)
+{
+       struct vchiq_service *service = find_service_by_handle(instance, handle);
+       enum vchiq_bulk_mode mode = VCHIQ_BULK_MODE_BLOCKING;
+       int status = -EINVAL;
+
+       if (!service)
+               return -EINVAL;
+
+       if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
+               goto error_exit;
+
+       if (!offset && !uoffset)
+               goto error_exit;
+
+       if (vchiq_check_service(service))
+               goto error_exit;
+
+
+       status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset, size,
+                                                        userdata, mode, dir);
+
+error_exit:
+       vchiq_service_put(service);
+
+       return status;
+}
+
 /*
  * This function may be called by kernel threads or user threads.
  * User threads may receive -EAGAIN to indicate that a signal has been
@@ -3121,12 +3168,6 @@ int vchiq_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
        case VCHIQ_BULK_MODE_NOCALLBACK:
        case VCHIQ_BULK_MODE_CALLBACK:
                break;
-       case VCHIQ_BULK_MODE_BLOCKING:
-               bulk_waiter = userdata;
-               init_completion(&bulk_waiter->event);
-               bulk_waiter->actual = 0;
-               bulk_waiter->bulk = NULL;
-               break;
        default:
                goto error_exit;
        }
index 985d9ea3a06a5a8e14088febbc30d08c39fbb810..2dd89101c1c661721f0b667952f1fac0849ac5c6 100644 (file)
@@ -474,6 +474,11 @@ extern int
 vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
                                      unsigned int handle, struct bulk_waiter *userdata);
 
+extern int
+vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
+                                      void *offset, void __user *uoffset, int size,
+                                      void __user *userdata, enum vchiq_bulk_dir dir);
+
 extern int
 vchiq_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *offset,
                    void __user *uoffset, int size, void *userdata, enum vchiq_bulk_mode mode,
index 550838d2863b8c304fac9f2f3ee23d9ca7408d29..830633f2326b6b15ca0df9bf6642803a4357f55e 100644 (file)
@@ -304,6 +304,12 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
                }
 
                userdata = &waiter->bulk_waiter;
+
+               status = vchiq_bulk_xfer_blocking_interruptible(instance, args->handle,
+                                                               NULL, args->data, args->size,
+                                                               userdata, dir);
+
+               goto bulk_transfer_handled;
        } else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
                mutex_lock(&instance->bulk_waiter_list_mutex);
                list_for_each_entry(iter, &instance->bulk_waiter_list,