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@xxxxxxxxxx> --- .../interface/vchiq_arm/vchiq_arm.c | 16 ++++----- .../interface/vchiq_arm/vchiq_core.c | 36 +++++++++++++------ .../interface/vchiq_arm/vchiq_core.h | 8 ++++- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 3ed0e4ea7f5c..b377f18aed45 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -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); } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 65270a5b29db..d7d7f4d9d57f 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -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; } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 30e4965c7666..cedd8e721aae 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -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 -- 2.25.0.225.g125e21ebc7-goog _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel