You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
558 lines
17 KiB
558 lines
17 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
|
|
* Description: common code in mailbox driver
|
|
*/
|
|
#include "mbx_common.h"
|
|
#include "los_mbx.h"
|
|
|
|
#include "securec.h"
|
|
#include "los_printf.h"
|
|
#include "los_base.h"
|
|
#include "los_memory.h"
|
|
#include "los_mux.h"
|
|
|
|
#include <string.h>
|
|
|
|
static struct mailbox g_mailbox = {0};
|
|
|
|
static void rx_tail(struct session * const session, const union msg_head *rx_head)
|
|
{
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
td_u32 handle;
|
|
#endif
|
|
|
|
if (!rx_head->bits.ongoing) {
|
|
session->rx_status &= ~SESSION_BUSY;
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
handle = GEN_SESSION_HANDLE(rx_head->bits.num, rx_head->bits.port);
|
|
/* Call session callback func */
|
|
if (session->func != NULL) {
|
|
session->func(handle, session->data);
|
|
}
|
|
#endif
|
|
} else {
|
|
session->rx_status |= SESSION_BUSY;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static td_s32 rx(struct session * const session, const union msg_head *rx_head)
|
|
{
|
|
td_u32 rd_idx, wr_idx, empty_len;
|
|
td_u32 i, j, tmp_data;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if ((session == NULL) || (rx_head == NULL) || (session->rx_reg == NULL) || (session->rx_reg->pending == NULL)) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
|
|
session->rx_status |= SESSION_BUSY;
|
|
wr_idx = session->rx_buf.wr_idx;
|
|
rd_idx = session->rx_buf.rd_idx;
|
|
if (rd_idx > wr_idx) {
|
|
empty_len = rd_idx - wr_idx;
|
|
} else {
|
|
empty_len = session->rx_buf.size + rd_idx - wr_idx;
|
|
}
|
|
if (rx_head->bits.msg_len >= empty_len) {
|
|
session->rx_status &= ~SESSION_BUSY;
|
|
return SOC_ERR_MAILBOX_ERR_RECEIVE;
|
|
}
|
|
for (i = 0; i < rx_head->bits.msg_len / 4; i++) { /* copy 4 bytes for each time */
|
|
tmp_data = MBX_READL(session->rx_reg->argv + i);
|
|
for (j = 0; j < 4; j++) { /* copy 4 bytes in a register */
|
|
session->rx_buf.addr[wr_idx++] = (tmp_data >> (8 * j)) & 0xFF; /* 8 bits offset with 0xFF mask */
|
|
wr_idx %= session->rx_buf.size;
|
|
}
|
|
}
|
|
if (rx_head->bits.msg_len % 4) { /* copy left bytes less then 4 bytes */
|
|
tmp_data = MBX_READL(session->rx_reg->argv + i);
|
|
for (j = 0; j < rx_head->bits.msg_len % 4; j++) { /* copy for less 4 bytes in a register */
|
|
session->rx_buf.addr[wr_idx++] = (tmp_data >> (8 * j)) & 0xFF; /* 8 bits offset with 0xFF mask */
|
|
wr_idx %= session->rx_buf.size;
|
|
}
|
|
}
|
|
session->rx_buf.wr_idx = wr_idx;
|
|
rx_tail(session, rx_head);
|
|
|
|
/* Clean rx pending status */
|
|
MBX_WRITEL(0x00, (session->rx_reg->pending));
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
static struct session *find_session(td_u32 session_num, td_u32 session_port)
|
|
{
|
|
struct session *session = NULL;
|
|
struct session *tmp = NULL;
|
|
|
|
MBX_LIST_FOR_EACH_ENTRY(session, tmp, &g_mailbox.list_head, node) {
|
|
if ((session->num == session_num) && (session->port == session_port)) {
|
|
return session;
|
|
}
|
|
}
|
|
|
|
MBX_LIST_FOR_EACH_ENTRY(session, tmp, &g_mailbox.list_head, node) {
|
|
if ((session->num == session_num) && (session->port == 0)) {
|
|
return session;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
td_s32 mbx_rx_msg(const td_void *rx_head_addr)
|
|
{
|
|
struct session *session = NULL;
|
|
union msg_head rx_head = {.head = 0};
|
|
td_s32 ret;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
|
|
if (rx_head_addr == NULL) {
|
|
return SOC_ERR_MAILBOX_INVALID_PTR;
|
|
}
|
|
|
|
rx_head.head = MBX_READL(rx_head_addr);
|
|
session = find_session(rx_head.bits.num, rx_head.bits.port);
|
|
if ((session == NULL) || (session->rx_reg == NULL) || (session->rx_reg->pending == NULL)) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
|
|
if ((void *)MBX_READL((session->rx_reg->pending)) != NULL) {
|
|
if (rx_head.bits.msg_len != 0) {
|
|
ret = rx(session, &rx_head);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
MBX_ERR_PRINT("Receive in mbx_rx_msg and ret:0x%x\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
} else {
|
|
return SOC_ERR_MAILBOX_ERR_RECEIVE;
|
|
}
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
static td_s32 async_tx(td_u32 handle, const td_u8 *msg, td_u32 msg_len)
|
|
{
|
|
td_u32 i;
|
|
td_u32 rd_idx;
|
|
td_u32 wr_idx;
|
|
td_u32 empty_len;
|
|
struct session *session = NULL;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if (msg_len == 0) {
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
session = find_session(SESSION_HANDLE_NUM(handle), SESSION_HANDLE_PORT(handle));
|
|
if (session == NULL) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
if (session->tx_buf.addr == NULL) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
wr_idx = session->tx_buf.wr_idx;
|
|
rd_idx = session->tx_buf.rd_idx;
|
|
if (rd_idx > wr_idx) {
|
|
empty_len = rd_idx - wr_idx;
|
|
} else {
|
|
empty_len = session->tx_buf.size + rd_idx - wr_idx;
|
|
}
|
|
if (msg_len >= empty_len) {
|
|
session->tx_status = (td_s32)SOC_ERR_MAILBOX_NO_MEMORY;
|
|
return SOC_ERR_MAILBOX_NO_MEMORY;
|
|
}
|
|
|
|
for (i = 0; i < msg_len; i++) {
|
|
session->tx_buf.addr[wr_idx++] = msg[i];
|
|
wr_idx %= session->tx_buf.size;
|
|
}
|
|
session->tx_buf.wr_idx = wr_idx;
|
|
session->tx_status = (td_s32)SOC_ERR_MAILBOX_PENDING;
|
|
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
|
|
static td_s32 sync_tx_to_reg(struct session *session, const td_u8 *msg, td_u32 msg_len, td_s32 tx_count)
|
|
{
|
|
td_s32 i, tmp_data;
|
|
|
|
if ((session == TD_NULL) || (msg == TD_NULL) || (session->tx_reg == TD_NULL) ||
|
|
(session->tx_reg->argv == TD_NULL)) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
|
|
for (i = 0; i < msg_len / 4; i++) { /* write body data with 4 bytes every times */
|
|
tmp_data = 0;
|
|
if (memcpy_s(&tmp_data, sizeof(tmp_data), &msg[i * 4 + tx_count], sizeof(td_s32))) { /* offset 4 step */
|
|
MBX_ERR_PRINT("memcpy_s failed\n");
|
|
return SOC_MBX_FAILURE;
|
|
}
|
|
MBX_WRITEL(tmp_data, session->tx_reg->argv + i);
|
|
}
|
|
if (msg_len % 4) { /* for left data that less than 4 bytes */
|
|
tmp_data = 0;
|
|
if (memcpy_s(&tmp_data, sizeof(tmp_data), &msg[i * 4 + tx_count], msg_len % 4)) { /* offset 4 step */
|
|
MBX_ERR_PRINT("memcpy_s failed\n");
|
|
return SOC_MBX_FAILURE;
|
|
}
|
|
MBX_WRITEL(tmp_data, session->tx_reg->argv + i);
|
|
}
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
static td_s32 check_param(td_u32 handle, const td_u8 *msg, td_u32 msg_len, struct session **ptr_session)
|
|
{
|
|
struct session *session = NULL;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if (msg_len == 0) {
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
|
|
session = find_session(SESSION_HANDLE_NUM(handle), SESSION_HANDLE_PORT(handle));
|
|
if ((session == NULL) || (msg == NULL) || (session->tx_reg == NULL) ||
|
|
(session->tx_reg->argv == NULL) || (session->tx_reg->trigger_rx == NULL) ||
|
|
(session->tx_reg->head == NULL) || (session->tx_reg->lock == NULL) || (session->tx_reg->pending == NULL)) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
|
|
*ptr_session = session;
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
static td_void load_tx_head(td_u32 handle, union msg_head *tx_head, struct session *session, td_u32 *len)
|
|
{
|
|
td_u32 msg_len = *len;
|
|
|
|
/* write head data */
|
|
tx_head->bits.num = session->num;
|
|
tx_head->bits.port = SESSION_HANDLE_PORT(handle);
|
|
tx_head->bits.msg_len = msg_len / session->tx_reg->argv_size ? \
|
|
session->tx_reg->argv_size : msg_len % session->tx_reg->argv_size;
|
|
|
|
msg_len -= tx_head->bits.msg_len;
|
|
if (msg_len == 0) {
|
|
tx_head->bits.ongoing = TD_FALSE;
|
|
session->tx_status = SOC_MBX_SUCCESS;
|
|
} else {
|
|
tx_head->bits.ongoing = TD_TRUE;
|
|
session->tx_status = (td_s32)SOC_ERR_MAILBOX_PENDING;
|
|
}
|
|
MBX_WRITEL(tx_head->head, session->tx_reg->head);
|
|
*len = msg_len;
|
|
}
|
|
|
|
static td_s32 sync_tx(td_u32 handle, const td_u8 *msg, td_u32 msg_len, td_u32 timeout)
|
|
{
|
|
td_s32 tx_count, ret;
|
|
td_u32 status;
|
|
struct session *session = NULL;
|
|
union msg_head tx_head = {.head = 0};
|
|
td_ulong lock_flag;
|
|
ret = check_param(handle, msg, msg_len, &session);
|
|
if ((ret != SOC_MBX_SUCCESS) || (session == NULL)) {
|
|
return ret;
|
|
}
|
|
|
|
tx_count = 0;
|
|
while (1) {
|
|
spin_lock_irqsave(session->tx_reg->lock, &lock_flag);
|
|
status = MBX_READL((session->tx_reg->pending));
|
|
spin_unlock_irqrestore(session->tx_reg->lock, &lock_flag);
|
|
if (status) {
|
|
MBX_UDELAY(MBX_DELAY_TIME);
|
|
if (timeout > MBX_DELAY_TIME) {
|
|
timeout = timeout - MBX_DELAY_TIME;
|
|
} else {
|
|
return SOC_ERR_MAILBOX_TIMEOUT;
|
|
}
|
|
continue;
|
|
}
|
|
/* break until sending completion */
|
|
if (msg_len <= 0) {
|
|
break;
|
|
}
|
|
spin_lock_irqsave(session->tx_reg->lock, &lock_flag);
|
|
status = MBX_READL((session->tx_reg->pending));
|
|
if (status) {
|
|
spin_unlock_irqrestore(session->tx_reg->lock, &lock_flag);
|
|
continue;
|
|
}
|
|
|
|
load_tx_head(handle, &tx_head, session, &msg_len);
|
|
|
|
ret = sync_tx_to_reg(session, msg, tx_head.bits.msg_len, tx_count);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
spin_unlock_irqrestore(session->tx_reg->lock, &lock_flag);
|
|
return ret;
|
|
}
|
|
/* trigger rx interrupt in other side */
|
|
MBX_WRITEL(0x01, session->tx_reg->trigger_rx); /* write 0x01 to trigger */
|
|
tx_count += (td_s32)tx_head.bits.msg_len;
|
|
spin_unlock_irqrestore(session->tx_reg->lock, &lock_flag);
|
|
}
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
td_s32 mbx_tx(td_u32 handle, const td_u8 *msg, td_u32 msg_len, td_u32 * const tx_len, td_u32 timeout)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (tx_len == NULL) {
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
*tx_len = 0;
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if (msg == NULL) {
|
|
*tx_len = 0;
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
if (msg_len == 0) {
|
|
*tx_len = 0;
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
if (timeout == 0) {
|
|
ret = async_tx(handle, msg, msg_len);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
*tx_len = 0;
|
|
return ret;
|
|
}
|
|
} else {
|
|
ret = sync_tx(handle, msg, msg_len, timeout);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
*tx_len = 0;
|
|
return ret;
|
|
}
|
|
}
|
|
*tx_len = msg_len;
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
td_s32 mbx_rx(td_u32 handle, td_u8 *msg, td_u32 msg_len, td_u32 * const rx_len, td_u32 timeout)
|
|
{
|
|
struct session *session = NULL;
|
|
td_u32 status, rd_idx, wr_idx;
|
|
td_u32 i, len;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
*rx_len = 0;
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if ((msg == NULL) || (msg_len == 0) || (rx_len == NULL)) {
|
|
return SOC_ERR_MAILBOX_INVALID_PARA;
|
|
}
|
|
|
|
session = find_session(SESSION_HANDLE_NUM(handle), SESSION_HANDLE_PORT(handle));
|
|
if (session == NULL) {
|
|
*rx_len = 0;
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
rd_idx = session->rx_buf.rd_idx;
|
|
wr_idx = session->rx_buf.wr_idx;
|
|
status = session->rx_status & SESSION_BUSY;
|
|
while (status || !(wr_idx - rd_idx)) {
|
|
MBX_UDELAY(MBX_DELAY_TIME);
|
|
/* Receive message with polling mode if not support interrupt */
|
|
mbx_polling_rx();
|
|
if (timeout > MBX_DELAY_TIME) {
|
|
timeout = timeout - MBX_DELAY_TIME;
|
|
}
|
|
if (timeout <= MBX_DELAY_TIME) {
|
|
*rx_len = 0;
|
|
return SOC_ERR_MAILBOX_TIMEOUT;
|
|
}
|
|
rd_idx = session->rx_buf.rd_idx;
|
|
wr_idx = session->rx_buf.wr_idx;
|
|
status = session->rx_status & SESSION_BUSY;
|
|
}
|
|
if (wr_idx > rd_idx) {
|
|
len = wr_idx - rd_idx;
|
|
} else {
|
|
len = session->rx_buf.size + wr_idx - rd_idx;
|
|
}
|
|
len = msg_len > len ? len : msg_len;
|
|
for (i = 0; i < len; i++) {
|
|
msg[i] = session->rx_buf.addr[rd_idx++];
|
|
rd_idx %= session->rx_buf.size;
|
|
}
|
|
session->rx_buf.rd_idx = rd_idx;
|
|
*rx_len = len;
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
td_s32 mbx_register_irq_callback(td_u32 handle, session_callback func, const td_void * const data)
|
|
{
|
|
struct session *session = NULL;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
session = find_session(SESSION_HANDLE_NUM(handle), SESSION_HANDLE_PORT(handle));
|
|
if (session == NULL) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
session->func = func;
|
|
session->data = data;
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
static struct session *mbx_alloc_session(td_u32 session_id, td_u32 rx_buf_size, td_u32 tx_buf_size)
|
|
{
|
|
struct session *session = NULL;
|
|
struct session *tmp = NULL;
|
|
td_u32 port;
|
|
|
|
port = 0;
|
|
|
|
/* find the minimun port of free session in the list */
|
|
retry:
|
|
MBX_LIST_FOR_EACH_ENTRY(session, tmp, &g_mailbox.list_head, node) {
|
|
if (session->num == SESSION_ID_NUM(session_id)) {
|
|
if (port == session->port) {
|
|
port++;
|
|
goto retry;
|
|
}
|
|
}
|
|
}
|
|
|
|
session = (struct session *)MBX_MALLOC(sizeof(struct session));
|
|
if (session == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
(void)memset_s(session, sizeof(struct session), 0, sizeof(struct session) - 1);
|
|
session->num = SESSION_ID_NUM(session_id);
|
|
session->port = port;
|
|
if (rx_buf_size > 0) {
|
|
session->rx_buf.addr = (td_u8 *)MBX_MALLOC(rx_buf_size);
|
|
if (!session->rx_buf.addr) {
|
|
return NULL;
|
|
}
|
|
session->rx_buf.size = rx_buf_size;
|
|
} else {
|
|
session->rx_buf.addr = NULL;
|
|
session->rx_buf.size = 0;
|
|
}
|
|
session->rx_buf.rd_idx = 0;
|
|
session->rx_buf.wr_idx = 0;
|
|
if (tx_buf_size > 0) {
|
|
session->tx_buf.addr = (td_u8 *)MBX_MALLOC(tx_buf_size);
|
|
if (!session->tx_buf.addr) {
|
|
return NULL;
|
|
}
|
|
session->tx_buf.size = tx_buf_size;
|
|
} else {
|
|
session->tx_buf.addr = NULL;
|
|
session->tx_buf.size = 0;
|
|
}
|
|
session->tx_buf.rd_idx = 0;
|
|
session->tx_buf.wr_idx = 0;
|
|
|
|
return session;
|
|
}
|
|
|
|
td_s32 mbx_open(td_u32 session_id, td_u32 rx_buf_size, td_u32 tx_buf_size)
|
|
{
|
|
struct session *session = NULL;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
if (rx_buf_size == 0) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
|
|
if (SESSION_ID_SIDE0(session_id) != g_mailbox.local_cpu && \
|
|
SESSION_ID_SIDE1(session_id) != g_mailbox.local_cpu) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
if (SESSION_ID_SIDE0(session_id) >= CPU_MAX || \
|
|
SESSION_ID_SIDE1(session_id) >= CPU_MAX) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
mutex_lock(&g_mailbox.list_lock);
|
|
session = mbx_alloc_session(session_id, rx_buf_size, tx_buf_size);
|
|
if (session == NULL) {
|
|
mutex_unlock(&g_mailbox.list_lock);
|
|
return SOC_ERR_MAILBOX_NO_MEMORY;
|
|
}
|
|
init_mailbox_reg(session, session_id, &g_mailbox);
|
|
if ((session->tx_reg == NULL) || (session->rx_reg == NULL)) {
|
|
if (session->rx_buf.addr != NULL) {
|
|
MBX_FREE(session->rx_buf.addr);
|
|
session->rx_buf.addr = NULL;
|
|
}
|
|
if (session->tx_buf.addr != NULL) {
|
|
MBX_FREE(session->tx_buf.addr);
|
|
session->tx_buf.addr = NULL;
|
|
}
|
|
MBX_FREE(session);
|
|
mutex_unlock(&g_mailbox.list_lock);
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
MBX_LIST_ADD(&session->node, &g_mailbox.list_head);
|
|
mutex_unlock(&g_mailbox.list_lock);
|
|
|
|
return GEN_SESSION_HANDLE(session->num, session->port);
|
|
}
|
|
|
|
td_s32 mbx_close(td_u32 handle)
|
|
{
|
|
struct session *session = NULL;
|
|
|
|
if (g_mailbox.initalized != TD_TRUE) {
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
session = find_session(SESSION_HANDLE_NUM(handle), SESSION_HANDLE_PORT(handle));
|
|
if (session == NULL) {
|
|
return SOC_ERR_MAILBOX_INVALID_HANDLE;
|
|
}
|
|
if (session->tx_reg != NULL) {
|
|
MBX_FREE(session->tx_reg);
|
|
session->tx_reg = NULL;
|
|
}
|
|
if (session->rx_reg != NULL) {
|
|
MBX_FREE(session->rx_reg);
|
|
session->rx_reg = NULL;
|
|
}
|
|
if (session->rx_buf.addr != NULL) {
|
|
MBX_FREE(session->rx_buf.addr);
|
|
session->rx_buf.addr = NULL;
|
|
}
|
|
if (session->tx_buf.addr != NULL) {
|
|
MBX_FREE(session->tx_buf.addr);
|
|
session->tx_buf.addr = NULL;
|
|
}
|
|
mutex_lock(&g_mailbox.list_lock);
|
|
MBX_LIST_DEL(&session->node);
|
|
MBX_FREE(session);
|
|
session = NULL;
|
|
mutex_unlock(&g_mailbox.list_lock);
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
struct mailbox *get_mailbox_data(td_void)
|
|
{
|
|
return &g_mailbox;
|
|
}
|