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 11static int g_connected; 12static int g_num_deferred_callbacks; 13static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS]; 14static int g_once_init; 15static DEFINE_MUTEX(g_connected_mutex); 16 17/* Function to initialize our lock */ 18static 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 */ 31void 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} 55EXPORT_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 */ 61void 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