-
Notifications
You must be signed in to change notification settings - Fork 2
/
ipc_host.c
198 lines (169 loc) · 6.78 KB
/
ipc_host.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**
******************************************************************************
*
* @file ipc_host.c
*
* @brief IPC module.
*
* Copyright (C) BouffaloLab 2017-2018
*
******************************************************************************
*/
/*
* INCLUDE FILES
******************************************************************************
*/
#include <linux/spinlock.h>
#include "bl_defs.h"
#include "ipc_host.h"
/*
* TYPES DEFINITION
******************************************************************************
*/
const int nx_txdesc_cnt[] =
{
NX_TXDESC_CNT0,
NX_TXDESC_CNT1,
NX_TXDESC_CNT2,
NX_TXDESC_CNT3,
#if NX_TXQ_CNT == 5
NX_TXDESC_CNT4,
#endif
};
const int nx_txdesc_cnt_msk[] =
{
NX_TXDESC_CNT0 - 1,
NX_TXDESC_CNT1 - 1,
NX_TXDESC_CNT2 - 1,
NX_TXDESC_CNT3 - 1,
#if NX_TXQ_CNT == 5
NX_TXDESC_CNT4 - 1,
#endif
};
const int nx_txuser_cnt[] =
{
CONFIG_USER_MAX,
CONFIG_USER_MAX,
CONFIG_USER_MAX,
CONFIG_USER_MAX,
#if NX_TXQ_CNT == 5
1,
#endif
};
/**
******************************************************************************
*/
void *ipc_host_tx_flush(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos)
{
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos];
void *host_id = env->tx_host_id[queue_idx][user_pos][used_idx & nx_txdesc_cnt_msk[queue_idx]];
// call the external function to indicate that a TX packet is freed
if (host_id != 0)
{
// Reset the host id in the array
env->tx_host_id[queue_idx][user_pos][used_idx & nx_txdesc_cnt_msk[queue_idx]] = 0;
// Increment the used index
env->txdesc_used_idx[queue_idx][user_pos]++;
}
return (host_id);
}
/**
******************************************************************************
*/
void ipc_host_tx_cfm_handler(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos, struct bl_hw_txhdr *hw_hdr, struct bl_txq **txq_saved)
{
void *host_id = NULL;
struct sk_buff *skb;
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos] & nx_txdesc_cnt_msk[queue_idx];
uint32_t free_idx = env->txdesc_free_idx[queue_idx][user_pos] & nx_txdesc_cnt_msk[queue_idx];
host_id = env->tx_host_id[queue_idx][user_pos][used_idx];
ASSERT_ERR(host_id != NULL);
env->tx_host_id[queue_idx][user_pos][used_idx] = 0;
skb=host_id;
BL_DBG("cfm skb=%p in %d of buffer, pkt_sn=%u\n", host_id, used_idx & nx_txdesc_cnt_msk[queue_idx], ((struct bl_txhdr *)(skb->data))->sw_hdr->hdr.reserved);
if (env->cb.send_data_cfm(env->pthis, host_id, hw_hdr, (void **)txq_saved) != 0) {
BL_DBG("send_data_cfm!=0, so break, used_idx=%d\n", used_idx);
env->tx_host_id[queue_idx][user_pos][used_idx] = host_id;
} else {
env->txdesc_used_idx[queue_idx][user_pos]++;
}
if ((env->txdesc_used_idx[queue_idx][user_pos]&nx_txdesc_cnt_msk[queue_idx]) == free_idx) {
BL_DBG("ipc_host_tx_cfm_handler: used_idx=free_idx=%d\n", free_idx);
env->rb_len[queue_idx] = nx_txdesc_cnt[queue_idx];
} else {
BL_DBG("ipc_host_tx_cfm_handler: used_idx=%d, free_idx=%d\n", env->txdesc_used_idx[queue_idx][user_pos]&nx_txdesc_cnt_msk[queue_idx], free_idx);
env->rb_len[queue_idx] = ((env->txdesc_used_idx[queue_idx][user_pos]&nx_txdesc_cnt_msk[queue_idx])-free_idx + nx_txdesc_cnt[queue_idx]) % nx_txdesc_cnt[queue_idx];
}
BL_DBG("ipc_host_tx_cfm_handler: env->rb_len[%d]=%d\n", queue_idx, env->rb_len[queue_idx]);
BL_DBG("used_idx=%d--->%d\n", env->txdesc_used_idx[queue_idx][user_pos]-1, env->txdesc_used_idx[queue_idx][user_pos]);
}
/**
******************************************************************************
*/
void ipc_host_init(struct ipc_host_env_tag *env,
struct ipc_host_cb_tag *cb,
void *pthis)
{
unsigned int i;
// Reset the IPC Host environment
memset(env, 0, sizeof(struct ipc_host_env_tag));
// Save the callbacks in our own environment
env->cb = *cb;
// Save the pointer to the register base
env->pthis = pthis;
// Initialize buffers numbers and buffers sizes needed for DMA Receptions
env->rx_bufnb = IPC_RXBUF_CNT;
env->rx_bufsz = IPC_RXBUF_SIZE;
#ifdef CONFIG_BL_FULLMAC
env->rxdesc_nb = IPC_RXDESC_CNT;
#endif //(CONFIG_BL_FULLMAC)
env->ipc_e2amsg_bufnb = IPC_MSGE2A_BUF_CNT;
env->ipc_e2amsg_bufsz = sizeof(struct ipc_e2a_msg);
env->ipc_dbg_bufnb = IPC_DBGBUF_CNT;
env->ipc_dbg_bufsz = sizeof(struct ipc_dbg_msg);
env->rb_len[0] = NX_TXDESC_CNT0;
env->rb_len[1] = NX_TXDESC_CNT1;
env->rb_len[2] = NX_TXDESC_CNT2;
env->rb_len[3] = NX_TXDESC_CNT3;
#if NX_TXQ_CNT == 5
env->rb_len[4] = NX_TXDESC_CNT4;
#endif
for (i = 0; i < CONFIG_USER_MAX; i++)
{
// Initialize the pointers to the hostid arrays
env->tx_host_id[0][i] = env->tx_host_id0[i];
env->tx_host_id[1][i] = env->tx_host_id1[i];
env->tx_host_id[2][i] = env->tx_host_id2[i];
env->tx_host_id[3][i] = env->tx_host_id3[i];
#if NX_TXQ_CNT == 5
env->tx_host_id[4][i] = NULL;
#endif
}
#if NX_TXQ_CNT == 5
env->tx_host_id[4][0] = env->tx_host_id4[0];
#endif
}
/**
******************************************************************************
*/
void ipc_host_txdesc_push(struct ipc_host_env_tag *env, const int queue_idx,
const int user_pos, void *host_id)
{
struct sk_buff *skb=host_id;
uint32_t free_idx = env->txdesc_free_idx[queue_idx][user_pos] & nx_txdesc_cnt_msk[queue_idx];
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos] & nx_txdesc_cnt_msk[queue_idx];
BL_DBG("save skb=%p in %d of buffer, pkt_sn=%u\n", host_id, free_idx, ((struct bl_txhdr *)(skb->data))->sw_hdr->hdr.reserved);
// Save the host id in the environment
env->tx_host_id[queue_idx][user_pos][free_idx] = host_id;
if((free_idx + 1) % nx_txdesc_cnt[queue_idx] == used_idx) {
BL_DBG("queue is full: free_idx=%d, used_idx=%d\n", free_idx, used_idx);
env->txdesc_free_idx[queue_idx][user_pos]++;
env->rb_len[queue_idx] = 0;
} else {
env->txdesc_free_idx[queue_idx][user_pos]++;
BL_DBG("ipc_host_txdesc_push: used_idx=%d, free_idx=%d\n", used_idx, env->txdesc_free_idx[queue_idx][user_pos]&nx_txdesc_cnt_msk[queue_idx]);
env->rb_len[queue_idx] = (used_idx-(env->txdesc_free_idx[queue_idx][user_pos]&nx_txdesc_cnt_msk[queue_idx]) + nx_txdesc_cnt[queue_idx]) % nx_txdesc_cnt[queue_idx];
}
BL_DBG("ipc_host_txdesc_push: env->rb_len[%d]=%d\n", queue_idx, env->rb_len[queue_idx]);
BL_DBG("queue_idx[%d], free_idx: %d--->%d\n", queue_idx, env->txdesc_free_idx[queue_idx][user_pos] - 1, env->txdesc_free_idx[queue_idx][user_pos]);
}