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