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