1371ebdbeSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 23baad68aSGreg Kroah-Hartman /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ 371bad7f0Spopcornmix 471bad7f0Spopcornmix #include "vchiq_connected.h" 571bad7f0Spopcornmix #include "vchiq_core.h" 671bad7f0Spopcornmix #include <linux/module.h> 771bad7f0Spopcornmix #include <linux/mutex.h> 871bad7f0Spopcornmix 971bad7f0Spopcornmix #define MAX_CALLBACKS 10 1071bad7f0Spopcornmix 1171bad7f0Spopcornmix static int g_connected; 1271bad7f0Spopcornmix static int g_num_deferred_callbacks; 1371bad7f0Spopcornmix static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; 1471bad7f0Spopcornmix static int g_once_init; 1571bad7f0Spopcornmix static struct mutex g_connected_mutex; 1671bad7f0Spopcornmix 1771bad7f0Spopcornmix /**************************************************************************** 1871bad7f0Spopcornmix * 1971bad7f0Spopcornmix * Function to initialize our lock. 2071bad7f0Spopcornmix * 2171bad7f0Spopcornmix ***************************************************************************/ 2271bad7f0Spopcornmix 2371bad7f0Spopcornmix static void connected_init(void) 2471bad7f0Spopcornmix { 2571bad7f0Spopcornmix if (!g_once_init) { 2671bad7f0Spopcornmix mutex_init(&g_connected_mutex); 2771bad7f0Spopcornmix g_once_init = 1; 2871bad7f0Spopcornmix } 2971bad7f0Spopcornmix } 3071bad7f0Spopcornmix 3171bad7f0Spopcornmix /**************************************************************************** 3271bad7f0Spopcornmix * 3371bad7f0Spopcornmix * This function is used to defer initialization until the vchiq stack is 3471bad7f0Spopcornmix * initialized. If the stack is already initialized, then the callback will 3571bad7f0Spopcornmix * be made immediately, otherwise it will be deferred until 3671bad7f0Spopcornmix * vchiq_call_connected_callbacks is called. 3771bad7f0Spopcornmix * 3871bad7f0Spopcornmix ***************************************************************************/ 3971bad7f0Spopcornmix 4071bad7f0Spopcornmix void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) 4171bad7f0Spopcornmix { 4271bad7f0Spopcornmix connected_init(); 4371bad7f0Spopcornmix 44b826d73bSArnd Bergmann if (mutex_lock_killable(&g_connected_mutex) != 0) 4571bad7f0Spopcornmix return; 4671bad7f0Spopcornmix 4771bad7f0Spopcornmix if (g_connected) 4871bad7f0Spopcornmix /* We're already connected. Call the callback immediately. */ 4971bad7f0Spopcornmix 5071bad7f0Spopcornmix callback(); 5171bad7f0Spopcornmix else { 5271bad7f0Spopcornmix if (g_num_deferred_callbacks >= MAX_CALLBACKS) 5371bad7f0Spopcornmix vchiq_log_error(vchiq_core_log_level, 5471bad7f0Spopcornmix "There already %d callback registered - " 5571bad7f0Spopcornmix "please increase MAX_CALLBACKS", 5671bad7f0Spopcornmix g_num_deferred_callbacks); 5771bad7f0Spopcornmix else { 5871bad7f0Spopcornmix g_deferred_callback[g_num_deferred_callbacks] = 5971bad7f0Spopcornmix callback; 6071bad7f0Spopcornmix g_num_deferred_callbacks++; 6171bad7f0Spopcornmix } 6271bad7f0Spopcornmix } 6371bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 6471bad7f0Spopcornmix } 6571bad7f0Spopcornmix 6671bad7f0Spopcornmix /**************************************************************************** 6771bad7f0Spopcornmix * 6871bad7f0Spopcornmix * This function is called by the vchiq stack once it has been connected to 6971bad7f0Spopcornmix * the videocore and clients can start to use the stack. 7071bad7f0Spopcornmix * 7171bad7f0Spopcornmix ***************************************************************************/ 7271bad7f0Spopcornmix 7371bad7f0Spopcornmix void vchiq_call_connected_callbacks(void) 7471bad7f0Spopcornmix { 7571bad7f0Spopcornmix int i; 7671bad7f0Spopcornmix 7771bad7f0Spopcornmix connected_init(); 7871bad7f0Spopcornmix 79b826d73bSArnd Bergmann if (mutex_lock_killable(&g_connected_mutex) != 0) 8071bad7f0Spopcornmix return; 8171bad7f0Spopcornmix 8271bad7f0Spopcornmix for (i = 0; i < g_num_deferred_callbacks; i++) 8371bad7f0Spopcornmix g_deferred_callback[i](); 8471bad7f0Spopcornmix 8571bad7f0Spopcornmix g_num_deferred_callbacks = 0; 8671bad7f0Spopcornmix g_connected = 1; 8771bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 8871bad7f0Spopcornmix } 8971bad7f0Spopcornmix EXPORT_SYMBOL(vchiq_add_connected_callback); 90