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