1371ebdbeSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 23baad68aSGreg Kroah-Hartman /* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ 371bad7f0Spopcornmix 471bad7f0Spopcornmix #include "vchiq_connected.h" 571bad7f0Spopcornmix #include "vchiq_core.h" 671bad7f0Spopcornmix #include <linux/module.h> 771bad7f0Spopcornmix #include <linux/mutex.h> 871bad7f0Spopcornmix 971bad7f0Spopcornmix #define MAX_CALLBACKS 10 1071bad7f0Spopcornmix 1171bad7f0Spopcornmix static int g_connected; 1271bad7f0Spopcornmix static int g_num_deferred_callbacks; 13e4c1935eSOjaswin Mujoo static void (*g_deferred_callback[MAX_CALLBACKS])(void); 1471bad7f0Spopcornmix static int g_once_init; 151790f2beSZheng Yongjun static DEFINE_MUTEX(g_connected_mutex); 1671bad7f0Spopcornmix 17619f70f0SJohn Oldman /* Function to initialize our lock */ 1871bad7f0Spopcornmix static void connected_init(void) 1971bad7f0Spopcornmix { 205b3087efSGaston Gonzalez if (!g_once_init) 2171bad7f0Spopcornmix g_once_init = 1; 2271bad7f0Spopcornmix } 2371bad7f0Spopcornmix 24619f70f0SJohn Oldman /* 2571bad7f0Spopcornmix * This function is used to defer initialization until the vchiq stack is 2671bad7f0Spopcornmix * initialized. If the stack is already initialized, then the callback will 2771bad7f0Spopcornmix * be made immediately, otherwise it will be deferred until 2871bad7f0Spopcornmix * vchiq_call_connected_callbacks is called. 29619f70f0SJohn Oldman */ 30e4c1935eSOjaswin Mujoo void vchiq_add_connected_callback(void (*callback)(void)) 3171bad7f0Spopcornmix { 3271bad7f0Spopcornmix connected_init(); 3371bad7f0Spopcornmix 34023dbe17SNicolas Saenz Julienne if (mutex_lock_killable(&g_connected_mutex)) 3571bad7f0Spopcornmix return; 3671bad7f0Spopcornmix 37*34197588SGaston Gonzalez if (g_connected) { 3871bad7f0Spopcornmix /* We're already connected. Call the callback immediately. */ 3971bad7f0Spopcornmix callback(); 40*34197588SGaston Gonzalez } else { 41*34197588SGaston Gonzalez if (g_num_deferred_callbacks >= MAX_CALLBACKS) { 4271bad7f0Spopcornmix vchiq_log_error(vchiq_core_log_level, 43c2ec4a6eSAmarjargal Gundjalam "There already %d callback registered - please increase MAX_CALLBACKS", 4471bad7f0Spopcornmix g_num_deferred_callbacks); 45*34197588SGaston Gonzalez } else { 4671bad7f0Spopcornmix g_deferred_callback[g_num_deferred_callbacks] = 4771bad7f0Spopcornmix callback; 4871bad7f0Spopcornmix g_num_deferred_callbacks++; 4971bad7f0Spopcornmix } 5071bad7f0Spopcornmix } 5171bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 5271bad7f0Spopcornmix } 53826818f8SStefan Wahren EXPORT_SYMBOL(vchiq_add_connected_callback); 5471bad7f0Spopcornmix 55619f70f0SJohn Oldman /* 5671bad7f0Spopcornmix * This function is called by the vchiq stack once it has been connected to 5771bad7f0Spopcornmix * the videocore and clients can start to use the stack. 58619f70f0SJohn Oldman */ 5971bad7f0Spopcornmix void vchiq_call_connected_callbacks(void) 6071bad7f0Spopcornmix { 6171bad7f0Spopcornmix int i; 6271bad7f0Spopcornmix 6371bad7f0Spopcornmix connected_init(); 6471bad7f0Spopcornmix 65023dbe17SNicolas Saenz Julienne if (mutex_lock_killable(&g_connected_mutex)) 6671bad7f0Spopcornmix return; 6771bad7f0Spopcornmix 6871bad7f0Spopcornmix for (i = 0; i < g_num_deferred_callbacks; i++) 6971bad7f0Spopcornmix g_deferred_callback[i](); 7071bad7f0Spopcornmix 7171bad7f0Spopcornmix g_num_deferred_callbacks = 0; 7271bad7f0Spopcornmix g_connected = 1; 7371bad7f0Spopcornmix mutex_unlock(&g_connected_mutex); 7471bad7f0Spopcornmix } 75