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; 151790f2beSZheng Yongjun static DEFINE_MUTEX(g_connected_mutex); 1671bad7f0Spopcornmix 17619f70f0SJohn Oldman /* Function to initialize our lock */ 1871bad7f0Spopcornmix static void connected_init(void) 1971bad7f0Spopcornmix { 2071bad7f0Spopcornmix if (!g_once_init) { 2171bad7f0Spopcornmix g_once_init = 1; 2271bad7f0Spopcornmix } 2371bad7f0Spopcornmix } 2471bad7f0Spopcornmix 25619f70f0SJohn Oldman /* 2671bad7f0Spopcornmix * This function is used to defer initialization until the vchiq stack is 2771bad7f0Spopcornmix * initialized. If the stack is already initialized, then the callback will 2871bad7f0Spopcornmix * be made immediately, otherwise it will be deferred until 2971bad7f0Spopcornmix * vchiq_call_connected_callbacks is called. 30619f70f0SJohn Oldman */ 3171bad7f0Spopcornmix void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) 3271bad7f0Spopcornmix { 3371bad7f0Spopcornmix connected_init(); 3471bad7f0Spopcornmix 35023dbe17SNicolas Saenz Julienne if (mutex_lock_killable(&g_connected_mutex)) 3671bad7f0Spopcornmix return; 3771bad7f0Spopcornmix 3871bad7f0Spopcornmix if (g_connected) 3971bad7f0Spopcornmix /* We're already connected. Call the callback immediately. */ 4071bad7f0Spopcornmix 4171bad7f0Spopcornmix callback(); 4271bad7f0Spopcornmix else { 4371bad7f0Spopcornmix if (g_num_deferred_callbacks >= MAX_CALLBACKS) 4471bad7f0Spopcornmix vchiq_log_error(vchiq_core_log_level, 45c2ec4a6eSAmarjargal Gundjalam "There already %d callback registered - please increase MAX_CALLBACKS", 4671bad7f0Spopcornmix g_num_deferred_callbacks); 4771bad7f0Spopcornmix else { 4871bad7f0Spopcornmix g_deferred_callback[g_num_deferred_callbacks] = 4971bad7f0Spopcornmix callback; 5071bad7f0Spopcornmix g_num_deferred_callbacks++; 5171bad7f0Spopcornmix } 5271bad7f0Spopcornmix } 5371bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 5471bad7f0Spopcornmix } 55*826818f8SStefan Wahren EXPORT_SYMBOL(vchiq_add_connected_callback); 5671bad7f0Spopcornmix 57619f70f0SJohn Oldman /* 5871bad7f0Spopcornmix * This function is called by the vchiq stack once it has been connected to 5971bad7f0Spopcornmix * the videocore and clients can start to use the stack. 60619f70f0SJohn Oldman */ 6171bad7f0Spopcornmix void vchiq_call_connected_callbacks(void) 6271bad7f0Spopcornmix { 6371bad7f0Spopcornmix int i; 6471bad7f0Spopcornmix 6571bad7f0Spopcornmix connected_init(); 6671bad7f0Spopcornmix 67023dbe17SNicolas Saenz Julienne if (mutex_lock_killable(&g_connected_mutex)) 6871bad7f0Spopcornmix return; 6971bad7f0Spopcornmix 7071bad7f0Spopcornmix for (i = 0; i < g_num_deferred_callbacks; i++) 7171bad7f0Spopcornmix g_deferred_callback[i](); 7271bad7f0Spopcornmix 7371bad7f0Spopcornmix g_num_deferred_callbacks = 0; 7471bad7f0Spopcornmix g_connected = 1; 7571bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 7671bad7f0Spopcornmix } 77