blob: 0e1a8e5c14d69df106ed99a1728c17e22508126c [file] [log] [blame]
/******************************************************************************
*
* <:copyright-BRCM:2016:DUAL/GPL:standard
*
* Copyright (c) 2016 Broadcom
* All Rights Reserved
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed
* to you under the terms of the GNU General Public License version 2
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
* with the following added to such license:
*
* As a special exception, the copyright holders of this software give
* you permission to link this software with independent modules, and
* to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module.
* An independent module is a module which is not derived from this
* software. The special exception does not apply to any modifications
* of the software.
*
* Not withstanding the above, under no circumstances may you combine
* this software in any way with any other Broadcom software provided
* under a license other than the GPL, without Broadcom's express prior
* written consent.
*
* :>
*
*****************************************************************************/
/**
* @file fsm_common.c
* @brief Common code to support the BAL access terminal FSMs
*
* @addtogroup core
*/
/*@{*/
/*--- project includes ---*/
#include <bcmos_system.h>
#include <acc_term_fsm.h>
#include <bal_msg.h>
#include <bal_api.h>
#include "bal_worker.h"
#include "bal_mac_util.h"
#include "bal_switch_util.h"
#include <bal_osmsg.h>
#include <fsm_common.h>
#ifdef ENABLE_LOG
#include <bcm_dev_log.h>
#endif
/*****************************************************************************/
/**
* @brief Send a management message response
*
* A Worker module function that sends the specified message to the
* BAL Public API.
*
* @param cmd_status The results of the command associated with the message
*
* @param msg_payload A pointer to the message to be sent
*
* @param oper_type The operation type of the object in this response
*
* @param log_id The log id of the calling component
*
* @returns bcmos_errno
*
*****************************************************************************/
bcmos_errno mgmt_msg_send_balapi_rsp(bcmos_errno cmd_status,
void *msg_payload,
bcmbal_obj_msg_type oper_type,
dev_log_id log_id)
{
bcmos_errno ret = BCM_ERR_OK;
/* Parameter checks */
BUG_ON(NULL == msg_payload);
BCM_LOG(DEBUG, log_id, "sending rsp message to the public api (payload at %p)\n",
msg_payload);
/*
* Send the response back to the BAL Public API backend
*/
bcmbal_msg_hdr_set(msg_payload,
bcmbal_type_major_get(msg_payload),
BAL_MSG_TYPE_RSP,
BAL_SUBSYSTEM_CORE,
bcmbal_msg_id_obj_get(msg_payload),
bcmbal_msg_id_oper_get(msg_payload),
bcmbal_ex_id_get(msg_payload));
/* Return the command status to the Public API backend */
((bcmbal_obj *)(msg_payload))->status = cmd_status;
((bcmbal_obj *)(msg_payload))->dir = BCMBAL_OBJ_MSG_DIR_RESPONSE;
((bcmbal_obj *)(msg_payload))->type = oper_type;
if(BCM_ERR_OK != cmd_status)
{
((bcmbal_obj *)(msg_payload))->presence_mask = 0;
}
/* Send message, but don't free it. It is still being used by FSM */
if(BCM_ERR_OK != (ret = bcmbal_msg_send(p_bal_core_to_api_queue, msg_payload, BCMOS_MSG_SEND_NO_FREE_ON_ERROR)))
{
BCM_LOG(ERROR, log_id, "msg_send failed to send rsp to core (error:%s)\n",
bcmos_strerror(ret));
}
else
{
BCM_LOG(DEBUG, log_id, "RSP message sent to the public api with status=%s\n",
bcmos_strerror(cmd_status));
}
return ret;
}
/*****************************************************************************/
/**
* @brief Send a management message indication
*
* A Worker module function that sends the specified message to the
* BAL Public API.
*
* @param cmd_status The results of the command associated with the message
*
* @param is_auto_ind Set to BCMOS_TRUE if the indication to be sent is an AUTO IND
*
* @param msg_payload A pointer to the message to be sent (a BAL object!) (may be NULL)
*
* @param log_id The log id of the calling component
*
* @returns bcmos_errno
*
*****************************************************************************/
static bcmos_errno _mgmt_msg_send_balapi_ind(bcmos_errno cmd_status,
bcmos_bool is_auto_ind,
void *msg_payload, /* If this is NULL, there is no message body */
dev_log_id log_id)
{
bcmos_errno ret = BCM_ERR_OK;
uint16_t payload_size;
void *p_ind_msg;
bcmbal_obj_id obj_type;
if(NULL == msg_payload)
{
obj_type = BCMBAL_OBJ_ID_ANY;
payload_size = sizeof(bcmbal_obj);
}
else
{
switch(((bcmbal_obj *)msg_payload)->obj_type)
{
case (BCMBAL_OBJ_ID_FLOW):
{
payload_size = sizeof(bcmbal_flow_cfg);
break;
}
case (BCMBAL_OBJ_ID_ACCESS_TERMINAL):
{
payload_size = sizeof(bcmbal_access_terminal_cfg);
break;
}
case (BCMBAL_OBJ_ID_INTERFACE):
{
payload_size = sizeof(bcmbal_interface_cfg);
break;
}
case (BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL):
{
payload_size = sizeof(bcmbal_subscriber_terminal_cfg);
break;
}
case (BCMBAL_OBJ_ID_GROUP):
{
payload_size = sizeof(bcmbal_group_cfg);
break;
}
case (BCMBAL_OBJ_ID_TM_SCHED):
{
payload_size = sizeof(bcmbal_tm_sched_cfg);
break;
}
case (BCMBAL_OBJ_ID_TM_QUEUE):
{
payload_size = sizeof(bcmbal_tm_queue_cfg);
break;
}
default:
{
BCM_LOG(ERROR, log_id, "indication for object (%d) not supported\n",
((bcmbal_obj *)msg_payload)->obj_type);
ret = BCM_ERR_PARM;
goto out;
}
}
}
p_ind_msg = bcmbal_msg_calloc(payload_size);
if(NULL == msg_payload)
{
((bcmbal_obj *)p_ind_msg)->obj_type = obj_type;
}
else
{
memcpy(p_ind_msg, msg_payload, payload_size);
}
/*
* Send the indication back to the BAL Public API backend
*/
bcmbal_msg_hdr_set(p_ind_msg,
BCMBAL_MGMT_API_IND_MSG,
(BCMOS_TRUE == is_auto_ind) ? BAL_MSG_TYPE_AUTO_IND : BAL_MSG_TYPE_IND,
BAL_SUBSYSTEM_CORE,
((bcmbal_obj *)p_ind_msg)->obj_type,
0,
0);
/* Return the command status to the Public API backend */
((bcmbal_obj *)(p_ind_msg))->status = cmd_status;
((bcmbal_obj *)(p_ind_msg))->type = BCMBAL_OBJ_MSG_TYPE_GET;
((bcmbal_obj *)(p_ind_msg))->dir = BCMBAL_OBJ_MSG_DIR_RESPONSE;
BCM_LOG(DEBUG, log_id, "sending IND message to the public api (payload at %p)\n", p_ind_msg);
if(BCM_ERR_OK != (ret = bcmbal_msg_send(p_bal_core_to_api_ind_queue, p_ind_msg, BCMOS_MSG_SEND_AUTO_FREE)))
{
BCM_LOG(ERROR, log_id, "msg_send failed to send IND to public API (%s)\n", bcmos_strerror(ret));
}
else
{
BCM_LOG(DEBUG, log_id, "IND message sent to the public api with status=%s\n",
bcmos_strerror(cmd_status));
}
out:
return ret;
}
bcmos_errno mgmt_msg_send_balapi_ind(bcmos_errno cmd_status,
void *msg_payload, /* If this is NULL, there is no message body */
dev_log_id log_id)
{
return _mgmt_msg_send_balapi_ind(cmd_status,
BCMOS_FALSE,
msg_payload,
log_id);
}
bcmos_errno mgmt_msg_send_balapi_auto_ind(bcmos_errno cmd_status,
void *msg_payload, /* If this is NULL, there is no message body */
dev_log_id log_id)
{
return _mgmt_msg_send_balapi_ind(cmd_status,
BCMOS_TRUE,
msg_payload,
log_id);
}
/*****************************************************************************/
/**
* @brief Create and Start the FSM timer
*
* @param p_timer_inst A pointer to an instance of a timer data structure
*
* @param p_inst An opaque pointer to an FSM instance to be passed to the timer
* expiry handler
*
* @param p_timer_expiry_handler A timer expiry handler function
*
* @param delay The delay interval (in mS) for this timer to run before the
* expiry handler is called
*
* @param log_id The log_id to use when logging errors encountered in this
* function
*
* @returns bcmos_errno
*/
bcmos_errno fsm_timer_start(bcmos_timer *p_timer_inst,
void *p_inst,
F_bcmos_timer_handler p_timer_expiry_handler,
uint32_t delay, /* delay is in mS */
dev_log_id log_id)
{
bcmos_errno ret = BCM_ERR_OK;
bcmos_timer_parm timer_spec;
/* Parameter checks */
BUG_ON(p_inst == NULL);
BUG_ON(p_timer_expiry_handler == NULL);
BUG_ON(p_timer_inst == NULL);
/* Create bcm_os timer */
timer_spec.owner = BCMOS_MODULE_ID_WORKER_MGMT;
timer_spec.handler = p_timer_expiry_handler;
timer_spec.data = (long) p_inst;
timer_spec.periodic = BCMOS_FALSE;
if (BCM_ERR_OK != bcmos_timer_create(p_timer_inst, &timer_spec))
{
BCM_LOG(ERROR, log_id, "Can't create timer for FSM\n");
ret = BCM_ERR_NORES;
}
else
{
/* Start the timer. Timer resolution is in uS*/
bcmos_timer_start(p_timer_inst, delay*1000);
}
return ret;
}
/*****************************************************************************/
/**
* @brief Stop and delete the specified FSM timer
*
* @param p_timer_inst A pointer to an instance of a timer data structure
*
*/
void fsm_timer_stop(bcmos_timer *p_timer_inst)
{
/* Parameter checks */
BUG_ON(p_timer_inst == NULL);
bcmos_timer_destroy(p_timer_inst);
}
/*@}*/