staging: vc04_services: don't increment service refcount when it's not needed
authorMarcelo Diop-Gonzalez <marcgonzalez@google.com>
Wed, 12 Feb 2020 18:43:33 +0000 (13:43 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Feb 2020 21:40:44 +0000 (13:40 -0800)
There are a few places where a service's reference count is incremented,
something quick is done, and the refcount is dropped. This can be made
a little simpler/faster by not grabbing a reference in these cases.

Signed-off-by: Marcelo Diop-Gonzalez <marcgonzalez@google.com>
Link: https://lore.kernel.org/r/ac6186ac888f1acf489b5b504efcba8b0d6a8b25.1581532523.git.marcgonzalez@google.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

index 3ed0e4e..b377f18 100644 (file)
@@ -2497,11 +2497,11 @@ vchiq_instance_get_use_count(struct vchiq_instance *instance)
        int use_count = 0, i;
 
        i = 0;
-       while ((service = next_service_by_instance(instance->state,
-               instance, &i))) {
+       rcu_read_lock();
+       while ((service = __next_service_by_instance(instance->state,
+                                                    instance, &i)))
                use_count += service->service_use_count;
-               unlock_service(service);
-       }
+       rcu_read_unlock();
        return use_count;
 }
 
@@ -2524,11 +2524,11 @@ vchiq_instance_set_trace(struct vchiq_instance *instance, int trace)
        int i;
 
        i = 0;
-       while ((service = next_service_by_instance(instance->state,
-               instance, &i))) {
+       rcu_read_lock();
+       while ((service = __next_service_by_instance(instance->state,
+                                                    instance, &i)))
                service->trace = trace;
-               unlock_service(service);
-       }
+       rcu_read_unlock();
        instance->trace = (trace != 0);
 }
 
index 65270a5..d7d7f4d 100644 (file)
@@ -222,28 +222,42 @@ find_closed_service_for_instance(struct vchiq_instance *instance,
 }
 
 struct vchiq_service *
-next_service_by_instance(struct vchiq_state *state, struct vchiq_instance *instance,
-                        int *pidx)
+__next_service_by_instance(struct vchiq_state *state,
+                          struct vchiq_instance *instance,
+                          int *pidx)
 {
        struct vchiq_service *service = NULL;
        int idx = *pidx;
 
-       rcu_read_lock();
        while (idx < state->unused_service) {
                struct vchiq_service *srv;
 
                srv = rcu_dereference(state->services[idx++]);
                if (srv && srv->srvstate != VCHIQ_SRVSTATE_FREE &&
-                   srv->instance == instance &&
-                   kref_get_unless_zero(&srv->ref_count)) {
-                       service = rcu_pointer_handoff(srv);
+                   srv->instance == instance) {
+                       service = srv;
                        break;
                }
        }
-       rcu_read_unlock();
 
        *pidx = idx;
+       return service;
+}
 
+struct vchiq_service *
+next_service_by_instance(struct vchiq_state *state,
+                        struct vchiq_instance *instance,
+                        int *pidx)
+{
+       struct vchiq_service *service;
+
+       rcu_read_lock();
+       service = __next_service_by_instance(state, instance, pidx);
+       if (service && kref_get_unless_zero(&service->ref_count))
+               service = rcu_pointer_handoff(service);
+       else
+               service = NULL;
+       rcu_read_unlock();
        return service;
 }
 
@@ -283,13 +297,13 @@ unlock_service(struct vchiq_service *service)
 int
 vchiq_get_client_id(unsigned int handle)
 {
-       struct vchiq_service *service = find_service_by_handle(handle);
+       struct vchiq_service *service;
        int id;
 
+       rcu_read_lock();
+       service = handle_to_service(handle);
        id = service ? service->client_id : 0;
-       if (service)
-               unlock_service(service);
-
+       rcu_read_unlock();
        return id;
 }
 
index 30e4965..cedd8e7 100644 (file)
@@ -572,7 +572,13 @@ find_closed_service_for_instance(struct vchiq_instance *instance,
        unsigned int handle);
 
 extern struct vchiq_service *
-next_service_by_instance(struct vchiq_state *state, struct vchiq_instance *instance,
+__next_service_by_instance(struct vchiq_state *state,
+                          struct vchiq_instance *instance,
+                          int *pidx);
+
+extern struct vchiq_service *
+next_service_by_instance(struct vchiq_state *state,
+                        struct vchiq_instance *instance,
                         int *pidx);
 
 extern void