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