diff options
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm')
6 files changed, 206 insertions, 798 deletions
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index ca30bfd52919..c18c6ca0b6c0 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -257,49 +257,6 @@ int vchiq_dump_platform_state(void *dump_context) return vchiq_dump(dump_context, buf, len + 1); } -enum vchiq_status -vchiq_platform_suspend(struct vchiq_state *state) -{ - return VCHIQ_ERROR; -} - -enum vchiq_status -vchiq_platform_resume(struct vchiq_state *state) -{ - return VCHIQ_SUCCESS; -} - -void -vchiq_platform_paused(struct vchiq_state *state) -{ -} - -void -vchiq_platform_resumed(struct vchiq_state *state) -{ -} - -int -vchiq_platform_videocore_wanted(struct vchiq_state *state) -{ - return 1; // autosuspend not supported - videocore always wanted -} - -int -vchiq_platform_use_suspend_timer(void) -{ - return 0; -} -void -vchiq_dump_platform_use_state(struct vchiq_state *state) -{ - vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); -} -void -vchiq_platform_handle_timeout(struct vchiq_state *state) -{ - (void)state; -} /* * Local functions */ 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 4458c1e60fa3..a1ea9777a444 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/compat.h> #include <linux/dma-mapping.h> +#include <linux/rcupdate.h> #include <soc/bcm2835/raspberrypi-firmware.h> #include "vchiq_core.h" @@ -48,39 +49,6 @@ int vchiq_arm_log_level = VCHIQ_LOG_DEFAULT; int vchiq_susp_log_level = VCHIQ_LOG_ERROR; -#define SUSPEND_TIMER_TIMEOUT_MS 100 -#define SUSPEND_RETRY_TIMER_TIMEOUT_MS 1000 - -#define VC_SUSPEND_NUM_OFFSET 3 /* number of values before idle which are -ve */ -static const char *const suspend_state_names[] = { - "VC_SUSPEND_FORCE_CANCELED", - "VC_SUSPEND_REJECTED", - "VC_SUSPEND_FAILED", - "VC_SUSPEND_IDLE", - "VC_SUSPEND_REQUESTED", - "VC_SUSPEND_IN_PROGRESS", - "VC_SUSPEND_SUSPENDED" -}; -#define VC_RESUME_NUM_OFFSET 1 /* number of values before idle which are -ve */ -static const char *const resume_state_names[] = { - "VC_RESUME_FAILED", - "VC_RESUME_IDLE", - "VC_RESUME_REQUESTED", - "VC_RESUME_IN_PROGRESS", - "VC_RESUME_RESUMED" -}; -/* The number of times we allow force suspend to timeout before actually -** _forcing_ suspend. This is to cater for SW which fails to release vchiq -** correctly - we don't want to prevent ARM suspend indefinitely in this case. -*/ -#define FORCE_SUSPEND_FAIL_MAX 8 - -/* The time in ms allowed for videocore to go idle when force suspend has been - * requested */ -#define FORCE_SUSPEND_TIMEOUT_MS 200 - -static void suspend_timer_callback(struct timer_list *t); - struct user_service { struct vchiq_service *service; void *userdata; @@ -2129,10 +2097,12 @@ int vchiq_dump_platform_instances(void *dump_context) /* There is no list of instances, so instead scan all services, marking those that have been dumped. */ + rcu_read_lock(); for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = state->services[i]; + struct vchiq_service *service; struct vchiq_instance *instance; + service = rcu_dereference(state->services[i]); if (!service || service->base.callback != service_callback) continue; @@ -2140,18 +2110,26 @@ int vchiq_dump_platform_instances(void *dump_context) if (instance) instance->mark = 0; } + rcu_read_unlock(); for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = state->services[i]; + struct vchiq_service *service; struct vchiq_instance *instance; int err; - if (!service || service->base.callback != service_callback) + rcu_read_lock(); + service = rcu_dereference(state->services[i]); + if (!service || service->base.callback != service_callback) { + rcu_read_unlock(); continue; + } instance = service->instance; - if (!instance || instance->mark) + if (!instance || instance->mark) { + rcu_read_unlock(); continue; + } + rcu_read_unlock(); len = snprintf(buf, sizeof(buf), "Instance %pK: pid %d,%s completions %d/%d", @@ -2161,7 +2139,6 @@ int vchiq_dump_platform_instances(void *dump_context) instance->completion_insert - instance->completion_remove, MAX_COMPLETIONS); - err = vchiq_dump(dump_context, buf, len + 1); if (err) return err; @@ -2184,17 +2161,17 @@ int vchiq_dump_platform_service_state(void *dump_context, char buf[80]; int len; - len = snprintf(buf, sizeof(buf), " instance %pK", service->instance); + len = scnprintf(buf, sizeof(buf), " instance %pK", service->instance); if ((service->base.callback == service_callback) && user_service->is_vchi) { - len += snprintf(buf + len, sizeof(buf) - len, + len += scnprintf(buf + len, sizeof(buf) - len, ", %d/%d messages", user_service->msg_insert - user_service->msg_remove, MSG_QUEUE_SIZE); if (user_service->dequeue_pending) - len += snprintf(buf + len, sizeof(buf) - len, + len += scnprintf(buf + len, sizeof(buf) - len, " (dequeue pending)"); } @@ -2258,27 +2235,6 @@ vchiq_fops = { * Autosuspend related functionality */ -int -vchiq_videocore_wanted(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - if (!arm_state) - /* autosuspend not supported - always return wanted */ - return 1; - else if (arm_state->blocked_count) - return 1; - else if (!arm_state->videocore_use_count) - /* usage count zero - check for override unless we're forcing */ - if (arm_state->resume_blocked) - return 0; - else - return vchiq_platform_videocore_wanted(state); - else - /* non-zero usage count - videocore still required */ - return 1; -} - static enum vchiq_status vchiq_keepalive_vchiq_callback(enum vchiq_reason reason, struct vchiq_header *header, @@ -2382,317 +2338,13 @@ vchiq_arm_init_state(struct vchiq_state *state, atomic_set(&arm_state->ka_use_ack_count, 0); atomic_set(&arm_state->ka_release_count, 0); - init_completion(&arm_state->vc_suspend_complete); - - init_completion(&arm_state->vc_resume_complete); - /* Initialise to 'done' state. We only want to block on resume - * completion while videocore is suspended. */ - set_resume_state(arm_state, VC_RESUME_RESUMED); - - init_completion(&arm_state->resume_blocker); - /* Initialise to 'done' state. We only want to block on this - * completion while resume is blocked */ - complete_all(&arm_state->resume_blocker); - - init_completion(&arm_state->blocked_blocker); - /* Initialise to 'done' state. We only want to block on this - * completion while things are waiting on the resume blocker */ - complete_all(&arm_state->blocked_blocker); - - arm_state->suspend_timer_timeout = SUSPEND_TIMER_TIMEOUT_MS; - arm_state->suspend_timer_running = 0; arm_state->state = state; - timer_setup(&arm_state->suspend_timer, suspend_timer_callback, - 0); - arm_state->first_connect = 0; } return VCHIQ_SUCCESS; } -/* -** Functions to modify the state variables; -** set_suspend_state -** set_resume_state -** -** There are more state variables than we might like, so ensure they remain in -** step. Suspend and resume state are maintained separately, since most of -** these state machines can operate independently. However, there are a few -** states where state transitions in one state machine cause a reset to the -** other state machine. In addition, there are some completion events which -** need to occur on state machine reset and end-state(s), so these are also -** dealt with in these functions. -** -** In all states we set the state variable according to the input, but in some -** cases we perform additional steps outlined below; -** -** VC_SUSPEND_IDLE - Initialise the suspend completion at the same time. -** The suspend completion is completed after any suspend -** attempt. When we reset the state machine we also reset -** the completion. This reset occurs when videocore is -** resumed, and also if we initiate suspend after a suspend -** failure. -** -** VC_SUSPEND_IN_PROGRESS - This state is considered the point of no return for -** suspend - ie from this point on we must try to suspend -** before resuming can occur. We therefore also reset the -** resume state machine to VC_RESUME_IDLE in this state. -** -** VC_SUSPEND_SUSPENDED - Suspend has completed successfully. Also call -** complete_all on the suspend completion to notify -** anything waiting for suspend to happen. -** -** VC_SUSPEND_REJECTED - Videocore rejected suspend. Videocore will also -** initiate resume, so no need to alter resume state. -** We call complete_all on the suspend completion to notify -** of suspend rejection. -** -** VC_SUSPEND_FAILED - We failed to initiate videocore suspend. We notify the -** suspend completion and reset the resume state machine. -** -** VC_RESUME_IDLE - Initialise the resume completion at the same time. The -** resume completion is in it's 'done' state whenever -** videcore is running. Therefore, the VC_RESUME_IDLE -** state implies that videocore is suspended. -** Hence, any thread which needs to wait until videocore is -** running can wait on this completion - it will only block -** if videocore is suspended. -** -** VC_RESUME_RESUMED - Resume has completed successfully. Videocore is running. -** Call complete_all on the resume completion to unblock -** any threads waiting for resume. Also reset the suspend -** state machine to it's idle state. -** -** VC_RESUME_FAILED - Currently unused - no mechanism to fail resume exists. -*/ - -void -set_suspend_state(struct vchiq_arm_state *arm_state, - enum vc_suspend_status new_state) -{ - /* set the state in all cases */ - arm_state->vc_suspend_state = new_state; - - /* state specific additional actions */ - switch (new_state) { - case VC_SUSPEND_FORCE_CANCELED: - complete_all(&arm_state->vc_suspend_complete); - break; - case VC_SUSPEND_REJECTED: - complete_all(&arm_state->vc_suspend_complete); - break; - case VC_SUSPEND_FAILED: - complete_all(&arm_state->vc_suspend_complete); - arm_state->vc_resume_state = VC_RESUME_RESUMED; - complete_all(&arm_state->vc_resume_complete); - break; - case VC_SUSPEND_IDLE: - reinit_completion(&arm_state->vc_suspend_complete); - break; - case VC_SUSPEND_REQUESTED: - break; - case VC_SUSPEND_IN_PROGRESS: - set_resume_state(arm_state, VC_RESUME_IDLE); - break; - case VC_SUSPEND_SUSPENDED: - complete_all(&arm_state->vc_suspend_complete); - break; - default: - BUG(); - break; - } -} - -void -set_resume_state(struct vchiq_arm_state *arm_state, - enum vc_resume_status new_state) -{ - /* set the state in all cases */ - arm_state->vc_resume_state = new_state; - - /* state specific additional actions */ - switch (new_state) { - case VC_RESUME_FAILED: - break; - case VC_RESUME_IDLE: - reinit_completion(&arm_state->vc_resume_complete); - break; - case VC_RESUME_REQUESTED: - break; - case VC_RESUME_IN_PROGRESS: - break; - case VC_RESUME_RESUMED: - complete_all(&arm_state->vc_resume_complete); - set_suspend_state(arm_state, VC_SUSPEND_IDLE); - break; - default: - BUG(); - break; - } -} - -/* should be called with the write lock held */ -inline void -start_suspend_timer(struct vchiq_arm_state *arm_state) -{ - del_timer(&arm_state->suspend_timer); - arm_state->suspend_timer.expires = jiffies + - msecs_to_jiffies(arm_state->suspend_timer_timeout); - add_timer(&arm_state->suspend_timer); - arm_state->suspend_timer_running = 1; -} - -/* should be called with the write lock held */ -static inline void -stop_suspend_timer(struct vchiq_arm_state *arm_state) -{ - if (arm_state->suspend_timer_running) { - del_timer(&arm_state->suspend_timer); - arm_state->suspend_timer_running = 0; - } -} - -static inline int -need_resume(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && - (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && - vchiq_videocore_wanted(state); -} - -static inline void -unblock_resume(struct vchiq_arm_state *arm_state) -{ - complete_all(&arm_state->resume_blocker); - arm_state->resume_blocked = 0; -} - -/* Initiate suspend via slot handler. Should be called with the write lock - * held */ -enum vchiq_status -vchiq_arm_vcsuspend(struct vchiq_state *state) -{ - enum vchiq_status status = VCHIQ_ERROR; - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - if (!arm_state) - goto out; - - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - status = VCHIQ_SUCCESS; - - switch (arm_state->vc_suspend_state) { - case VC_SUSPEND_REQUESTED: - vchiq_log_info(vchiq_susp_log_level, "%s: suspend already " - "requested", __func__); - break; - case VC_SUSPEND_IN_PROGRESS: - vchiq_log_info(vchiq_susp_log_level, "%s: suspend already in " - "progress", __func__); - break; - - default: - /* We don't expect to be in other states, so log but continue - * anyway */ - vchiq_log_error(vchiq_susp_log_level, - "%s unexpected suspend state %s", __func__, - suspend_state_names[arm_state->vc_suspend_state + - VC_SUSPEND_NUM_OFFSET]); - /* fall through */ - case VC_SUSPEND_REJECTED: - case VC_SUSPEND_FAILED: - /* Ensure any idle state actions have been run */ - set_suspend_state(arm_state, VC_SUSPEND_IDLE); - /* fall through */ - case VC_SUSPEND_IDLE: - vchiq_log_info(vchiq_susp_log_level, - "%s: suspending", __func__); - set_suspend_state(arm_state, VC_SUSPEND_REQUESTED); - /* kick the slot handler thread to initiate suspend */ - request_poll(state, NULL, 0); - break; - } - -out: - vchiq_log_trace(vchiq_susp_log_level, "%s exit %d", __func__, status); - return status; -} - -void -vchiq_platform_check_suspend(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - int susp = 0; - - if (!arm_state) - goto out; - - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - - write_lock_bh(&arm_state->susp_res_lock); - if (arm_state->vc_suspend_state == VC_SUSPEND_REQUESTED && - arm_state->vc_resume_state == VC_RESUME_RESUMED) { - set_suspend_state(arm_state, VC_SUSPEND_IN_PROGRESS); - susp = 1; - } - write_unlock_bh(&arm_state->susp_res_lock); - - if (susp) - vchiq_platform_suspend(state); - -out: - vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); - return; -} - -void -vchiq_check_suspend(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - if (!arm_state) - goto out; - - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - - write_lock_bh(&arm_state->susp_res_lock); - if (arm_state->vc_suspend_state != VC_SUSPEND_SUSPENDED && - arm_state->first_connect && - !vchiq_videocore_wanted(state)) { - vchiq_arm_vcsuspend(state); - } - write_unlock_bh(&arm_state->susp_res_lock); - -out: - vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); -} - -/* This function should be called with the write lock held */ -int -vchiq_check_resume(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - int resume = 0; - - if (!arm_state) - goto out; - - vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); - - if (need_resume(state)) { - set_resume_state(arm_state, VC_RESUME_REQUESTED); - request_poll(state, NULL, 0); - resume = 1; - } - -out: - vchiq_log_trace(vchiq_susp_log_level, "%s exit", __func__); - return resume; -} - enum vchiq_status vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, enum USE_TYPE_E use_type) @@ -2724,88 +2376,15 @@ vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, } write_lock_bh(&arm_state->susp_res_lock); - while (arm_state->resume_blocked) { - /* If we call 'use' while force suspend is waiting for suspend, - * then we're about to block the thread which the force is - * waiting to complete, so we're bound to just time out. In this - * case, set the suspend state such that the wait will be - * canceled, so we can complete as quickly as possible. */ - if (arm_state->resume_blocked && arm_state->vc_suspend_state == - VC_SUSPEND_IDLE) { - set_suspend_state(arm_state, VC_SUSPEND_FORCE_CANCELED); - break; - } - /* If suspend is already in progress then we need to block */ - if (!try_wait_for_completion(&arm_state->resume_blocker)) { - /* Indicate that there are threads waiting on the resume - * blocker. These need to be allowed to complete before - * a _second_ call to force suspend can complete, - * otherwise low priority threads might never actually - * continue */ - arm_state->blocked_count++; - write_unlock_bh(&arm_state->susp_res_lock); - vchiq_log_info(vchiq_susp_log_level, "%s %s resume " - "blocked - waiting...", __func__, entity); - if (wait_for_completion_killable( - &arm_state->resume_blocker)) { - vchiq_log_error(vchiq_susp_log_level, "%s %s " - "wait for resume blocker interrupted", - __func__, entity); - ret = VCHIQ_ERROR; - write_lock_bh(&arm_state->susp_res_lock); - arm_state->blocked_count--; - write_unlock_bh(&arm_state->susp_res_lock); - goto out; - } - vchiq_log_info(vchiq_susp_log_level, "%s %s resume " - "unblocked", __func__, entity); - write_lock_bh(&arm_state->susp_res_lock); - if (--arm_state->blocked_count == 0) - complete_all(&arm_state->blocked_blocker); - } - } - - stop_suspend_timer(arm_state); - local_uc = ++arm_state->videocore_use_count; local_entity_uc = ++(*entity_uc); - /* If there's a pending request which hasn't yet been serviced then - * just clear it. If we're past VC_SUSPEND_REQUESTED state then - * vc_resume_complete will block until we either resume or fail to - * suspend */ - if (arm_state->vc_suspend_state <= VC_SUSPEND_REQUESTED) - set_suspend_state(arm_state, VC_SUSPEND_IDLE); - - if ((use_type != USE_TYPE_SERVICE_NO_RESUME) && need_resume(state)) { - set_resume_state(arm_state, VC_RESUME_REQUESTED); - vchiq_log_info(vchiq_susp_log_level, - "%s %s count %d, state count %d", - __func__, entity, local_entity_uc, local_uc); - request_poll(state, NULL, 0); - } else - vchiq_log_trace(vchiq_susp_log_level, - "%s %s count %d, state count %d", - __func__, entity, *entity_uc, local_uc); + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, local_uc); write_unlock_bh(&arm_state->susp_res_lock); - /* Completion is in a done state when we're not suspended, so this won't - * block for the non-suspended case. */ - if (!try_wait_for_completion(&arm_state->vc_resume_complete)) { - vchiq_log_info(vchiq_susp_log_level, "%s %s wait for resume", - __func__, entity); - if (wait_for_completion_killable( - &arm_state->vc_resume_complete)) { - vchiq_log_error(vchiq_susp_log_level, "%s %s wait for " - "resume interrupted", __func__, entity); - ret = VCHIQ_ERROR; - goto out; - } - vchiq_log_info(vchiq_susp_log_level, "%s %s resumed", __func__, - entity); - } - if (ret == VCHIQ_SUCCESS) { enum vchiq_status status = VCHIQ_SUCCESS; long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); @@ -2860,24 +2439,10 @@ vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) --arm_state->videocore_use_count; --(*entity_uc); - if (!vchiq_videocore_wanted(state)) { - if (vchiq_platform_use_suspend_timer() && - !arm_state->resume_blocked) { - /* Only use the timer if we're not trying to force - * suspend (=> resume_blocked) */ - start_suspend_timer(arm_state); - } else { - vchiq_log_info(vchiq_susp_log_level, - "%s %s count %d, state count %d - suspending", - __func__, entity, *entity_uc, - arm_state->videocore_use_count); - vchiq_arm_vcsuspend(state); - } - } else - vchiq_log_trace(vchiq_susp_log_level, - "%s %s count %d, state count %d", - __func__, entity, *entity_uc, - arm_state->videocore_use_count); + vchiq_log_trace(vchiq_susp_log_level, + "%s %s count %d, state count %d", + __func__, entity, *entity_uc, + arm_state->videocore_use_count); unlock: write_unlock_bh(&arm_state->susp_res_lock); @@ -2932,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; } @@ -2959,25 +2524,14 @@ 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); } -static void suspend_timer_callback(struct timer_list *t) -{ - struct vchiq_arm_state *arm_state = - from_timer(arm_state, t, suspend_timer); - struct vchiq_state *state = arm_state->state; - - vchiq_log_info(vchiq_susp_log_level, - "%s - suspend timer expired - check suspend", __func__); - vchiq_check_suspend(state); -} - enum vchiq_status vchiq_use_service(unsigned int handle) { @@ -3022,8 +2576,6 @@ vchiq_dump_service_use_state(struct vchiq_state *state) int only_nonzero = 0; static const char *nz = "<-- preventing suspend"; - enum vc_suspend_status vc_suspend_state; - enum vc_resume_status vc_resume_state; int peer_count; int vc_use_count; int active_services; @@ -3037,16 +2589,16 @@ vchiq_dump_service_use_state(struct vchiq_state *state) return; read_lock_bh(&arm_state->susp_res_lock); - vc_suspend_state = arm_state->vc_suspend_state; - vc_resume_state = arm_state->vc_resume_state; peer_count = arm_state->peer_use_count; vc_use_count = arm_state->videocore_use_count; active_services = state->unused_service; if (active_services > MAX_SERVICES) only_nonzero = 1; + rcu_read_lock(); for (i = 0; i < active_services; i++) { - struct vchiq_service *service_ptr = state->services[i]; + struct vchiq_service *service_ptr = + rcu_dereference(state->services[i]); if (!service_ptr) continue; @@ -3064,16 +2616,10 @@ vchiq_dump_service_use_state(struct vchiq_state *state) if (found >= MAX_SERVICES) break; } + rcu_read_unlock(); read_unlock_bh(&arm_state->susp_res_lock); - vchiq_log_warning(vchiq_susp_log_level, - "-- Videcore suspend state: %s --", - suspend_state_names[vc_suspend_state + VC_SUSPEND_NUM_OFFSET]); - vchiq_log_warning(vchiq_susp_log_level, - "-- Videcore resume state: %s --", - resume_state_names[vc_resume_state + VC_RESUME_NUM_OFFSET]); - if (only_nonzero) vchiq_log_warning(vchiq_susp_log_level, "Too many active " "services (%d). Only dumping up to first %d services " @@ -3093,8 +2639,6 @@ vchiq_dump_service_use_state(struct vchiq_state *state) "--- Overall vchiq instance use count %d", vc_use_count); kfree(service_data); - - vchiq_dump_platform_use_state(state); } enum vchiq_status @@ -3118,24 +2662,16 @@ vchiq_check_service(struct vchiq_service *service) if (ret == VCHIQ_ERROR) { vchiq_log_error(vchiq_susp_log_level, "%s ERROR - %c%c%c%c:%d service count %d, " - "state count %d, videocore suspend state %s", __func__, + "state count %d", __func__, VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), service->client_id, service->service_use_count, - arm_state->videocore_use_count, - suspend_state_names[arm_state->vc_suspend_state + - VC_SUSPEND_NUM_OFFSET]); + arm_state->videocore_use_count); vchiq_dump_service_use_state(service->state); } out: return ret; } -/* stub functions */ -void vchiq_on_remote_use_active(struct vchiq_state *state) -{ - (void)state; -} - void vchiq_platform_conn_state_changed(struct vchiq_state *state, enum vchiq_connstate oldstate, enum vchiq_connstate newstate) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index 19d2a2eefb6a..0784c5002417 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -14,27 +14,8 @@ #include "vchiq_core.h" #include "vchiq_debugfs.h" -enum vc_suspend_status { - VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */ - VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */ - VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */ - VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */ - VC_SUSPEND_REQUESTED, /* User has requested suspend */ - VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */ - VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */ -}; - -enum vc_resume_status { - VC_RESUME_FAILED = -1, /* Videocore resume failed */ - VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */ - VC_RESUME_REQUESTED, /* User has requested resume */ - VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */ - VC_RESUME_RESUMED /* Videocore resumed successfully (active) */ -}; - enum USE_TYPE_E { USE_TYPE_SERVICE, - USE_TYPE_SERVICE_NO_RESUME, USE_TYPE_VCHIQ }; @@ -46,19 +27,9 @@ struct vchiq_arm_state { atomic_t ka_use_ack_count; atomic_t ka_release_count; - struct completion vc_suspend_complete; - struct completion vc_resume_complete; - rwlock_t susp_res_lock; - enum vc_suspend_status vc_suspend_state; - enum vc_resume_status vc_resume_state; - - unsigned int wake_address; struct vchiq_state *state; - struct timer_list suspend_timer; - int suspend_timer_timeout; - int suspend_timer_running; /* Global use count for videocore. ** This is equal to the sum of the use counts for all services. When @@ -72,27 +43,11 @@ struct vchiq_arm_state { */ int peer_use_count; - /* Flag to indicate whether resume is blocked. This happens when the - ** ARM is suspending - */ - struct completion resume_blocker; - int resume_blocked; - struct completion blocked_blocker; - int blocked_count; - - int autosuspend_override; - /* Flag to indicate that the first vchiq connect has made it through. ** This means that both sides should be fully ready, and we should ** be able to suspend after this point. */ int first_connect; - - unsigned long long suspend_start_time; - unsigned long long sleep_start_time; - unsigned long long resume_start_time; - unsigned long long last_wake_time; - }; struct vchiq_drvdata { @@ -110,18 +65,9 @@ extern struct vchiq_state * vchiq_get_state(void); extern enum vchiq_status -vchiq_arm_vcsuspend(struct vchiq_state *state); - -extern enum vchiq_status -vchiq_arm_vcresume(struct vchiq_state *state); - -extern enum vchiq_status vchiq_arm_init_state(struct vchiq_state *state, struct vchiq_arm_state *arm_state); -extern int -vchiq_check_resume(struct vchiq_state *state); - extern void vchiq_check_suspend(struct vchiq_state *state); enum vchiq_status @@ -133,15 +79,6 @@ vchiq_release_service(unsigned int handle); extern enum vchiq_status vchiq_check_service(struct vchiq_service *service); -extern enum vchiq_status -vchiq_platform_suspend(struct vchiq_state *state); - -extern int -vchiq_platform_videocore_wanted(struct vchiq_state *state); - -extern int -vchiq_platform_use_suspend_timer(void); - extern void vchiq_dump_platform_use_state(struct vchiq_state *state); @@ -151,8 +88,6 @@ vchiq_dump_service_use_state(struct vchiq_state *state); extern struct vchiq_arm_state* vchiq_platform_get_arm_state(struct vchiq_state *state); -extern int -vchiq_videocore_wanted(struct vchiq_state *state); extern enum vchiq_status vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, @@ -176,15 +111,4 @@ vchiq_instance_get_trace(struct vchiq_instance *instance); extern void vchiq_instance_set_trace(struct vchiq_instance *instance, int trace); -extern void -set_suspend_state(struct vchiq_arm_state *arm_state, - enum vc_suspend_status new_state); - -extern void -set_resume_state(struct vchiq_arm_state *arm_state, - enum vc_resume_status new_state); - -extern void -start_suspend_timer(struct vchiq_arm_state *arm_state); - #endif /* VCHIQ_ARM_H */ 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 76351078affb..edcd97373809 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ +#include <linux/kref.h> +#include <linux/rcupdate.h> + #include "vchiq_core.h" #define VCHIQ_SLOT_HANDLER_STACK 8192 @@ -54,7 +57,6 @@ int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; -static DEFINE_SPINLOCK(service_spinlock); DEFINE_SPINLOCK(bulk_waiter_spinlock); static DEFINE_SPINLOCK(quota_spinlock); @@ -136,44 +138,41 @@ find_service_by_handle(unsigned int handle) { struct vchiq_service *service; - spin_lock(&service_spinlock); + rcu_read_lock(); service = handle_to_service(handle); - if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && - (service->handle == handle)) { - WARN_ON(service->ref_count == 0); - service->ref_count++; - } else - service = NULL; - spin_unlock(&service_spinlock); - - if (!service) - vchiq_log_info(vchiq_core_log_level, - "Invalid service handle 0x%x", handle); - - return service; + if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && + service->handle == handle && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); + return service; + } + rcu_read_unlock(); + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + return NULL; } struct vchiq_service * find_service_by_port(struct vchiq_state *state, int localport) { - struct vchiq_service *service = NULL; if ((unsigned int)localport <= VCHIQ_PORT_MAX) { - spin_lock(&service_spinlock); - service = state->services[localport]; - if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { - WARN_ON(service->ref_count == 0); - service->ref_count++; - } else - service = NULL; - spin_unlock(&service_spinlock); - } - - if (!service) - vchiq_log_info(vchiq_core_log_level, - "Invalid port %d", localport); + struct vchiq_service *service; - return service; + rcu_read_lock(); + service = rcu_dereference(state->services[localport]); + if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); + return service; + } + rcu_read_unlock(); + } + vchiq_log_info(vchiq_core_log_level, + "Invalid port %d", localport); + return NULL; } struct vchiq_service * @@ -182,22 +181,20 @@ find_service_for_instance(struct vchiq_instance *instance, { struct vchiq_service *service; - spin_lock(&service_spinlock); + rcu_read_lock(); service = handle_to_service(handle); - if (service && (service->srvstate != VCHIQ_SRVSTATE_FREE) && - (service->handle == handle) && - (service->instance == instance)) { - WARN_ON(service->ref_count == 0); - service->ref_count++; - } else - service = NULL; - spin_unlock(&service_spinlock); - - if (!service) - vchiq_log_info(vchiq_core_log_level, - "Invalid service handle 0x%x", handle); - - return service; + if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && + service->handle == handle && + service->instance == instance && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); + return service; + } + rcu_read_unlock(); + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); + return NULL; } struct vchiq_service * @@ -206,121 +203,125 @@ find_closed_service_for_instance(struct vchiq_instance *instance, { struct vchiq_service *service; - spin_lock(&service_spinlock); + rcu_read_lock(); service = handle_to_service(handle); if (service && - ((service->srvstate == VCHIQ_SRVSTATE_FREE) || - (service->srvstate == VCHIQ_SRVSTATE_CLOSED)) && - (service->handle == handle) && - (service->instance == instance)) { - WARN_ON(service->ref_count == 0); - service->ref_count++; - } else - service = NULL; - spin_unlock(&service_spinlock); - - if (!service) - vchiq_log_info(vchiq_core_log_level, - "Invalid service handle 0x%x", handle); - + (service->srvstate == VCHIQ_SRVSTATE_FREE || + service->srvstate == VCHIQ_SRVSTATE_CLOSED) && + service->handle == handle && + service->instance == instance && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); + return service; + } + rcu_read_unlock(); + vchiq_log_info(vchiq_core_log_level, + "Invalid service handle 0x%x", handle); return service; } 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; - spin_lock(&service_spinlock); while (idx < state->unused_service) { - struct vchiq_service *srv = state->services[idx++]; + struct vchiq_service *srv; - if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && - (srv->instance == instance)) { + srv = rcu_dereference(state->services[idx++]); + if (srv && srv->srvstate != VCHIQ_SRVSTATE_FREE && + srv->instance == instance) { service = srv; - WARN_ON(service->ref_count == 0); - service->ref_count++; break; } } - spin_unlock(&service_spinlock); *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(); + while (1) { + service = __next_service_by_instance(state, instance, pidx); + if (!service) + break; + if (kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + break; + } + } + rcu_read_unlock(); return service; } void lock_service(struct vchiq_service *service) { - spin_lock(&service_spinlock); - WARN_ON(!service); - if (service) { - WARN_ON(service->ref_count == 0); - service->ref_count++; + if (!service) { + WARN(1, "%s service is NULL\n", __func__); + return; } - spin_unlock(&service_spinlock); + kref_get(&service->ref_count); +} + +static void service_release(struct kref *kref) +{ + struct vchiq_service *service = + container_of(kref, struct vchiq_service, ref_count); + struct vchiq_state *state = service->state; + + WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + rcu_assign_pointer(state->services[service->localport], NULL); + if (service->userdata_term) + service->userdata_term(service->base.userdata); + kfree_rcu(service, rcu); } void unlock_service(struct vchiq_service *service) { - spin_lock(&service_spinlock); if (!service) { WARN(1, "%s: service is NULL\n", __func__); - goto unlock; - } - if (!service->ref_count) { - WARN(1, "%s: ref_count is zero\n", __func__); - goto unlock; - } - service->ref_count--; - if (!service->ref_count) { - struct vchiq_state *state = service->state; - - WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); - state->services[service->localport] = NULL; - } else { - service = NULL; + return; } -unlock: - spin_unlock(&service_spinlock); - - if (service && service->userdata_term) - service->userdata_term(service->base.userdata); - - kfree(service); + kref_put(&service->ref_count, service_release); } 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; } void * vchiq_get_service_userdata(unsigned int handle) { - struct vchiq_service *service = handle_to_service(handle); - - return service ? service->base.userdata : NULL; -} - -int -vchiq_get_service_fourcc(unsigned int handle) -{ - struct vchiq_service *service = handle_to_service(handle); + void *userdata; + struct vchiq_service *service; - return service ? service->base.fourcc : 0; + rcu_read_lock(); + service = handle_to_service(handle); + userdata = service ? service->base.userdata : NULL; + rcu_read_unlock(); + return userdata; } static void @@ -468,19 +469,23 @@ get_listening_service(struct vchiq_state *state, int fourcc) WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); + rcu_read_lock(); for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = state->services[i]; + struct vchiq_service *service; + service = rcu_dereference(state->services[i]); if (service && - (service->public_fourcc == fourcc) && - ((service->srvstate == VCHIQ_SRVSTATE_LISTENING) || - ((service->srvstate == VCHIQ_SRVSTATE_OPEN) && - (service->remoteport == VCHIQ_PORT_FREE)))) { - lock_service(service); + service->public_fourcc == fourcc && + (service->srvstate == VCHIQ_SRVSTATE_LISTENING || + (service->srvstate == VCHIQ_SRVSTATE_OPEN && + service->remoteport == VCHIQ_PORT_FREE)) && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); return service; } } - + rcu_read_unlock(); return NULL; } @@ -490,15 +495,20 @@ get_connected_service(struct vchiq_state *state, unsigned int port) { int i; + rcu_read_lock(); for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = state->services[i]; - - if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) - && (service->remoteport == port)) { - lock_service(service); + struct vchiq_service *service = + rcu_dereference(state->services[i]); + + if (service && service->srvstate == VCHIQ_SRVSTATE_OPEN && + service->remoteport == port && + kref_get_unless_zero(&service->ref_count)) { + service = rcu_pointer_handoff(service); + rcu_read_unlock(); return service; } } + rcu_read_unlock(); return NULL; } @@ -1798,7 +1808,6 @@ parse_rx_slots(struct vchiq_state *state) } /* At this point slot_mutex is held */ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); - vchiq_platform_paused(state); break; case VCHIQ_MSG_RESUME: vchiq_log_trace(vchiq_core_log_level, @@ -1807,7 +1816,6 @@ parse_rx_slots(struct vchiq_state *state) /* Release the slot mutex */ mutex_unlock(&state->slot_mutex); vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - vchiq_platform_resumed(state); break; case VCHIQ_MSG_REMOTE_USE: @@ -1817,7 +1825,6 @@ parse_rx_slots(struct vchiq_state *state) vchiq_on_remote_release(state); break; case VCHIQ_MSG_REMOTE_USE_ACTIVE: - vchiq_on_remote_use_active(state); break; default: @@ -1869,9 +1876,6 @@ slot_handler_func(void *v) DEBUG_TRACE(SLOT_HANDLER_LINE); if (state->poll_needed) { - /* Check if we need to suspend - may change our - * conn_state */ - vchiq_platform_check_suspend(state); state->poll_needed = 0; @@ -1897,10 +1901,6 @@ slot_handler_func(void *v) } break; - case VCHIQ_CONNSTATE_PAUSED: - vchiq_platform_resume(state); - break; - case VCHIQ_CONNSTATE_RESUMING: if (queue_message(state, NULL, VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), @@ -1908,7 +1908,6 @@ slot_handler_func(void *v) != VCHIQ_RETRY) { vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - vchiq_platform_resumed(state); } else { /* This should really be impossible, ** since the PAUSE should have flushed @@ -1918,11 +1917,6 @@ slot_handler_func(void *v) "message"); } break; - - case VCHIQ_CONNSTATE_PAUSE_TIMEOUT: - case VCHIQ_CONNSTATE_RESUME_TIMEOUT: - vchiq_platform_handle_timeout(state); - break; default: break; } @@ -2284,7 +2278,7 @@ vchiq_add_service_internal(struct vchiq_state *state, vchiq_userdata_term userdata_term) { struct vchiq_service *service; - struct vchiq_service **pservice = NULL; + struct vchiq_service __rcu **pservice = NULL; struct vchiq_service_quota *service_quota; int i; @@ -2296,7 +2290,7 @@ vchiq_add_service_internal(struct vchiq_state *state, service->base.callback = params->callback; service->base.userdata = params->userdata; service->handle = VCHIQ_SERVICE_HANDLE_INVALID; - service->ref_count = 1; + kref_init(&service->ref_count); service->srvstate = VCHIQ_SRVSTATE_FREE; service->userdata_term = userdata_term; service->localport = VCHIQ_PORT_FREE; @@ -2322,7 +2316,7 @@ vchiq_add_service_internal(struct vchiq_state *state, mutex_init(&service->bulk_mutex); memset(&service->stats, 0, sizeof(service->stats)); - /* Although it is perfectly possible to use service_spinlock + /* Although it is perfectly possible to use a spinlock ** to protect the creation of services, it is overkill as it ** disables interrupts while the array is searched. ** The only danger is of another thread trying to create a @@ -2340,17 +2334,17 @@ vchiq_add_service_internal(struct vchiq_state *state, if (srvstate == VCHIQ_SRVSTATE_OPENING) { for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *srv = state->services[i]; - - if (!srv) { + if (!rcu_access_pointer(state->services[i])) { pservice = &state->services[i]; break; } } } else { + rcu_read_lock(); for (i = (state->unused_service - 1); i >= 0; i--) { - struct vchiq_service *srv = state->services[i]; + struct vchiq_service *srv; + srv = rcu_dereference(state->services[i]); if (!srv) pservice = &state->services[i]; else if ((srv->public_fourcc == params->fourcc) @@ -2363,6 +2357,7 @@ vchiq_add_service_internal(struct vchiq_state *state, break; } } + rcu_read_unlock(); } if (pservice) { @@ -2374,7 +2369,7 @@ vchiq_add_service_internal(struct vchiq_state *state, (state->id * VCHIQ_MAX_SERVICES) | service->localport; handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; - *pservice = service; + rcu_assign_pointer(*pservice, service); if (pservice == &state->services[state->unused_service]) state->unused_service++; } @@ -2437,13 +2432,13 @@ vchiq_open_service_internal(struct vchiq_service *service, int client_id) status = VCHIQ_RETRY; vchiq_release_service_internal(service); } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && - (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { + (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) vchiq_log_error(vchiq_core_log_level, - "%d: osi - srvstate = %s (ref %d)", - service->state->id, - srvstate_names[service->srvstate], - service->ref_count); + "%d: osi - srvstate = %s (ref %u)", + service->state->id, + srvstate_names[service->srvstate], + kref_read(&service->ref_count)); status = VCHIQ_ERROR; VCHIQ_SERVICE_STATS_INC(service, error_count); vchiq_release_service_internal(service); @@ -3449,10 +3444,13 @@ int vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) char buf[80]; int len; int err; + unsigned int ref_count; + /*Don't include the lock just taken*/ + ref_count = kref_read(&service->ref_count) - 1; len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", - service->localport, srvstate_names[service->srvstate], - service->ref_count - 1); /*Don't include the lock just taken*/ + service->localport, srvstate_names[service->srvstate], + ref_count); if (service->srvstate != VCHIQ_SRVSTATE_FREE) { char remoteport[30]; 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 c31f953a9986..cedd8e721aae 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -7,6 +7,8 @@ #include <linux/mutex.h> #include <linux/completion.h> #include <linux/kthread.h> +#include <linux/kref.h> +#include <linux/rcupdate.h> #include <linux/wait.h> #include "vchiq_cfg.h" @@ -251,7 +253,8 @@ struct vchiq_slot_info { struct vchiq_service { struct vchiq_service_base base; unsigned int handle; - unsigned int ref_count; + struct kref ref_count; + struct rcu_head rcu; int srvstate; vchiq_userdata_term userdata_term; unsigned int localport; @@ -464,7 +467,7 @@ struct vchiq_state { int error_count; } stats; - struct vchiq_service *services[VCHIQ_MAX_SERVICES]; + struct vchiq_service __rcu *services[VCHIQ_MAX_SERVICES]; struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES]; struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS]; @@ -545,12 +548,13 @@ request_poll(struct vchiq_state *state, struct vchiq_service *service, static inline struct vchiq_service * handle_to_service(unsigned int handle) { + int idx = handle & (VCHIQ_MAX_SERVICES - 1); struct vchiq_state *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & (VCHIQ_MAX_STATES - 1)]; + if (!state) return NULL; - - return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; + return rcu_dereference(state->services[idx]); } extern struct vchiq_service * @@ -568,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 @@ -590,18 +600,6 @@ vchiq_complete_bulk(struct vchiq_bulk *bulk); extern void remote_event_signal(struct remote_event *event); -void -vchiq_platform_check_suspend(struct vchiq_state *state); - -extern void -vchiq_platform_paused(struct vchiq_state *state); - -extern enum vchiq_status -vchiq_platform_resume(struct vchiq_state *state); - -extern void -vchiq_platform_resumed(struct vchiq_state *state); - extern int vchiq_dump(void *dump_context, const char *str, int len); @@ -648,9 +646,6 @@ vchiq_platform_conn_state_changed(struct vchiq_state *state, enum vchiq_connstate newstate); extern void -vchiq_platform_handle_timeout(struct vchiq_state *state); - -extern void vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate); extern void diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h index 07c6a3db5ab6..39b77ea19210 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h @@ -13,7 +13,6 @@ #define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) #define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service) -#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service) enum vchiq_reason { VCHIQ_SERVICE_OPENED, /* service, -, - */ @@ -128,7 +127,6 @@ extern enum vchiq_status vchiq_bulk_receive_handle(unsigned int service, enum vchiq_bulk_mode mode); extern int vchiq_get_client_id(unsigned int service); extern void *vchiq_get_service_userdata(unsigned int service); -extern int vchiq_get_service_fourcc(unsigned int service); extern void vchiq_get_config(struct vchiq_config *config); extern enum vchiq_status vchiq_set_service_option(unsigned int service, enum vchiq_service_option option, int value); |