1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ 3 4 #include "vchiq_connected.h" 5 #include "vchiq_core.h" 6 #include <linux/module.h> 7 #include <linux/mutex.h> 8 9 #define MAX_CALLBACKS 10 10 11 static int g_connected; 12 static int g_num_deferred_callbacks; 13 static void (*g_deferred_callback[MAX_CALLBACKS])(void); 14 static int g_once_init; 15 static DEFINE_MUTEX(g_connected_mutex); 16 17 /* Function to initialize our lock */ connected_init(void)18static void connected_init(void) 19 { 20 if (!g_once_init) 21 g_once_init = 1; 22 } 23 24 /* 25 * This function is used to defer initialization until the vchiq stack is 26 * initialized. If the stack is already initialized, then the callback will 27 * be made immediately, otherwise it will be deferred until 28 * vchiq_call_connected_callbacks is called. 29 */ vchiq_add_connected_callback(void (* callback)(void))30void vchiq_add_connected_callback(void (*callback)(void)) 31 { 32 connected_init(); 33 34 if (mutex_lock_killable(&g_connected_mutex)) 35 return; 36 37 if (g_connected) { 38 /* We're already connected. Call the callback immediately. */ 39 callback(); 40 } else { 41 if (g_num_deferred_callbacks >= MAX_CALLBACKS) { 42 vchiq_log_error(vchiq_core_log_level, 43 "There already %d callback registered - please increase MAX_CALLBACKS", 44 g_num_deferred_callbacks); 45 } else { 46 g_deferred_callback[g_num_deferred_callbacks] = 47 callback; 48 g_num_deferred_callbacks++; 49 } 50 } 51 mutex_unlock(&g_connected_mutex); 52 } 53 EXPORT_SYMBOL(vchiq_add_connected_callback); 54 55 /* 56 * This function is called by the vchiq stack once it has been connected to 57 * the videocore and clients can start to use the stack. 58 */ vchiq_call_connected_callbacks(void)59void vchiq_call_connected_callbacks(void) 60 { 61 int i; 62 63 connected_init(); 64 65 if (mutex_lock_killable(&g_connected_mutex)) 66 return; 67 68 for (i = 0; i < g_num_deferred_callbacks; i++) 69 g_deferred_callback[i](); 70 71 g_num_deferred_callbacks = 0; 72 g_connected = 1; 73 mutex_unlock(&g_connected_mutex); 74 } 75