1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * 文 件 名 : hmac_uapsd.c
15 * 生成日期 : 2013年9月18日
16 * 功能描述 : UAPSD hmac层处理
17 */
18
19 /*****************************************************************************
20 1 头文件包含
21 *****************************************************************************/
22 #include "hmac_uapsd.h"
23 #include "wlan_spec.h"
24 #include "mac_vap_ext.h"
25 #include "mac_frame.h"
26 #include "hmac_mgmt_ap.h"
27 #include "hmac_encap_frame_ap.h"
28 #include "hmac_mgmt_bss_comm.h"
29 #include "hmac_rx_data.h"
30 #include "wlan_msg.h"
31 #include "oal_net.h"
32 #include "hal_common_ops.h"
33 #include "hal_ext_if.h"
34 #include "mac_device_ext.h"
35 #include "hmac_vap.h"
36 #include "hmac_main.h"
37 #include "hmac_user.h"
38 #include "hmac_psm_ap.h"
39 #include "hmac_tx_mgmt.h"
40 #include "hmac_feature_dft.h"
41 #include "hmac_tx_mpdu_adapt.h"
42 #include "hmac_tx_mpdu_queue.h"
43 #include "hmac_feature_interface.h"
44 #include "frw_util_notifier.h"
45
46 #ifdef __cplusplus
47 #if __cplusplus
48 extern "C" {
49 #endif
50 #endif
51
52 #undef THIS_FILE_ID
53 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_UAPSD_C
54
55 #undef THIS_MOD_ID
56 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
57
58 hmac_user_uapsd_info_stru *g_user_uapsd_info[WLAN_USER_MAX_USER_LIMIT];
59 osal_u8 g_max_queue_len[WLAN_VAP_MAX_NUM_PER_DEVICE_LIMIT] = {
60 HMAC_UAPSD_QDEPTH_DEFAULT, HMAC_UAPSD_QDEPTH_DEFAULT, HMAC_UAPSD_QDEPTH_DEFAULT, HMAC_UAPSD_QDEPTH_DEFAULT
61 };
62
63 /*****************************************************************************
64 3 函数实现
65 *****************************************************************************/
66 OSAL_STATIC osal_u32 hmac_uapsd_send_qosnull(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac);
67 OSAL_STATIC osal_void hmac_uapsd_process_trigger(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac,
68 const oal_netbuf_stru *net_buf);
69 OSAL_STATIC osal_s32 hmac_uapsd_process_queue(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac);
70 OSAL_STATIC osal_s32 hmac_uapsd_flush_queue(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user);
71 OSAL_STATIC osal_s32 hmac_config_set_uapsd_update(hmac_vap_stru *hmac_vap, osal_u8 *data);
72
hmac_get_uapsd_max_queue_len(osal_u8 vap_id)73 OSAL_STATIC osal_u8 hmac_get_uapsd_max_queue_len(osal_u8 vap_id)
74 {
75 if (hmac_vap_id_param_check(vap_id) != OSAL_TRUE) {
76 return HMAC_UAPSD_QDEPTH_DEFAULT;
77 }
78 return g_max_queue_len[vap_id];
79 }
80
hmac_ap_get_user_uapsd_info(osal_u16 assoc_id)81 OSAL_STATIC hmac_user_uapsd_info_stru *hmac_ap_get_user_uapsd_info(osal_u16 assoc_id)
82 {
83 if (hmac_user_assoc_id_param_check(assoc_id) != OSAL_TRUE) {
84 return OSAL_NULL;
85 }
86 return g_user_uapsd_info[assoc_id];
87 }
88
89 /*****************************************************************************
90 函 数 名 : hmac_psm_is_uapsd_empty
91 功能描述 : 判断某一个用户的uspsd队列是否都为空,如果非空就返回false
92 *****************************************************************************/
hmac_psm_is_uapsd_empty(hmac_user_stru * hmac_user)93 OSAL_STATIC oal_bool_enum_uint8 hmac_psm_is_uapsd_empty(hmac_user_stru *hmac_user)
94 {
95 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
96
97 if (hmac_user == OSAL_NULL) {
98 return OSAL_TRUE;
99 }
100
101 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
102 if (user_uapsd_info == OSAL_NULL) {
103 return OSAL_TRUE;
104 }
105
106 if (osal_adapt_atomic_read(&user_uapsd_info->uapsd_stru.mpdu_num) == 0) {
107 return OSAL_TRUE;
108 }
109
110 return OSAL_FALSE;
111 }
112
hmac_uapsd_fill_st_uapsd_status(mac_user_uapsd_status_stru * uapsd_status,const osal_u8 * wmm_ie,osal_u8 * uapsd_flag)113 OAL_STATIC osal_void hmac_uapsd_fill_st_uapsd_status(mac_user_uapsd_status_stru *uapsd_status,
114 const osal_u8 *wmm_ie, osal_u8 *uapsd_flag)
115 {
116 osal_u8 ret = OAL_FALSE;
117 osal_u8 max_sp;
118 uapsd_status->qos_info = wmm_ie[HMAC_UAPSD_WME_LEN];
119
120 /* 8为WMM IE长度 */
121 if ((wmm_ie[HMAC_UAPSD_WME_LEN] & BIT0) == BIT0) {
122 uapsd_status->ac_trigger_ena[WLAN_WME_AC_VO] = 1;
123 uapsd_status->ac_delievy_ena[WLAN_WME_AC_VO] = 1;
124 ret = OAL_TRUE;
125 }
126
127 if ((wmm_ie[HMAC_UAPSD_WME_LEN] & BIT1) == BIT1) {
128 uapsd_status->ac_trigger_ena[WLAN_WME_AC_VI] = 1;
129 uapsd_status->ac_delievy_ena[WLAN_WME_AC_VI] = 1;
130 ret = OAL_TRUE;
131 }
132
133 if ((wmm_ie[HMAC_UAPSD_WME_LEN] & BIT2) == BIT2) {
134 uapsd_status->ac_trigger_ena[WLAN_WME_AC_BK] = 1;
135 uapsd_status->ac_delievy_ena[WLAN_WME_AC_BK] = 1;
136 ret = OAL_TRUE;
137 }
138
139 if ((wmm_ie[HMAC_UAPSD_WME_LEN] & BIT3) == BIT3) {
140 uapsd_status->ac_trigger_ena[WLAN_WME_AC_BE] = 1;
141 uapsd_status->ac_delievy_ena[WLAN_WME_AC_BE] = 1;
142 ret = OAL_TRUE;
143 }
144
145 if (ret == OAL_TRUE) {
146 *uapsd_flag |= HMAC_USR_UAPSD_EN;
147 }
148
149 /* 设置max SP长度 */
150 max_sp = (wmm_ie[HMAC_UAPSD_WME_LEN] >> 5) & 0x3; /* 5偏移 */
151 switch (max_sp) {
152 case 1:
153 uapsd_status->max_sp_len = 2; /* 2设置max SP长度 */
154 break;
155 case 2: /* 2类型判断 */
156 uapsd_status->max_sp_len = 4; /* 4设置max SP长度 */
157 break;
158 case 3: /* 3类型判断 */
159 uapsd_status->max_sp_len = 6; /* 6设置max SP长度 */
160 break;
161 default:
162 uapsd_status->max_sp_len = HMAC_UAPSD_SEND_ALL;
163 break;
164 }
165 return;
166 }
167
168 /*****************************************************************************
169 函 数 名 : hmac_uapsd_update_user_para_etc
170 功能描述 : uapsd处理关联请求中的WMM IE
171 *****************************************************************************/
hmac_uapsd_update_user_para_etc(osal_u8 * payload,osal_u8 sub_type,osal_u32 msg_len,hmac_user_stru * hmac_user)172 OSAL_STATIC osal_u32 hmac_uapsd_update_user_para_etc(osal_u8 *payload, osal_u8 sub_type, osal_u32 msg_len,
173 hmac_user_stru *hmac_user)
174 {
175 osal_s32 ret;
176 osal_u8 uapsd_flag = 0;
177 mac_user_uapsd_status_stru uapsd_status;
178 hmac_vap_stru *hmac_vap = OAL_PTR_NULL;
179 osal_u16 len;
180 osal_u16 len_total;
181 osal_u8 *param = OAL_PTR_NULL;
182 osal_u8 *wmm_ie = OAL_PTR_NULL;
183
184 unref_param(sub_type);
185
186 wmm_ie = hmac_get_wmm_ie_etc(payload, (osal_u16)msg_len);
187 if (wmm_ie == OAL_PTR_NULL) {
188 oam_warning_log2(0, OAM_SF_PWR, "vap_id[%d] Could not find WMM IE in assoc req,user_id[%d]\n",
189 hmac_user->vap_id, hmac_user->assoc_id);
190 return OAL_ERR_CODE_PTR_NULL;
191 }
192
193 memset_s(&uapsd_status, OAL_SIZEOF(mac_user_uapsd_status_stru), 0, OAL_SIZEOF(mac_user_uapsd_status_stru));
194 hmac_uapsd_fill_st_uapsd_status(&uapsd_status, wmm_ie, &uapsd_flag);
195
196 /* Send uapsd_flag & uapsd_status syn to dmac */
197 hmac_vap = (hmac_vap_stru *)mac_res_get_hmac_vap(hmac_user->vap_id);
198 if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
199 oam_error_log1(0, OAM_SF_CFG, "{hmac_uapsd_update_user_para_etc::get mac_vap [%d] null.}",
200 hmac_user->vap_id);
201 return OAL_ERR_CODE_PTR_NULL;
202 }
203 len = OAL_SIZEOF(osal_u16);
204 len_total = OAL_SIZEOF(osal_u16) + OAL_SIZEOF(osal_u8) + OAL_SIZEOF(mac_user_uapsd_status_stru);
205 param = (osal_u8 *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, len_total, OAL_TRUE);
206 if (osal_unlikely(param == OAL_PTR_NULL)) {
207 oam_error_log1(0, OAM_SF_CFG,
208 "vap_id[%d] {hmac_uapsd_update_user_para_etc::param null.}", hmac_vap->vap_id);
209 return OAL_ERR_CODE_PTR_NULL;
210 }
211 // user_index
212 (osal_void)memcpy_s(param, len, &(hmac_user->assoc_id), len);
213 // uapsd_flag
214 (osal_void)memcpy_s(param + len, OAL_SIZEOF(osal_u8), &uapsd_flag, OAL_SIZEOF(osal_u8));
215 len += OAL_SIZEOF(osal_u8);
216 // uapsd_status
217 (osal_void)memcpy_s(param + len, OAL_SIZEOF(mac_user_uapsd_status_stru),
218 &uapsd_status, OAL_SIZEOF(mac_user_uapsd_status_stru));
219 len += OAL_SIZEOF(mac_user_uapsd_status_stru);
220
221 ret = hmac_config_set_uapsd_update(hmac_vap, param);
222 if (osal_unlikely(ret != OAL_SUCC)) {
223 oam_warning_log2(0, OAM_SF_CFG,
224 "vap_id[%d] {hmac_uapsd_update_user_para_etc::hmac_config_set_uapsd_update fail %u}",
225 hmac_vap->vap_id, ret);
226 }
227 oal_mem_free(param, OAL_TRUE);
228 return OAL_SUCC;
229 }
230
hmac_usr_uapsd_use_tim(const hmac_user_stru * hmac_usr)231 OSAL_STATIC osal_u8 hmac_usr_uapsd_use_tim(const hmac_user_stru *hmac_usr)
232 {
233 mac_user_uapsd_status_stru uapsd_status = hmac_ap_get_user_uapsd_info(hmac_usr->assoc_id)->uapsd_status;
234 osal_u8 uapsd_flag = hmac_ap_get_user_uapsd_info(hmac_usr->assoc_id)->uapsd_flag;
235
236 return (((uapsd_status.ac_delievy_ena[WLAN_WME_AC_BK] != 0) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0)) &&
237 ((uapsd_status.ac_delievy_ena[WLAN_WME_AC_BE] != 0) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0)) &&
238 ((uapsd_status.ac_delievy_ena[WLAN_WME_AC_VI] != 0) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0)) &&
239 ((uapsd_status.ac_delievy_ena[WLAN_WME_AC_VO] != 0) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0)));
240 }
241
hmac_uapsd_state_trans(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,const mac_ieee80211_qos_frame_stru * mac_header)242 OSAL_STATIC osal_u32 hmac_uapsd_state_trans(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
243 const mac_ieee80211_qos_frame_stru *mac_header)
244 {
245 hmac_user_uapsd_stru *uapsd_stru = OSAL_NULL;
246 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
247 osal_u8 uapsd_flag;
248 osal_s32 uapsd_qdepth;
249
250 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
251 if (user_uapsd_info == OSAL_NULL) {
252 return OSAL_FALSE;
253 }
254 uapsd_stru = &user_uapsd_info->uapsd_stru;
255 uapsd_flag = user_uapsd_info->uapsd_flag;
256 if ((((mac_header->frame_control.power_mgmt) == 1) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) == 0)) ||
257 (((mac_header->frame_control.power_mgmt) == 0) && ((uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0))) {
258 user_uapsd_info->uapsd_flag &= ~HMAC_USR_UAPSD_SP;
259 if (mac_header->frame_control.power_mgmt == 1) {
260 /* 从非节能态迁移到节能态 */
261 (osal_void)memset_s(&uapsd_stru->uapsd_trigseq[0], sizeof(uapsd_stru->uapsd_trigseq),
262 0xff, sizeof(uapsd_stru->uapsd_trigseq));
263 user_uapsd_info->uapsd_flag |= HMAC_USR_UAPSD_TRIG;
264 } else {
265 /* flush 节能队列 */
266 uapsd_qdepth = hmac_uapsd_flush_queue(hmac_vap, hmac_user);
267 if ((uapsd_qdepth == 0) && (hmac_usr_uapsd_use_tim(hmac_user) != 0)) {
268 /* 调用PSM的TIM设置接口 */
269 hmac_psm_set_local_bitmap(hmac_vap, hmac_user, 0);
270 }
271 /* 从节能态迁移到非节能态 */
272 user_uapsd_info->uapsd_flag &= ~HMAC_USR_UAPSD_TRIG;
273 }
274 return OSAL_TRUE;
275 }
276
277 return OSAL_FALSE;
278 }
279
280 /*****************************************************************************
281 函 数 名 : hmac_uapsd_trigger_check
282 功能描述 : 接收报文流程中检查是否trigger帧
283 *****************************************************************************/
hmac_uapsd_rx_trigger_check(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,const oal_netbuf_stru * net_buf)284 WIFI_TCM_TEXT OSAL_STATIC osal_void hmac_uapsd_rx_trigger_check(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
285 const oal_netbuf_stru *net_buf)
286 {
287 mac_ieee80211_qos_frame_stru *mac_header = OSAL_NULL;
288 mac_rx_ctl_stru *rx_ctrl = OSAL_NULL;
289 osal_u8 uapsd_flag;
290 osal_u32 istrigger = OSAL_FALSE;
291 osal_u8 tid;
292 osal_u8 ac = WLAN_WME_AC_BE;
293 osal_u32 run_time;
294 osal_u32 cur_tsf;
295 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
296
297 if (hmac_vap == OSAL_NULL || hmac_user == OSAL_NULL) {
298 return;
299 }
300
301 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
302 if (user_uapsd_info == OSAL_NULL) {
303 return;
304 }
305
306 uapsd_flag = user_uapsd_info->uapsd_flag;
307
308 /* 如果当前Usr不是uapsd使能的返回 */
309 if ((uapsd_flag & HMAC_USR_UAPSD_EN) == 0) {
310 return;
311 }
312
313 /* 如果当前Usr处于一个Service Period中,返回 */
314 cur_tsf = (osal_u32)osal_get_time_stamp_ms();
315 run_time = osal_get_runtime((user_uapsd_info->uapsd_status.last_esop_tsf), cur_tsf);
316 if (((uapsd_flag & HMAC_USR_UAPSD_SP) != 0) && run_time <= HMAC_UAPSD_IDLE_INT) {
317 return;
318 }
319 user_uapsd_info->uapsd_flag &= ~HMAC_USR_UAPSD_SP;
320
321 rx_ctrl = (mac_rx_ctl_stru *)oal_netbuf_cb_const(net_buf);
322 mac_header = (mac_ieee80211_qos_frame_stru *)(mac_get_rx_cb_mac_hdr(rx_ctrl));
323 if (hmac_uapsd_state_trans(hmac_vap, hmac_user, mac_header) == OSAL_TRUE) {
324 return;
325 }
326
327 /* 检查是否是一个trigger帧:QOS DATA or Qos NULL DATA,非trigger帧也要继续处理是否需要状态切换 */
328 if ((mac_header->frame_control.type == WLAN_DATA_BASICTYPE) &&
329 ((mac_header->frame_control.sub_type == WLAN_QOS_DATA) ||
330 (mac_header->frame_control.sub_type == WLAN_QOS_NULL_FRAME))) {
331 istrigger = OSAL_TRUE;
332 tid = mac_header->qc_tid;
333 ac = wlan_wme_tid_to_ac(tid);
334 }
335
336 /* AC是trigge_en的且用户当前处于trigger状态,can be trigger */
337 if ((istrigger == OSAL_TRUE) &&
338 ((user_uapsd_info->uapsd_status.ac_trigger_ena[ac] == OSAL_TRUE) &&
339 ((user_uapsd_info->uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0))) {
340 hmac_uapsd_process_trigger(hmac_vap, hmac_user, ac, net_buf);
341 }
342 return;
343 }
344
345 /*****************************************************************************
346 函 数 名 : hmac_uapsd_process_trigger
347 功能描述 : trigger帧的处理
348 *****************************************************************************/
hmac_uapsd_process_trigger(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,osal_u8 ac,const oal_netbuf_stru * net_buf)349 OSAL_STATIC osal_void hmac_uapsd_process_trigger(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac,
350 const oal_netbuf_stru *net_buf)
351 {
352 mac_ieee80211_qos_frame_stru *mac_header = OSAL_NULL;
353 mac_rx_ctl_stru *rx_ctrl = OSAL_NULL;
354 osal_s32 uapsd_qdepth;
355 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
356
357 rx_ctrl = (mac_rx_ctl_stru *)oal_netbuf_cb_const(net_buf);
358 mac_header = (mac_ieee80211_qos_frame_stru *)(mac_get_rx_cb_mac_hdr(rx_ctrl));
359
360 if (hmac_user->is_multi_user == OSAL_FALSE) {
361 hmac_tid_resume(&hmac_user->tx_tid_queue[ac], DMAC_TID_PAUSE_RESUME_TYPE_PS);
362 }
363 hal_tx_disable_peer_sta_ps_ctrl(hmac_user->lut_index);
364
365 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
366 if (user_uapsd_info == OSAL_NULL) {
367 return;
368 }
369
370 if ((mac_header->frame_control.retry == OSAL_TRUE) &&
371 (mac_header->seq_num == user_uapsd_info->uapsd_stru.uapsd_trigseq[ac])) {
372 return;
373 }
374 user_uapsd_info->uapsd_stru.uapsd_trigseq[ac] = mac_header->seq_num;
375
376 uapsd_qdepth = hmac_uapsd_process_queue(hmac_vap, hmac_user, ac);
377 /* 在设置DMAC_USR_UAPSD_SP前,需判断是否有发送报文,-1表示没有报文发送,不应该置上DMAC_USR_UAPSD_SP */
378 if (uapsd_qdepth == HMAC_UAPSD_NOT_SEND_FRAME) {
379 oam_error_log1(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_process_trigger::NOT_SEND_FRAME == uapsd_qdepth.}",
380 hmac_user->vap_id);
381 return;
382 }
383
384 user_uapsd_info->uapsd_flag |= HMAC_USR_UAPSD_SP;
385 if ((uapsd_qdepth == 0) && hmac_usr_uapsd_use_tim(hmac_user) == OSAL_TRUE) {
386 /* 调用PSM的TIM设置接口 */
387 oam_info_log2(0, OAM_SF_PWR, "vap_id[%d] hmac_uapsd_process_trigger:set PVB to 0,usr id = %d",
388 hmac_user->vap_id, hmac_user->assoc_id);
389
390 hmac_psm_set_local_bitmap(hmac_vap, hmac_user, 0);
391 }
392 }
393
hmac_uapsd_set_frame_hdr(mac_ieee80211_qos_frame_stru * mac_header,hmac_user_uapsd_stru * hmac_uapsd,const mac_tx_ctl_stru * tx_ctrl,osal_u8 sp_last,osal_u8 * extra_qosnull)394 OSAL_STATIC osal_void hmac_uapsd_set_frame_hdr(mac_ieee80211_qos_frame_stru *mac_header,
395 hmac_user_uapsd_stru *hmac_uapsd, const mac_tx_ctl_stru *tx_ctrl, osal_u8 sp_last, osal_u8 *extra_qosnull)
396 {
397 mac_ieee80211_frame_stru *frame_hdr = OSAL_NULL;
398 osal_u8 is_eosp;
399
400 /* 管理帧没有EOSP位,因此额外发送一个qos null结束USP */
401 if (mac_header->frame_control.type == WLAN_MANAGEMENT ||
402 mac_header->frame_control.type == WLAN_CONTROL) {
403 frame_hdr = mac_get_frame_header_addr(tx_ctrl);
404 frame_hdr->frame_control.more_data = 0;
405 *extra_qosnull = OSAL_TRUE;
406 } else if (mac_header->frame_control.type == WLAN_DATA_BASICTYPE) {
407 /*
408 每次发送时如果后面还有帧,则将EOSP置0,More Data置1。
409 如果到max sp length,后面还有缓存帧,则将EOSP置1,More Data置1。
410 如果后面没有帧发送,则将EOSP置1,More Data置0。
411 当delivery-enable的AC队列中没有缓存帧,发送一个QoSNull帧,More Data置0。
412 */
413 is_eosp = OSAL_TRUE;
414 if (sp_last == OSAL_FALSE) {
415 mac_header->frame_control.more_data = 1;
416 is_eosp = OSAL_FALSE;
417 } else if (osal_adapt_atomic_read(&hmac_uapsd->mpdu_num) == 1) {
418 mac_header->frame_control.more_data = 0;
419 } else {
420 mac_header->frame_control.more_data = 1;
421 }
422
423 if (mac_header->frame_control.sub_type == WLAN_QOS_DATA ||
424 mac_header->frame_control.sub_type == WLAN_QOS_NULL_FRAME) {
425 mac_header->qc_eosp = is_eosp;
426 } else {
427 *extra_qosnull = is_eosp;
428 }
429 oam_info_log4(0, OAM_SF_PWR, "{hmac_uapsd_set_frame_hdr:: more data %d, type %02x, subtype %02x, eosp %d.}",
430 mac_header->frame_control.more_data, mac_header->frame_control.type,
431 mac_header->frame_control.sub_type, is_eosp);
432 }
433 return;
434 }
435
436 /*****************************************************************************
437 函 数 名 : hmac_uapsd_tx_pkt
438 功能描述 : U-APSD节能队列发包
439 *****************************************************************************/
hmac_uapsd_tx_pkt(oal_netbuf_stru * net_buf,hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,osal_u8 ac,osal_u8 sp_last,osal_u8 * extra_qosnull)440 OSAL_STATIC osal_s32 hmac_uapsd_tx_pkt(oal_netbuf_stru *net_buf, hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
441 osal_u8 ac, osal_u8 sp_last, osal_u8 *extra_qosnull)
442 {
443 hmac_user_uapsd_stru *hmac_uapsd = OSAL_NULL;
444 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
445 mac_tx_ctl_stru *tx_ctrl = OSAL_NULL;
446 mac_ieee80211_qos_frame_stru *mac_header = OSAL_NULL;
447
448 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
449 if (user_uapsd_info == OSAL_NULL) {
450 return OAL_ERR_CODE_PTR_NULL;
451 }
452
453 hmac_uapsd = &user_uapsd_info->uapsd_stru;
454
455 tx_ctrl = (mac_tx_ctl_stru *)oal_netbuf_cb(net_buf);
456 tx_ctrl->is_get_from_ps_queue = OSAL_TRUE;
457
458 /* 非flush操作,tid设置为uapsd专用tid,ac设置为trigger的AC */
459 tx_ctrl->tid = WLAN_TIDNO_UAPSD;
460 tx_ctrl->ac = ac;
461
462 if (osal_unlikely(extra_qosnull == OSAL_NULL)) {
463 oam_error_log0(0, OAM_SF_TXOP, "{hmac_uapsd_tx_pkt::param is null}.");
464 return OAL_FAIL;
465 }
466
467 mac_header = (mac_ieee80211_qos_frame_stru *)mac_get_frame_header_addr(tx_ctrl);
468 hmac_uapsd_set_frame_hdr(mac_header, hmac_uapsd, tx_ctrl, sp_last, extra_qosnull);
469 osal_adapt_atomic_dec(&hmac_uapsd->mpdu_num);
470
471 if (mac_header->frame_control.type == WLAN_DATA_BASICTYPE) {
472 if (mac_header->qc_eosp == 1) {
473 tx_ctrl->need_rsp = OSAL_TRUE;
474 user_uapsd_info->uapsd_status.last_esop_tsf = (osal_u32)osal_get_time_stamp_ms();
475 }
476
477 /* 发送不成功,则终止本次USP */
478 if (hmac_tx_process_data(hmac_vap->hal_device, hmac_vap, net_buf) != OAL_SUCC) {
479 oam_error_log1(0, OAM_SF_PWR,
480 "vap_id[%d] {hmac_uapsd_tx_pkt::hmac_tx_process_data failed.}", hmac_user->vap_id);
481 *extra_qosnull = OSAL_TRUE;
482 hmac_tx_excp_free_netbuf(net_buf);
483 return OAL_FAIL;
484 }
485 } else {
486 /* 发送不成功,则终止本次USP */
487 if (hmac_tx_mgmt(hmac_vap, net_buf, tx_ctrl->mpdu_payload_len + tx_ctrl->frame_header_length, OSAL_TRUE) !=
488 OAL_SUCC) {
489 oal_netbuf_free(net_buf);
490 oam_error_log1(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_tx_pkt::hmac_tx_mgmt failed.}", hmac_user->vap_id);
491 *extra_qosnull = OSAL_TRUE;
492 return OAL_FAIL;
493 }
494 }
495 return OAL_SUCC;
496 }
497
498 /*****************************************************************************
499 函 数 名 : hmac_uapsd_process_queue
500 功能描述 : U-APSD节能队列发包
501 *****************************************************************************/
hmac_uapsd_process_queue(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,osal_u8 ac)502 OSAL_STATIC osal_s32 hmac_uapsd_process_queue(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac)
503 {
504 osal_u8 send_num, loop, extra_qosnull, sp_last;
505 hmac_user_uapsd_stru *hmac_uapsd = OSAL_NULL;
506 mac_user_uapsd_status_stru *mac_uapsd_status = OSAL_NULL;
507 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
508 oal_netbuf_stru *net_buf = OSAL_NULL;
509
510 extra_qosnull = sp_last = OSAL_FALSE;
511
512 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
513 if (user_uapsd_info == OSAL_NULL) {
514 return OAL_ERR_CODE_PTR_NULL;
515 }
516
517 hmac_uapsd = &user_uapsd_info->uapsd_stru;
518
519 if (osal_adapt_atomic_read(&hmac_uapsd->mpdu_num) == 0) {
520 return (hmac_uapsd_send_qosnull(hmac_vap, hmac_user, ac) != OAL_SUCC) ? HMAC_UAPSD_NOT_SEND_FRAME : 0;
521 }
522
523 mac_uapsd_status = &user_uapsd_info->uapsd_status;
524
525 send_num = (mac_uapsd_status->max_sp_len < (osal_u8)osal_adapt_atomic_read(&hmac_uapsd->mpdu_num)) ?
526 mac_uapsd_status->max_sp_len : (osal_u8)osal_adapt_atomic_read(&hmac_uapsd->mpdu_num);
527 for (loop = 0; loop < send_num; loop++) {
528 osal_spin_lock(&hmac_uapsd->lock_uapsd);
529 net_buf = hmac_tx_dequeue_first_mpdu(&(hmac_uapsd->uapsd_queue_head));
530 if (net_buf == OSAL_NULL) {
531 osal_spin_unlock(&hmac_uapsd->lock_uapsd);
532
533 oam_error_log2(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_process_queue::net_buf,mpdu_num=%d.}",
534 hmac_user->vap_id, osal_adapt_atomic_read(&hmac_uapsd->mpdu_num));
535 return osal_adapt_atomic_read(&hmac_uapsd->mpdu_num);
536 }
537
538 osal_spin_unlock(&hmac_uapsd->lock_uapsd);
539
540 if (loop == send_num - 1) {
541 sp_last = OSAL_TRUE;
542 }
543
544 if (hmac_uapsd_tx_pkt(net_buf, hmac_vap, hmac_user, ac, sp_last, &extra_qosnull) != OAL_SUCC) {
545 oam_error_log2(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_process_queue::failed:assoc_id = %d.}",
546 hmac_user->vap_id, hmac_user->assoc_id);
547 break;
548 }
549 }
550
551 if (extra_qosnull == OSAL_TRUE) {
552 hmac_uapsd_send_qosnull(hmac_vap, hmac_user, ac);
553 }
554
555 return osal_adapt_atomic_read(&hmac_uapsd->mpdu_num);
556 }
557
hmac_uapsd_flush_queue_tx_frame(hmac_vap_stru * hmac_vap,oal_netbuf_stru * net_buf,mac_tx_ctl_stru * tx_ctrl)558 OSAL_STATIC osal_void hmac_uapsd_flush_queue_tx_frame(hmac_vap_stru *hmac_vap,
559 oal_netbuf_stru *net_buf, mac_tx_ctl_stru *tx_ctrl)
560 {
561 mac_ieee80211_frame_stru *frame_hdr = mac_get_frame_header_addr(tx_ctrl);
562
563 if (frame_hdr->frame_control.type == WLAN_DATA_BASICTYPE) {
564 /* 发送不成功,则终止本次USP */
565 if (hmac_tx_process_data(hmac_vap->hal_device, hmac_vap, net_buf) != OAL_SUCC) {
566 oam_error_log1(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_flush_queue::tx_process_data failed.}",
567 hmac_vap->vap_id);
568 hmac_tx_excp_free_netbuf(net_buf);
569 }
570 } else {
571 /* 发送不成功,则终止本次USP */
572 if (hmac_tx_mgmt(hmac_vap, net_buf, tx_ctrl->mpdu_payload_len + tx_ctrl->frame_header_length, OSAL_TRUE) !=
573 OAL_SUCC) {
574 oam_error_log1(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_flush_queue::hmac_tx_mgmt failed.}",
575 hmac_vap->vap_id);
576 hmac_tx_excp_free_netbuf(net_buf);
577 }
578 }
579 }
580
581 /*****************************************************************************
582 函 数 名 : hmac_uapsd_flush_queue
583 功能描述 : U-APSD节能队列flush
584 *****************************************************************************/
hmac_uapsd_flush_queue(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user)585 OSAL_STATIC osal_s32 hmac_uapsd_flush_queue(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user)
586 {
587 oal_netbuf_stru *net_buf = OSAL_NULL;
588 mac_tx_ctl_stru *tx_ctrl = OSAL_NULL;
589 mac_ieee80211_frame_stru *frame_hdr = OSAL_NULL;
590 hmac_user_uapsd_stru *hmac_uapsd = OSAL_NULL;
591 hmac_user_uapsd_info_stru *user_uapsd_info;
592
593 if (osal_unlikely(hmac_vap == OSAL_NULL || hmac_user == OSAL_NULL)) {
594 oam_error_log0(0, OAM_SF_TXOP, "{hmac_uapsd_flush_queue::param is null}.");
595 return OAL_ERR_CODE_PTR_NULL;
596 }
597
598 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
599 if (user_uapsd_info == OSAL_NULL) {
600 return OAL_ERR_CODE_PTR_NULL;
601 }
602
603 hmac_uapsd = &user_uapsd_info->uapsd_stru;
604
605 while (osal_adapt_atomic_read(&hmac_uapsd->mpdu_num) != 0) {
606 osal_spin_lock(&hmac_uapsd->lock_uapsd);
607 net_buf = hmac_tx_dequeue_first_mpdu(&(hmac_uapsd->uapsd_queue_head));
608 if (net_buf == OSAL_NULL) {
609 osal_spin_unlock(&hmac_uapsd->lock_uapsd);
610
611 oam_error_log2(0, OAM_SF_PWR, "vap_id[%d] {hmac_uapsd_flush_queue::net_buf null, mpdu_num=%d.}",
612 hmac_user->vap_id, osal_adapt_atomic_read(&hmac_uapsd->mpdu_num));
613 return osal_adapt_atomic_read(&hmac_uapsd->mpdu_num);
614 }
615
616 osal_spin_unlock(&hmac_uapsd->lock_uapsd);
617
618 tx_ctrl = (mac_tx_ctl_stru *)oal_netbuf_cb(net_buf);
619 tx_ctrl->is_get_from_ps_queue = OSAL_TRUE;
620
621 /* flush流程,视为正常流程的继续,清掉more data bit */
622 if (osal_adapt_atomic_read(&hmac_uapsd->mpdu_num) == 1) {
623 frame_hdr = mac_get_frame_header_addr(tx_ctrl);
624 frame_hdr->frame_control.more_data = 0;
625 }
626
627 osal_adapt_atomic_dec(&hmac_uapsd->mpdu_num);
628
629 hmac_uapsd_flush_queue_tx_frame(hmac_vap, net_buf, tx_ctrl);
630 }
631
632 return osal_adapt_atomic_read(&hmac_uapsd->mpdu_num);
633 }
634
hmac_uapsd_fill_qosnull_txctl(mac_tx_ctl_stru * tx_ctrl,osal_u8 ac,osal_u8 vap_id,osal_u8 assoc_id)635 OSAL_STATIC osal_void hmac_uapsd_fill_qosnull_txctl(mac_tx_ctl_stru *tx_ctrl, osal_u8 ac, osal_u8 vap_id,
636 osal_u8 assoc_id)
637 {
638 /* 填写tx部分 */
639 tx_ctrl->ack_policy = WLAN_TX_NORMAL_ACK;
640 tx_ctrl->ac = ac;
641 tx_ctrl->retried_num = 0;
642 tx_ctrl->tid = WLAN_TIDNO_UAPSD;
643 tx_ctrl->tx_vap_index = vap_id;
644 /* 填写tx rx公共部分 */
645 tx_ctrl->is_get_from_ps_queue = OSAL_TRUE;
646 tx_ctrl->frame_header_length = sizeof(mac_ieee80211_qos_frame_stru);
647 tx_ctrl->mpdu_num = 1;
648 tx_ctrl->msdu_num = 1;
649 tx_ctrl->netbuf_num = 1;
650 tx_ctrl->mpdu_payload_len = 0;
651 tx_ctrl->tx_user_idx = assoc_id;
652 tx_ctrl->need_rsp = OSAL_TRUE;
653 }
654
655 /*****************************************************************************
656 函 数 名 : hmac_uapsd_tx_complete
657 功能描述 : U-APSD 发送完成检查
658 *****************************************************************************/
hmac_uapsd_tx_complete(hmac_user_stru * hmac_user)659 OSAL_STATIC osal_void hmac_uapsd_tx_complete(hmac_user_stru *hmac_user)
660 {
661 if (hmac_ap_get_user_uapsd_info(hmac_user->assoc_id) == OSAL_NULL) {
662 return;
663 }
664 hmac_ap_get_user_uapsd_info(hmac_user->assoc_id)->uapsd_flag &= ~HMAC_USR_UAPSD_SP;
665 }
666
667 /*****************************************************************************
668 函 数 名 : hmac_uapsd_send_qosnull
669 功能描述 : U-APSD qos null data发送
670 *****************************************************************************/
hmac_uapsd_send_qosnull(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,osal_u8 ac)671 OSAL_STATIC osal_u32 hmac_uapsd_send_qosnull(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, osal_u8 ac)
672 {
673 oal_netbuf_stru *net_buf = OSAL_NULL;
674 mac_tx_ctl_stru *tx_ctrl = OSAL_NULL;
675 osal_u32 ret;
676 mac_ieee80211_qos_frame_stru *mac_header = OSAL_NULL;
677
678 /* 申请net_buff */
679 net_buf = oal_netbuf_alloc_ext(WLAN_SHORT_NETBUF_SIZE);
680 if (net_buf == OSAL_NULL) {
681 oam_error_log1(0, 0, "vap_id[%d] {hmac_uapsd_send_qosnull::pnet_buf failed.}", hmac_vap->vap_id);
682 return OAL_ERR_CODE_ALLOC_MEM_FAIL;
683 }
684 oal_netbuf_reserve(net_buf, (OAL_MAX_MAC_HDR_LEN - sizeof(mac_ieee80211_qos_frame_stru)));
685 oal_set_netbuf_prev(net_buf, OSAL_NULL);
686 oal_set_netbuf_next(net_buf, OSAL_NULL);
687
688 /* 填写帧头,其中from ds为1,to ds为0,因此frame control的第二个字节为02 */
689 (osal_void)memset_s(oal_netbuf_header(net_buf), sizeof(mac_ieee80211_qos_frame_stru),
690 0, sizeof(mac_ieee80211_qos_frame_stru));
691 mac_null_data_encap(oal_netbuf_header(net_buf),
692 (osal_u16)(WLAN_PROTOCOL_VERSION | WLAN_FC0_TYPE_DATA | WLAN_FC0_SUBTYPE_QOS_NULL) | 0x0200,
693 hmac_user->user_mac_addr, hmac_vap->bssid);
694
695 mac_header = (mac_ieee80211_qos_frame_stru *)oal_netbuf_header(net_buf);
696 mac_header->qc_tid = wlan_wme_ac_to_tid(ac);
697 mac_header->qc_eosp = 1;
698 /* 协议规定单播的QOS NULL DATA只允许normal ack */
699 mac_header->qc_ack_polocy = WLAN_TX_NORMAL_ACK;
700
701 /* 填写cb字段 */
702 tx_ctrl = (mac_tx_ctl_stru *)oal_netbuf_cb(net_buf);
703 hmac_uapsd_fill_qosnull_txctl(tx_ctrl, ac, hmac_vap->vap_id, (osal_u8)hmac_user->assoc_id);
704 oal_netbuf_put(net_buf, tx_ctrl->frame_header_length);
705
706 ret = hmac_tx_process_data(hmac_vap->hal_device, hmac_vap, net_buf);
707 if (ret != OAL_SUCC) {
708 oam_error_log2(0, OAM_SF_PWR,
709 "vap_id[%d] {hmac_uapsd_send_qosnull::tx_process_data failed[%d].}", hmac_vap->vap_id, ret);
710 hmac_tx_excp_free_netbuf(net_buf);
711 hmac_uapsd_tx_complete(hmac_user);
712 }
713 hmac_ap_get_user_uapsd_info(hmac_user->assoc_id)->uapsd_status.last_esop_tsf = (osal_u32)osal_get_time_stamp_ms();
714 return ret;
715 }
716
717 /*****************************************************************************
718 函 数 名 : hmac_usr_uapsd_ac_tigger
719 功能描述 : BE/BK/VI/VO具有delivery属性,其余ac无需判断
720 *****************************************************************************/
hmac_usr_uapsd_ac_tigger(wlan_wme_ac_type_enum_uint8 ac,const hmac_user_stru * hmac_usr)721 OSAL_STATIC osal_u8 hmac_usr_uapsd_ac_tigger(wlan_wme_ac_type_enum_uint8 ac, const hmac_user_stru *hmac_usr)
722 {
723 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
724
725 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_usr->assoc_id);
726 if (user_uapsd_info == OSAL_NULL) {
727 return OSAL_FALSE;
728 }
729
730 return ((ac < WLAN_WME_AC_BUTT) ?
731 (((user_uapsd_info->uapsd_status.ac_delievy_ena[ac] != 0) &&
732 ((user_uapsd_info->uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0))) :
733 ((user_uapsd_info->uapsd_flag & HMAC_USR_UAPSD_TRIG) != 0));
734 }
735
736 /*****************************************************************************
737 函 数 名 : hmac_uapsd_tx_need_enqueue
738 功能描述 : 发送时报文是否入UAPSD队列
739 *****************************************************************************/
hmac_uapsd_tx_need_enqueue(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const mac_tx_ctl_stru * tx_ctl)740 WIFI_TCM_TEXT OSAL_STATIC osal_u8 hmac_uapsd_tx_need_enqueue(const hmac_vap_stru *hmac_vap,
741 const hmac_user_stru *hmac_user, const mac_tx_ctl_stru *tx_ctl)
742 {
743 wlan_wme_ac_type_enum_uint8 ac;
744
745 /* 漫游状态时,强制发送该数据帧 */
746 #ifdef _PRE_WLAN_FEATURE_ROAM
747 if (hmac_vap->vap_state == MAC_VAP_STATE_ROAMING) {
748 return OSAL_FALSE;
749 }
750 #endif
751
752 ac = tx_ctl->ac;
753 if ((hmac_vap->cap_flag.uapsd == WLAN_FEATURE_UAPSD_IS_OPEN) && (tx_ctl->ismcast == OSAL_FALSE) &&
754 (tx_ctl->is_get_from_ps_queue == OSAL_FALSE) && (hmac_usr_uapsd_ac_tigger(ac, hmac_user) == OSAL_TRUE)) {
755 return OSAL_TRUE;
756 }
757
758 return OSAL_FALSE;
759 }
760
761 /*****************************************************************************
762 函 数 名 : hmac_uapsd_tx_enqueue
763 功能描述 : 发送时报文入UAPSD队列
764 *****************************************************************************/
hmac_uapsd_tx_enqueue(const hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * net_buf)765 OSAL_STATIC osal_u32 hmac_uapsd_tx_enqueue(const hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
766 oal_netbuf_stru *net_buf)
767 {
768 oal_netbuf_stru *first_net_buf = OSAL_NULL;
769 oal_netbuf_stru *netbuf = OSAL_NULL;
770 mac_tx_ctl_stru *tx_ctrl = OSAL_NULL;
771 mac_ieee80211_frame_stru *frame_hdr = OSAL_NULL;
772 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
773 hmac_user_uapsd_stru *uapsd_stru = OSAL_NULL;
774
775 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
776 if (user_uapsd_info == OSAL_NULL) {
777 return OAL_ERR_CODE_PTR_NULL;
778 }
779 uapsd_stru = &(user_uapsd_info->uapsd_stru);
780 /* 判断是否需要更新bitmap */
781 if ((osal_adapt_atomic_read(&uapsd_stru->mpdu_num) == 0) && hmac_usr_uapsd_use_tim(hmac_user) == OSAL_TRUE) {
782 hmac_psm_set_local_bitmap(hmac_vap, hmac_user, 1);
783 }
784
785 /* 对UAPSD节能队列进行操作,加锁保护 */
786 osal_spin_lock(&uapsd_stru->lock_uapsd);
787
788 first_net_buf = net_buf;
789 while ((osal_adapt_atomic_read(&uapsd_stru->mpdu_num) < hmac_get_uapsd_max_queue_len(hmac_vap->vap_id)) &&
790 (first_net_buf != OSAL_NULL)) {
791 /* 从每一个mpdu中第一个net_buf的CB字段获取该mpdu一共包含几个net_buff */
792 tx_ctrl = (mac_tx_ctl_stru *)oal_netbuf_cb(first_net_buf);
793
794 /* 入队时设置more data bit,减少出队时的操作 */
795 frame_hdr = mac_get_frame_header_addr(tx_ctrl);
796 frame_hdr->frame_control.more_data = 0x01;
797
798 /* 将该mpdu的每一个net_buff加入到节能队列中 */
799 netbuf = first_net_buf;
800 while (
801 (netbuf != OSAL_NULL)) {
802 first_net_buf = oal_get_netbuf_next(netbuf);
803
804 oal_netbuf_add_to_list_tail(netbuf, &uapsd_stru->uapsd_queue_head);
805
806 netbuf = first_net_buf;
807 }
808
809 /* 更新节能队列中mpdu的个数 */
810 osal_adapt_atomic_inc(&uapsd_stru->mpdu_num);
811 }
812
813 osal_spin_unlock(&uapsd_stru->lock_uapsd);
814
815 /*
816 判断是mpdu全都入队了还是队列满了,如果是因为队列满了并且还有mpdu没有入队,
817 则将剩下的mpdu释放
818 */
819 if ((osal_adapt_atomic_read(&uapsd_stru->mpdu_num) == hmac_get_uapsd_max_queue_len(hmac_vap->vap_id)) &&
820 (first_net_buf != OSAL_NULL)) {
821 hmac_tx_excp_free_netbuf(first_net_buf);
822 oam_warning_log1(0, 0, "vap_id[%d] {hmac_uapsd_tx_enqueue::some mpdus are released due to queue full.}",
823 hmac_user->vap_id);
824 }
825
826 return OAL_SUCC;
827 }
828
hmac_uapsd_enqueue_proc(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,mac_tx_ctl_stru * tx_ctl,oal_netbuf_stru * netbuf)829 WIFI_TCM_TEXT OSAL_STATIC osal_u32 hmac_uapsd_enqueue_proc(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
830 mac_tx_ctl_stru *tx_ctl, oal_netbuf_stru *netbuf)
831 {
832 if (osal_unlikely(hmac_vap == OSAL_NULL || hmac_user == OSAL_NULL)) {
833 oam_error_log0(0, OAM_SF_TXOP, "{hmac_uapsd_enqueue_proc::param is null}.");
834 return OAL_ERR_CODE_PTR_NULL;
835 }
836
837 if (hmac_uapsd_tx_need_enqueue(hmac_vap, hmac_user, tx_ctl) == OSAL_FALSE) {
838 return OAL_CONTINUE;
839 }
840
841 return hmac_uapsd_tx_enqueue(hmac_vap, hmac_user, netbuf);
842 }
843
hmac_config_tx_comp_ps_handle(hmac_vap_stru * hmac_vap,frw_msg * msg)844 OSAL_STATIC osal_s32 hmac_config_tx_comp_ps_handle(hmac_vap_stru *hmac_vap, frw_msg *msg)
845 {
846 hmac_user_stru *hmac_user = OSAL_NULL;
847 osal_u16 aid;
848
849 dmac_crx_ps_tx_status_stru *status_msg = (dmac_crx_ps_tx_status_stru *)msg->data;
850 if (hmac_vap == OSAL_NULL || hmac_vap->init_flag == MAC_VAP_INVAILD || !is_ap(hmac_vap)) {
851 oam_warning_log0(0, OAM_SF_ANY, "{hmac_config_tx_comp_ps_handle:: input param invalid!!!}");
852 return OAL_ERR_CODE_PTR_NULL;
853 }
854
855 aid = status_msg->user_idx;
856 hmac_user = mac_res_get_hmac_user_etc(aid);
857 if (hmac_user == OSAL_NULL) {
858 oam_warning_log1(0, OAM_SF_ANY, "{hmac_config_tx_comp_ps_handle:: user[%d] is null!!!}", aid);
859 return OAL_ERR_CODE_PTR_NULL;
860 }
861
862 hmac_uapsd_tx_complete(hmac_user);
863
864 return OAL_SUCC;
865 }
866
867 /*****************************************************************************
868 函 数 名 : hmac_config_set_uapsd_update
869 功能描述 : VAP U-APSD UPDATE
870 *****************************************************************************/
hmac_config_set_uapsd_update(hmac_vap_stru * hmac_vap,osal_u8 * data)871 OSAL_STATIC osal_s32 hmac_config_set_uapsd_update(hmac_vap_stru *hmac_vap, osal_u8 *data)
872 {
873 osal_u16 user_id;
874 osal_u8 uapsd_flag;
875 mac_user_uapsd_status_stru *uapsd_status = OSAL_NULL;
876 hmac_user_stru *hmac_user = OSAL_NULL;
877 osal_u8 len_tmp;
878 hmac_user_uapsd_info_stru *user_uapsd_info = OSAL_NULL;
879
880 user_id = *(osal_u16 *)data;
881 len_tmp = sizeof(user_id);
882 uapsd_flag = *(data + len_tmp);
883 len_tmp += sizeof(uapsd_flag);
884 uapsd_status = (mac_user_uapsd_status_stru *)(data + len_tmp);
885
886 hmac_user = (hmac_user_stru *)mac_res_get_hmac_user_etc(user_id);
887 if (osal_unlikely(hmac_user == OSAL_NULL)) {
888 oam_warning_log2(0, OAM_SF_CFG,
889 "vap_id[%d] {hmac_config_set_uapsd_update::hmac_user[%d] null.}", hmac_vap->vap_id, user_id);
890 return OAL_ERR_CODE_PTR_NULL;
891 }
892
893 user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
894 if (user_uapsd_info == OSAL_NULL) {
895 return OAL_ERR_CODE_PTR_NULL;
896 }
897
898 (osal_void)memcpy_s(&user_uapsd_info->uapsd_flag, sizeof(osal_u8), &uapsd_flag, sizeof(osal_u8));
899 (osal_void)memcpy_s(&user_uapsd_info->uapsd_status, sizeof(mac_user_uapsd_status_stru),
900 uapsd_status, sizeof(mac_user_uapsd_status_stru));
901 return OAL_SUCC;
902 }
903
904 /*****************************************************************************
905 函 数 名 : hmac_uapsd_usr_init
906 功能描述 : USR初始化时u-apsd的初始化
907 *****************************************************************************/
hmac_uapsd_user_init(hmac_user_stru * hmac_user)908 OSAL_STATIC osal_bool hmac_uapsd_user_init(hmac_user_stru *hmac_user)
909 {
910 hmac_user_uapsd_info_stru *user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
911 hmac_user_uapsd_stru *uapsd_stru = &(user_uapsd_info->uapsd_stru);
912
913 osal_spin_lock_init(&(uapsd_stru->lock_uapsd));
914 oal_netbuf_list_head_init(&(uapsd_stru->uapsd_queue_head));
915 osal_adapt_atomic_set(&uapsd_stru->mpdu_num, 0);
916 uapsd_stru->uapsd_trigseq[WLAN_WME_AC_BK] = HMAC_UAPSD_INVALID_TRIGGER_SEQ;
917 uapsd_stru->uapsd_trigseq[WLAN_WME_AC_BE] = HMAC_UAPSD_INVALID_TRIGGER_SEQ;
918 uapsd_stru->uapsd_trigseq[WLAN_WME_AC_VI] = HMAC_UAPSD_INVALID_TRIGGER_SEQ;
919 uapsd_stru->uapsd_trigseq[WLAN_WME_AC_VO] = HMAC_UAPSD_INVALID_TRIGGER_SEQ;
920
921 return OAL_SUCC;
922 }
923
hmac_uapsd_ap_user_add(osal_void * notify_data)924 OSAL_STATIC osal_bool hmac_uapsd_ap_user_add(osal_void *notify_data)
925 {
926 hmac_user_stru *hmac_user = (hmac_user_stru *)notify_data;
927 hmac_vap_stru *hmac_vap = OSAL_NULL;
928 osal_void *mem_ptr = OSAL_NULL;
929 osal_u16 assoc_id;
930
931 if (hmac_user == OSAL_NULL) {
932 return OSAL_FALSE;
933 }
934
935 assoc_id = hmac_user->assoc_id;
936 if (assoc_id >= WLAN_USER_MAX_USER_LIMIT) {
937 return OSAL_FALSE;
938 }
939
940 hmac_vap = mac_res_get_hmac_vap(hmac_user->vap_id);
941 if (hmac_vap == OSAL_NULL) {
942 return OSAL_FALSE;
943 }
944
945 if (hmac_vap->vap_mode != WLAN_VAP_MODE_BSS_AP) {
946 return OSAL_TRUE;
947 }
948
949 if (g_user_uapsd_info[assoc_id] != OSAL_NULL) {
950 oam_warning_log1(0, OAM_SF_CSA, "vap_id[%d] hmac_uapsd_ap_user_add mem already malloc!", assoc_id);
951 return OSAL_TRUE;
952 }
953
954 mem_ptr = oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(hmac_user_uapsd_info_stru), OAL_TRUE);
955 if (mem_ptr == OSAL_NULL) {
956 oam_error_log1(0, OAM_SF_CSA, "vap_id[%d] hmac_uapsd_ap_user_add malloc null!", assoc_id);
957 return OSAL_FALSE;
958 }
959
960 (osal_void)memset_s(mem_ptr, sizeof(hmac_user_uapsd_info_stru), 0, sizeof(hmac_user_uapsd_info_stru));
961 g_user_uapsd_info[assoc_id] = (hmac_user_uapsd_info_stru *)mem_ptr;
962
963 hmac_uapsd_user_init(hmac_user);
964
965 return OSAL_TRUE;
966 }
967
968 /*****************************************************************************
969 函 数 名 : hmac_uapsd_usr_destroy
970 功能描述 : USR删除时u-apsd资源的销毁
971 *****************************************************************************/
hmac_uapsd_user_destroy(hmac_user_stru * hmac_user)972 OSAL_STATIC osal_void hmac_uapsd_user_destroy(hmac_user_stru *hmac_user)
973 {
974 hmac_user_uapsd_info_stru *user_uapsd_info = hmac_ap_get_user_uapsd_info(hmac_user->assoc_id);
975 hmac_user_uapsd_stru *uapsd_stru = &(user_uapsd_info->uapsd_stru);
976 oal_netbuf_stru *net_buf = OSAL_NULL;
977
978 /* 释放节能队列中的mpdu */
979 osal_spin_lock(&uapsd_stru->lock_uapsd);
980 while (osal_adapt_atomic_read(&uapsd_stru->mpdu_num) != 0) {
981 net_buf = hmac_tx_dequeue_first_mpdu(&uapsd_stru->uapsd_queue_head);
982 if (net_buf == OSAL_NULL) {
983 break;
984 }
985 osal_adapt_atomic_dec(&uapsd_stru->mpdu_num);
986 hmac_tx_excp_free_netbuf(net_buf);
987 }
988 osal_spin_unlock(&uapsd_stru->lock_uapsd);
989 osal_spin_lock_destroy(&(uapsd_stru->lock_uapsd));
990 osal_adapt_atomic_set(&uapsd_stru->mpdu_num, 0);
991 return;
992 }
993
hmac_uapsd_ap_user_del(osal_void * notify_data)994 OSAL_STATIC osal_bool hmac_uapsd_ap_user_del(osal_void *notify_data)
995 {
996 hmac_user_stru *hmac_user = (hmac_user_stru *)notify_data;
997 osal_u16 assoc_id;
998
999 if (hmac_user == OSAL_NULL) {
1000 return OSAL_FALSE;
1001 }
1002
1003 assoc_id = hmac_user->assoc_id;
1004 if (assoc_id >= WLAN_USER_MAX_USER_LIMIT) {
1005 return OSAL_FALSE;
1006 }
1007
1008 if (g_user_uapsd_info[assoc_id] == OSAL_NULL) {
1009 oam_warning_log1(0, OAM_SF_CSA, "vap_id[%d] hmac_uapsd_ap_user_del mem already free!", assoc_id);
1010 return OSAL_TRUE;
1011 }
1012
1013 hmac_uapsd_user_destroy(hmac_user);
1014
1015 oal_mem_free((osal_void *)g_user_uapsd_info[assoc_id], OAL_TRUE);
1016 g_user_uapsd_info[assoc_id] = OSAL_NULL;
1017
1018 return OSAL_TRUE;
1019 }
1020
hmac_uapsd_ap_vap_add(osal_void * notify_data)1021 OSAL_STATIC osal_bool hmac_uapsd_ap_vap_add(osal_void *notify_data)
1022 {
1023 hmac_vap_stru *hmac_vap = (hmac_vap_stru *)notify_data;
1024
1025 if (hmac_vap == OSAL_NULL) {
1026 return OSAL_FALSE;
1027 }
1028
1029 if (hmac_vap->vap_mode != WLAN_VAP_MODE_BSS_AP) {
1030 return OSAL_TRUE;
1031 }
1032
1033 hmac_vap->cap_flag.uapsd = OSAL_TRUE;
1034
1035 return OSAL_TRUE;
1036 }
1037
hmac_uapsd_ap_init(osal_void)1038 osal_u32 hmac_uapsd_ap_init(osal_void)
1039 {
1040 frw_util_notifier_register(WLAN_UTIL_NOTIFIER_EVENT_ADD_VAP, hmac_uapsd_ap_vap_add);
1041 frw_util_notifier_register(WLAN_UTIL_NOTIFIER_EVENT_ADD_USER, hmac_uapsd_ap_user_add);
1042 frw_util_notifier_register(WLAN_UTIL_NOTIFIER_EVENT_DEL_USER, hmac_uapsd_ap_user_del);
1043
1044 frw_msg_hook_register(WLAN_MSG_D2H_CRX_PS_TX_STATUS, hmac_config_tx_comp_ps_handle);
1045
1046 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_UPDATE_USER_PARA, hmac_uapsd_update_user_para_etc);
1047 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_CHECK_TRIGGER, hmac_uapsd_rx_trigger_check);
1048 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_FLUSH_QUEUE, hmac_uapsd_flush_queue);
1049 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_ENQUEUE_PROC, hmac_uapsd_enqueue_proc);
1050 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_IS_QUEUE_EMPTY, hmac_psm_is_uapsd_empty);
1051 hmac_feature_hook_register(HMAC_FHOOK_AP_UAPSD_GET_USER_INFO, hmac_ap_get_user_uapsd_info);
1052
1053 return OAL_SUCC;
1054 }
1055
hmac_uapsd_ap_deinit(osal_void)1056 osal_void hmac_uapsd_ap_deinit(osal_void)
1057 {
1058 frw_util_notifier_unregister(WLAN_UTIL_NOTIFIER_EVENT_ADD_VAP, hmac_uapsd_ap_vap_add);
1059 frw_util_notifier_unregister(WLAN_UTIL_NOTIFIER_EVENT_ADD_USER, hmac_uapsd_ap_user_add);
1060 frw_util_notifier_unregister(WLAN_UTIL_NOTIFIER_EVENT_DEL_USER, hmac_uapsd_ap_user_del);
1061
1062 frw_msg_hook_unregister(WLAN_MSG_D2H_CRX_PS_TX_STATUS);
1063
1064 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_UPDATE_USER_PARA);
1065 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_CHECK_TRIGGER);
1066 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_FLUSH_QUEUE);
1067 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_ENQUEUE_PROC);
1068 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_IS_QUEUE_EMPTY);
1069 hmac_feature_hook_unregister(HMAC_FHOOK_AP_UAPSD_GET_USER_INFO);
1070
1071 return;
1072 }
1073
1074 #ifdef __cplusplus
1075 #if __cplusplus
1076 }
1077 #endif
1078 #endif
1079