• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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