blob: bdb0ab617d8b939e368021032b7915502f36f62a [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
#include "vchiq_connected.h"
#include "vchiq_core.h"
#include <linux/module.h>
#include <linux/mutex.h>
#define MAX_CALLBACKS 10
static int g_connected;
static int g_num_deferred_callbacks;
static void (*g_deferred_callback[MAX_CALLBACKS])(void);
static int g_once_init;
static DEFINE_MUTEX(g_connected_mutex);
/* Function to initialize our lock */
static void connected_init(void)
{
if (!g_once_init)
g_once_init = 1;
}
/*
* This function is used to defer initialization until the vchiq stack is
* initialized. If the stack is already initialized, then the callback will
* be made immediately, otherwise it will be deferred until
* vchiq_call_connected_callbacks is called.
*/
void vchiq_add_connected_callback(void (*callback)(void))
{
connected_init();
if (mutex_lock_killable(&g_connected_mutex))
return;
if (g_connected) {
/* We're already connected. Call the callback immediately. */
callback();
} else {
if (g_num_deferred_callbacks >= MAX_CALLBACKS) {
vchiq_log_error(vchiq_core_log_level,
"There already %d callback registered - please increase MAX_CALLBACKS",
g_num_deferred_callbacks);
} else {
g_deferred_callback[g_num_deferred_callbacks] =
callback;
g_num_deferred_callbacks++;
}
}
mutex_unlock(&g_connected_mutex);
}
EXPORT_SYMBOL(vchiq_add_connected_callback);
/*
* This function is called by the vchiq stack once it has been connected to
* the videocore and clients can start to use the stack.
*/
void vchiq_call_connected_callbacks(void)
{
int i;
connected_init();
if (mutex_lock_killable(&g_connected_mutex))
return;
for (i = 0; i < g_num_deferred_callbacks; i++)
g_deferred_callback[i]();
g_num_deferred_callbacks = 0;
g_connected = 1;
mutex_unlock(&g_connected_mutex);
}