diff options
Diffstat (limited to 'drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c')
-rw-r--r-- | drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 542 |
1 files changed, 39 insertions, 503 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 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) |