int32_t vc_gpuserv_init( void ) { VCHIQ_SERVICE_PARAMS_T vchiq_params; VCOS_STATUS_T status = VCOS_ENXIO; VCHIQ_STATUS_T vchiq_status; vcos_once(&gpuserv_client_once, init_once); vcos_mutex_lock(&gpuserv_client.lock); if (gpuserv_client.refcount++ > 0) { /* Already initialised so nothing to do */ vcos_mutex_unlock(&gpuserv_client.lock); return VCOS_SUCCESS; } vcos_log_set_level(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE); vcos_log_register("gpuserv", VCOS_LOG_CATEGORY); vcos_log_trace("%s: starting initialisation", VCOS_FUNCTION); /* Initialise a VCHIQ instance */ vchiq_status = vchiq_initialise(&gpuserv_client_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: failed to initialise vchiq: %d", VCOS_FUNCTION, vchiq_status); goto error; } vchiq_status = vchiq_connect(gpuserv_client_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: failed to connect to vchiq: %d", VCOS_FUNCTION, vchiq_status); goto error; } memset(&vchiq_params, 0, sizeof(vchiq_params)); vchiq_params.fourcc = VCHIQ_MAKE_FOURCC('G','P','U','S'); vchiq_params.callback = gpuserv_callback; vchiq_params.userdata = NULL; vchiq_params.version = 1; vchiq_params.version_min = 1; vchiq_status = vchiq_open_service(gpuserv_client_vchiq_instance, &vchiq_params, &gpuserv_client.service); if (vchiq_status != VCHIQ_SUCCESS) { vcos_log_error("%s: could not open vchiq service: %d", VCOS_FUNCTION, vchiq_status); goto error; } vcos_mutex_unlock(&gpuserv_client.lock); return 0; error: vcos_mutex_unlock(&gpuserv_client.lock); return -1; }
/*********************************************************** * Name: vchi_connect * * Arguments: VCHI_CONNECTION_T **connections * const uint32_t num_connections * VCHI_INSTANCE_T instance_handle) * * Description: Starts the command service on each connection, * causing INIT messages to be pinged back and forth * * Returns: 0 if successful, failure otherwise * ***********************************************************/ int32_t vchi_connect(VCHI_CONNECTION_T **connections, const uint32_t num_connections, VCHI_INSTANCE_T instance_handle) { VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; (void)connections; (void)num_connections; return vchiq_connect(instance); }
void vc_vchi_khronos_init() { VCOS_STATUS_T status = vcos_event_create(&bulk_event, NULL); assert(status == VCOS_SUCCESS); if (vchiq_initialise(&khrn_vchiq_instance) != VCHIQ_SUCCESS) { KHRONOS_CLIENT_LOG("* failed to open vchiq device\n"); exit(1); } KHRONOS_CLIENT_LOG("gldemo: connecting\n"); if (vchiq_connect(khrn_vchiq_instance) != VCHIQ_SUCCESS) { KHRONOS_CLIENT_LOG("* failed to connect\n"); exit(1); } if (vchiq_open_service(khrn_vchiq_instance, FOURCC_KHAN, khan_callback, NULL, &vchiq_khan_service) != VCHIQ_SUCCESS || vchiq_open_service(khrn_vchiq_instance, FOURCC_KHRN, khrn_callback, NULL, &vchiq_khrn_service) != VCHIQ_SUCCESS || vchiq_open_service(khrn_vchiq_instance, FOURCC_KHHN, khhn_callback, NULL, &vchiq_khhn_service) != VCHIQ_SUCCESS) { KHRONOS_CLIENT_LOG("* failed to add service - already in use?\n"); exit(1); } vchiu_queue_init(&khrn_queue, 64); vchiu_queue_init(&khhn_queue, 64); KHRONOS_CLIENT_LOG("gldemo: connected\n"); /* attach to process (there's just one) */ // bool success = client_process_attach(); // assert(success); }
MMAL_STATUS_T mmal_vc_init(void) { VCHIQ_SERVICE_PARAMS_T vchiq_params; MMAL_BOOL_T vchiq_initialised = 0, waitpool_initialised = 0; MMAL_BOOL_T service_initialised = 0; MMAL_STATUS_T status = MMAL_EIO; VCHIQ_STATUS_T vchiq_status; int count; vcos_once(&once, init_once); vcos_mutex_lock(&client.lock); count = client.refcount++; if (count > 0) { /* Already initialised so nothing to do */ vcos_mutex_unlock(&client.lock); return MMAL_SUCCESS; } vcos_log_register("mmalipc", VCOS_LOG_CATEGORY); /* Initialise a VCHIQ instance */ vchiq_status = vchiq_initialise(&mmal_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { LOG_ERROR("failed to initialise vchiq"); status = MMAL_EIO; goto error; } vchiq_initialised = 1; vchiq_status = vchiq_connect(mmal_vchiq_instance); if (vchiq_status != VCHIQ_SUCCESS) { LOG_ERROR("failed to connect to vchiq"); status = MMAL_EIO; goto error; } memset(&vchiq_params,0,sizeof(vchiq_params)); vchiq_params.fourcc = MMAL_CONTROL_FOURCC(); vchiq_params.callback = mmal_vc_vchiq_callback; vchiq_params.userdata = &client; vchiq_params.version = WORKER_VER_MAJOR; vchiq_params.version_min = WORKER_VER_MINIMUM; vchiq_status = vchiq_open_service(mmal_vchiq_instance, &vchiq_params, &client.service); if (vchiq_status != VCHIQ_SUCCESS) { LOG_ERROR("could not open vchiq service"); status = MMAL_EIO; goto error; } client.usecount = 1; /* usecount set to 1 by the open call. */ service_initialised = 1; status = create_waitpool(&client.waitpool); if (status != MMAL_SUCCESS) { LOG_ERROR("could not create wait pool"); goto error; } waitpool_initialised = 1; if (vcos_mutex_create(&client.bulk_lock, "mmal client bulk lock") != VCOS_SUCCESS) { LOG_ERROR("could not create bulk lock"); status = MMAL_ENOSPC; goto error; } client.inited = 1; vcos_mutex_unlock(&client.lock); /* assume we're not using VC immediately. Do this outside the lock */ mmal_vc_release(); return MMAL_SUCCESS; error: if (waitpool_initialised) destroy_waitpool(&client.waitpool); if (service_initialised) { client.usecount = 0; vchiq_close_service(client.service); } if (vchiq_initialised) vchiq_shutdown(mmal_vchiq_instance); vcos_log_unregister(VCOS_LOG_CATEGORY); client.refcount--; vcos_mutex_unlock(&client.lock); return status; }
static int vc_watchdog_thread_func(void *v) { while (1) { long rc; unsigned long msg = WDOG_PING_MSG; VCHIQ_ELEMENT_T elem = { .data = (void *)&msg, .size = sizeof(msg) }; int time_remaining = msecs_to_jiffies(WATCHDOG_PING_RATE_MS); LOG_DBG("%s: waiting on disable blocker...", __func__); if (wait_for_completion_interruptible( &vc_wdog_state->wdog_disable_blocker) != 0) { flush_signals(current); continue; } LOG_DBG("%s: Waiting for VC to be awake...", __func__); /* Ensure we only ping videocore when it's awake. Call use * service in a mode which will not initiate a wakeup */ vchiq_use_service_no_resume(vc_wdog_state->service_handle); if (!atomic_read(&vc_wdog_state->wdog_enabled)) { vchiq_release_service(vc_wdog_state->service_handle); LOG_DBG("%s: VC watchdog disabled", __func__); continue; } if (mutex_lock_interruptible(&vc_wdog_state->wdog_ping_mutex) != 0) { vchiq_release_service(vc_wdog_state->service_handle); LOG_DBG("%s: Interrupted waiting for ping", __func__); continue; } LOG_DBG("%s: Pinging videocore", __func__); /* ping vc... */ vchiq_queue_message(vc_wdog_state->service_handle, &elem, 1); LOG_DBG("%s: Waiting for ping response", __func__); /* ...and wait for the response with a timeout */ rc = wait_for_completion_interruptible_timeout( &vc_wdog_state->wdog_ping_response, msecs_to_jiffies(VC_PING_RESPONSE_TIMEOUT_MS)); if (rc == 0) { /* Timed out... BANG! */ vc_wdog_state->failed_pings++; LOG_ERR("%s VideoCore Watchdog timed out!! (%d)", __func__, vc_wdog_state->failed_pings); if (vc_wdog_state->failed_pings >= WATCHDOG_NO_RESPONSE_COUNT) BUG(); } else if (rc < 0) LOG_ERR("%s: Interrupted waiting for ping", __func__); else { LOG_DBG("%s: Ping response received", __func__); vc_wdog_state->failed_pings = 0; } mutex_unlock(&vc_wdog_state->wdog_ping_mutex); vchiq_release_service(vc_wdog_state->service_handle); LOG_DBG("%s: waiting before pinging again...", __func__); /* delay before running again */ do { set_current_state(TASK_INTERRUPTIBLE); time_remaining = schedule_timeout(time_remaining); if (time_remaining) { LOG_ERR("%s interrupted", __func__); flush_signals(current); } } while (time_remaining > 0); } return 0; } static void vc_watchdog_connected_init(void) { int ret = 0; VCHIQ_SERVICE_PARAMS_T vchiq_params = { .fourcc = VCHIQ_MAKE_FOURCC('W', 'D', 'O', 'G'), .callback = vc_watchdog_vchiq_callback, .version = VC_WDOG_VERSION, .version_min = VC_WDOG_VERSION_MIN }; LOG_INFO("%s: start", __func__); /* Initialize and create a VCHIQ connection */ ret = vchiq_initialise(&vc_wdog_state->initialise_instance); if (ret != 0) { LOG_ERR("%s: failed to initialise VCHIQ instance (ret=%d)", __func__, ret); ret = -EIO; goto out; } ret = vchiq_connect(vc_wdog_state->initialise_instance); if (ret != 0) { LOG_ERR("%s: failed to connect VCHIQ instance (ret=%d)", __func__, ret); ret = -EIO; goto out; } ret = vchiq_open_service(vc_wdog_state->initialise_instance, &vchiq_params, &vc_wdog_state->service_handle); if (ret != 0 || (vc_wdog_state->service_handle == 0)) { LOG_ERR("%s: failed to add WDOG service: error %d", __func__, ret); ret = -EPERM; goto out; } vchiq_release_service(vc_wdog_state->service_handle); init_completion(&vc_wdog_state->wdog_ping_response); mutex_init(&vc_wdog_state->wdog_ping_mutex); init_completion(&vc_wdog_state->wdog_disable_blocker); #ifdef ENABLE_VC_WATCHDOG complete_all(&vc_wdog_state->wdog_disable_blocker); atomic_set(&vc_wdog_state->wdog_enabled, 1); #else atomic_set(&vc_wdog_state->wdog_enabled, 0); #endif vc_wdog_state->wdog_thread = kthread_create( &vc_watchdog_thread_func, NULL, "vc-watchdog"); if (vc_wdog_state->wdog_thread == NULL) LOG_ERR("FATAL: couldn't create thread vc-watchdog"); else wake_up_process(vc_wdog_state->wdog_thread); out: LOG_INFO("%s: end (ret=%d)", __func__, ret); } static int vc_watchdog_probe(struct platform_device *p_dev) { int ret = 0; LOG_INFO("%s: start", __func__); vc_wdog_state = kzalloc(sizeof(struct vc_watchdog_state), GFP_KERNEL); if (!vc_wdog_state) { ret = -ENOMEM; goto exit; } vc_wdog_state->p_dev = p_dev; vc_wdog_state->proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); if (vc_wdog_state->proc_entry == NULL) { ret = -EFAULT; goto out_efault; } vc_wdog_state->proc_entry->data = (void *)vc_wdog_state; vc_wdog_state->proc_entry->write_proc = vc_watchdog_proc_write; vchiq_add_connected_callback(vc_watchdog_connected_init); goto exit; out_efault: kfree(vc_wdog_state); vc_wdog_state = NULL; exit: LOG_INFO("%s: end, ret=%d", __func__, ret); return ret; }