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 VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; 14 static int g_once_init; 15 static DEFINE_MUTEX(g_connected_mutex); 16 17 /* Function to initialize our lock */ 18 static void connected_init(void) 19 { 20 if (!g_once_init) { 21 g_once_init = 1; 22 } 23 } 24 25 /* 26 * This function is used to defer initialization until the vchiq stack is 27 * initialized. If the stack is already initialized, then the callback will 28 * be made immediately, otherwise it will be deferred until 29 * vchiq_call_connected_callbacks is called. 30 */ 31 void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback) 32 { 33 connected_init(); 34 35 if (mutex_lock_killable(&g_connected_mutex)) 36 return; 37 38 if (g_connected) 39 /* We're already connected. Call the callback immediately. */ 40 41 callback(); 42 else { 43 if (g_num_deferred_callbacks >= MAX_CALLBACKS) 44 vchiq_log_error(vchiq_core_log_level, 45 "There already %d callback registered - please increase MAX_CALLBACKS", 46 g_num_deferred_callbacks); 47 else { 48 g_deferred_callback[g_num_deferred_callbacks] = 49 callback; 50 g_num_deferred_callbacks++; 51 } 52 } 53 mutex_unlock(&g_connected_mutex); 54 } 55 EXPORT_SYMBOL(vchiq_add_connected_callback); 56 57 /* 58 * This function is called by the vchiq stack once it has been connected to 59 * the videocore and clients can start to use the stack. 60 */ 61 void vchiq_call_connected_callbacks(void) 62 { 63 int i; 64 65 connected_init(); 66 67 if (mutex_lock_killable(&g_connected_mutex)) 68 return; 69 70 for (i = 0; i < g_num_deferred_callbacks; i++) 71 g_deferred_callback[i](); 72 73 g_num_deferred_callbacks = 0; 74 g_connected = 1; 75 mutex_unlock(&g_connected_mutex); 76 } 77