1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * Copyright(c) 2019 - 2020 Realtek Corporation.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify it
6*4882a593Smuzhiyun * under the terms of version 2 of the GNU General Public License as
7*4882a593Smuzhiyun * published by the Free Software Foundation.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but WITHOUT
10*4882a593Smuzhiyun * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12*4882a593Smuzhiyun * more details.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Author: vincent_fann@realtek.com
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun *****************************************************************************/
17*4882a593Smuzhiyun #define _PHL_CMD_SCAN_C_
18*4882a593Smuzhiyun #include "phl_headers.h"
19*4882a593Smuzhiyun #include "phl_scan.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define param_to_phlcom(_param) (_param->wifi_role->phl_com)
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun enum _CMD_SCAN_STATE {
27*4882a593Smuzhiyun CMD_SCAN_ACQUIRE = BIT0,
28*4882a593Smuzhiyun CMD_SCAN_STARTED = BIT1,
29*4882a593Smuzhiyun CMD_SCAN_DF_IO = BIT2, /* Disable Function : IO */
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static void _cmd_scan_timer(void* role);
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define DBG_SCAN_CHAN_DUMP
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #ifdef DBG_SCAN_CHAN_DUMP
37*4882a593Smuzhiyun static void
_cmd_estimated_swch_seq(struct rtw_phl_scan_param * param,u8 op_num)38*4882a593Smuzhiyun _cmd_estimated_swch_seq(struct rtw_phl_scan_param *param, u8 op_num)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun u8 chidx = 0;
41*4882a593Smuzhiyun u8 opidx = 0;
42*4882a593Smuzhiyun u8 total_ch_num = 0;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun if ((param->back_op_mode == SCAN_BKOP_CNT) &&
45*4882a593Smuzhiyun (param->back_op_ch_cnt == 0)) {
46*4882a593Smuzhiyun PHL_ERR("%s bkop_cnt == 0\n", __func__);
47*4882a593Smuzhiyun _os_warn_on(1);
48*4882a593Smuzhiyun return;
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun /*swicth channel sequence by cmd_scan's estimated */
52*4882a593Smuzhiyun PHL_INFO("%s:: Estimated channel sequence:\n", __func__);
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun if (param->back_op_mode == SCAN_BKOP_CNT) {
55*4882a593Smuzhiyun PHL_INFO("[SCAN_BKOP_CNT]\n");
56*4882a593Smuzhiyun for(chidx = 0; chidx < param->ch_num; chidx++) {
57*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "%3d, ", param->ch[chidx].channel);
58*4882a593Smuzhiyun total_ch_num++;
59*4882a593Smuzhiyun if(!((chidx + 1) % param->back_op_ch_cnt)) {
60*4882a593Smuzhiyun if (op_num) {
61*4882a593Smuzhiyun for(opidx = 0; opidx < op_num; opidx++) {
62*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_,
63*4882a593Smuzhiyun "[%3d], ", param->back_op_ch[opidx].channel);
64*4882a593Smuzhiyun total_ch_num++;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun if(!((chidx + 1) % (param->back_op_ch_cnt * 2)))
69*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "\n");
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "\n");
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN_BKOP_TIME
75*4882a593Smuzhiyun else if (param->back_op_mode == SCAN_BKOP_TIMER) {
76*4882a593Smuzhiyun u16 ch_dur;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun PHL_INFO("[SCAN_BKOP_TIMER]\n");
79*4882a593Smuzhiyun for(chidx = 0; chidx < param->ch_num; chidx++) {
80*4882a593Smuzhiyun total_ch_num++;
81*4882a593Smuzhiyun ch_dur = (op_num) ? param->back_op_off_ch_dur_ms : param->ch[chidx].duration;
82*4882a593Smuzhiyun PHL_INFO("\t%3d, dur:%d(ms)\n", param->ch[chidx].channel, ch_dur);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun if (op_num) {
85*4882a593Smuzhiyun for(opidx = 0; opidx < op_num; opidx++) {
86*4882a593Smuzhiyun total_ch_num++;
87*4882a593Smuzhiyun PHL_INFO("\t[%3d], dur:%d(ms)\n",
88*4882a593Smuzhiyun param->back_op_ch[opidx].channel, param->back_op_ch[opidx].duration);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun PHL_INFO("max_listen_time:%d (ms)\n", param->max_listen_time);
92*4882a593Smuzhiyun PHL_INFO("op_ch_dur_ms:%d, off_ch_dur_ms:%d, off_ch_ext_dur_ms:%d (ms)",
93*4882a593Smuzhiyun param->back_op_ch_dur_ms,
94*4882a593Smuzhiyun param->back_op_off_ch_dur_ms,
95*4882a593Smuzhiyun param->back_op_off_ch_ext_dur_ms);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun #endif
98*4882a593Smuzhiyun else if (param->back_op_mode == SCAN_BKOP_NONE) {
99*4882a593Smuzhiyun PHL_INFO("[SCAN_BKOP_NONE]\n");
100*4882a593Smuzhiyun for(chidx = 0; chidx < param->ch_num; chidx++) {
101*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "%3d, ", param->ch[chidx].channel);
102*4882a593Smuzhiyun total_ch_num++;
103*4882a593Smuzhiyun if(!((chidx + 1) % 6))
104*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "\n");
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun PHL_DATA(COMP_PHL_DBG, _PHL_INFO_, "\n");
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun PHL_INFO("Scan chan num:%d , Total num:%d, repeat:%d\n",
110*4882a593Smuzhiyun param->ch_num, total_ch_num, param->repeat);
111*4882a593Smuzhiyun PHL_INFO("--------\n");
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun #endif /*DBG_SCAN_CHAN_DUMP*/
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static void
_cmd_scan_update_chlist(void * drv,struct rtw_phl_scan_param * param)116*4882a593Smuzhiyun _cmd_scan_update_chlist(void *drv, struct rtw_phl_scan_param *param)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun u8 idx = 0;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun INIT_LIST_HEAD(¶m->chlist.queue);
121*4882a593Smuzhiyun for(idx = 0; idx < param->ch_num; idx++) {
122*4882a593Smuzhiyun INIT_LIST_HEAD(¶m->ch[idx].list);
123*4882a593Smuzhiyun pq_push(drv, ¶m->chlist, ¶m->ch[idx].list, _tail, _ps);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun * Insert op channel list
129*4882a593Smuzhiyun * Ex. ch_intvl =3
130*4882a593Smuzhiyun * ch_idx : -1, 0, 1, 2, 3, 4, 5, 6
131*4882a593Smuzhiyun * ^ ^
132*4882a593Smuzhiyun * op0~op5 op0~op5
133*4882a593Smuzhiyun *
134*4882a593Smuzhiyun * => 0,1,2,[op0],[op1],3,4,5,[op0],[op1],6,7,8,[op0],[op1]
135*4882a593Smuzhiyun */
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun static inline void
_cmd_scan_enqueue_opch(void * drv,struct rtw_phl_scan_param * param,struct phl_queue * q)138*4882a593Smuzhiyun _cmd_scan_enqueue_opch(void *drv, struct rtw_phl_scan_param *param, struct phl_queue *q)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun u8 idx = 0;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun for(idx = 0; idx < MAX_WIFI_ROLE_NUMBER; idx ++) {
143*4882a593Smuzhiyun if(param->back_op_ch[idx].channel)
144*4882a593Smuzhiyun pq_push(drv, ¶m->chlist, ¶m->back_op_ch[idx].list, _first, _ps);
145*4882a593Smuzhiyun else
146*4882a593Smuzhiyun break;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun }
_cmd_scan_select_chnl(void * drv,struct rtw_phl_scan_param * param)149*4882a593Smuzhiyun static struct phl_scan_channel *_cmd_scan_select_chnl(
150*4882a593Smuzhiyun void *drv, struct rtw_phl_scan_param *param)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun struct phl_scan_channel *scan_ch = NULL;
153*4882a593Smuzhiyun _os_list* obj = NULL;
154*4882a593Smuzhiyun bool back_op_is_required = (param->back_op_ch[0].channel)? true:false;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun next_ch:
157*4882a593Smuzhiyun if(pq_pop(drv, ¶m->chlist, &obj, _first, _ps)) {
158*4882a593Smuzhiyun scan_ch = (struct phl_scan_channel*)obj;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if(scan_ch->scan_mode == NORMAL_SCAN_MODE) {
161*4882a593Smuzhiyun /* 1- enable, 2- BK_CNT mode, 3- prev is non-op, 4- ch_intvl's turn */
162*4882a593Smuzhiyun if (back_op_is_required && param->back_op_mode == SCAN_BKOP_CNT) {
163*4882a593Smuzhiyun if(param->scan_ch &&
164*4882a593Smuzhiyun !((param->ch_idx + 1) % param->back_op_ch_cnt)) {
165*4882a593Smuzhiyun _cmd_scan_enqueue_opch(drv, param, ¶m->chlist);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun param->ch_idx++;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN_BKOP_TIME
171*4882a593Smuzhiyun else if (scan_ch->scan_mode == P2P_LISTEN_MODE) {
172*4882a593Smuzhiyun if (back_op_is_required && param->back_op_mode == SCAN_BKOP_TIMER) {
173*4882a593Smuzhiyun scan_ch->duration = param->back_op_off_ch_dur_ms;
174*4882a593Smuzhiyun _cmd_scan_enqueue_opch(drv, param, ¶m->chlist);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun param->ch_idx++;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun #endif
179*4882a593Smuzhiyun param->scan_ch = scan_ch;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun else if(param->repeat > 0) {
182*4882a593Smuzhiyun _cmd_scan_update_chlist(drv, param);
183*4882a593Smuzhiyun param->ch_idx = 0;
184*4882a593Smuzhiyun /* 255 means loop forever */
185*4882a593Smuzhiyun if (param->repeat != 255)
186*4882a593Smuzhiyun param->repeat--;
187*4882a593Smuzhiyun goto next_ch;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun else {
190*4882a593Smuzhiyun return NULL;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun PHL_INFO("%s: repeat[%d] ch_idx=[%d/%d], ch_number=%d, scan_mode= %s\n", __func__,
194*4882a593Smuzhiyun param->repeat, param->ch_idx, param->ch_num, param->scan_ch->channel,
195*4882a593Smuzhiyun (param->scan_ch->scan_mode == BACKOP_MODE)? "OP_CH": "Non-OP");
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun return param->scan_ch;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun /* Notification complete */
_cmd_scan_timer_notify_cb(void * role,struct phl_msg * msg)201*4882a593Smuzhiyun void _cmd_scan_timer_notify_cb(
202*4882a593Smuzhiyun void *role, struct phl_msg *msg)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun if (IS_MSG_CANNOT_IO(msg->msg_id)) {
205*4882a593Smuzhiyun PHL_ERR("%s: SWCH_DONE failure by CANNOT IO\n", __func__);
206*4882a593Smuzhiyun return;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (IS_MSG_CANCEL(msg->msg_id)) {
210*4882a593Smuzhiyun /* Last event occured MSG_STATUS_PENDING */
211*4882a593Smuzhiyun PHL_ERR("%s: SWCH_DONE pending or abort Occurred!\n", __func__);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun _cmd_scan_timer(role);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
_cmd_scan_timer(void * role)217*4882a593Smuzhiyun static void _cmd_scan_timer(void* role)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun struct rtw_wifi_role_t *wifi_role = (struct rtw_wifi_role_t *)role;
220*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
221*4882a593Smuzhiyun struct phl_info_t *phl_info = phl_com->phl_priv;
222*4882a593Smuzhiyun u8 band_idx = wifi_role->hw_band;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun struct phl_msg msg = {0};
225*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun PHL_INFO("%s \n", __func__);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_SCAN);
230*4882a593Smuzhiyun /** When listen state of each channel entry expired,
231*4882a593Smuzhiyun * timer callback send MSG_EVT_LISTEN_STATE_EXPIRE for additional condition check
232*4882a593Smuzhiyun * If nothing specitail occured, then send MSG_EVT_SWCH_START to proceed for the rest of channel list
233*4882a593Smuzhiyun * therefore, additional process delay for MSG_EVT_LISTEN_STATE_EXPIRE would prolong listen period
234*4882a593Smuzhiyun * */
235*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_LISTEN_STATE_EXPIRE);
236*4882a593Smuzhiyun msg.rsvd[0] = (u8*)role;
237*4882a593Smuzhiyun msg.band_idx = band_idx;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun attr.completion.completion = _cmd_scan_timer_notify_cb;
240*4882a593Smuzhiyun attr.completion.priv = role;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun if(phl_disp_eng_send_msg(phl_info, &msg, &attr, NULL) != RTW_PHL_STATUS_SUCCESS)
243*4882a593Smuzhiyun PHL_ERR("%s: [SCAN_TIMER] phl_disp_eng_send_msg failed !\n", __func__);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /* Notification complete */
_cmd_swch_done_notify_cb(void * drv,struct phl_msg * msg)247*4882a593Smuzhiyun void _cmd_swch_done_notify_cb(
248*4882a593Smuzhiyun void *drv, struct phl_msg *msg)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun if (msg->inbuf) {
251*4882a593Smuzhiyun _os_mem_free(drv, msg->inbuf, msg->inlen);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
_cmd_swch_done_notify(void * dispr,void * drv,struct rtw_phl_scan_param * param)255*4882a593Smuzhiyun enum rtw_phl_status _cmd_swch_done_notify(
256*4882a593Smuzhiyun void *dispr, void *drv, struct rtw_phl_scan_param *param)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
259*4882a593Smuzhiyun struct phl_scan_channel *scan_ch = param->scan_ch;
260*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = param_to_phlcom(param);
261*4882a593Smuzhiyun struct phl_info_t *phl = (struct phl_info_t *) phl_com->phl_priv;
262*4882a593Smuzhiyun struct phl_msg msg = {0};
263*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
264*4882a593Smuzhiyun u8 *info = NULL;
265*4882a593Smuzhiyun u8 idx = 0xff;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun info = _os_mem_alloc(drv, sizeof(struct phl_scan_channel));
268*4882a593Smuzhiyun if (info == NULL) {
269*4882a593Smuzhiyun PHL_ERR("%s: [SWCH_DONE] alloc buffer failed!\n", __func__);
270*4882a593Smuzhiyun return RTW_PHL_STATUS_FAILURE;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun _os_mem_cpy(drv, info, scan_ch, sizeof(*scan_ch));
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_SCAN);
276*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SWCH_DONE);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun attr.opt = MSG_OPT_CLR_SNDR_MSG_IF_PENDING;
279*4882a593Smuzhiyun attr.completion.completion = _cmd_swch_done_notify_cb;
280*4882a593Smuzhiyun attr.completion.priv = drv;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun msg.inbuf = info;
283*4882a593Smuzhiyun msg.inlen = sizeof(struct phl_scan_channel);
284*4882a593Smuzhiyun msg.rsvd[0] = (u8*)param->wifi_role;
285*4882a593Smuzhiyun phl_dispr_get_idx(dispr, &idx);
286*4882a593Smuzhiyun msg.band_idx = idx;
287*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl, &msg, &attr, NULL);
288*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS) {
289*4882a593Smuzhiyun PHL_ERR("%s: [SWCH_DONE] phl_disp_eng_send_msg failed!\n", __func__);
290*4882a593Smuzhiyun _os_mem_free(drv, info, sizeof(struct phl_scan_channel));
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun return pstatus;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
_cmd_scan_end(void * drv,struct rtw_phl_scan_param * param)295*4882a593Smuzhiyun void _cmd_scan_end(
296*4882a593Smuzhiyun void *drv, struct rtw_phl_scan_param *param)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun struct rtw_wifi_role_t *wifi_role = param->wifi_role;
299*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
300*4882a593Smuzhiyun struct phl_info_t *phl_info = phl_com->phl_priv;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun PHL_INFO("_cmd_scan_end \n");
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun param->end_time = _os_get_cur_time_ms();
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun /* dump scan time */
307*4882a593Smuzhiyun param->total_scan_time =
308*4882a593Smuzhiyun phl_get_passing_time_ms(param->enqueue_time);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun pq_deinit(drv, ¶m->chlist);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /* acquire state */
313*4882a593Smuzhiyun _os_cancel_timer(drv, ¶m->scan_timer);
314*4882a593Smuzhiyun _os_release_timer(drv, ¶m->scan_timer);
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun if(TEST_STATUS_FLAG(param->state, CMD_SCAN_STARTED) &&
317*4882a593Smuzhiyun !TEST_STATUS_FLAG(param->state, CMD_SCAN_DF_IO) )
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun rtw_hal_com_scan_restore_tx_lifetime(phl_info->hal, wifi_role->hw_band);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun rtw_hal_scan_set_rxfltr_by_mode(phl_info->hal, wifi_role->hw_band,
322*4882a593Smuzhiyun false, ¶m->fltr_mode);
323*4882a593Smuzhiyun rtw_hal_scan_pause_tx_fifo(phl_info->hal, wifi_role->hw_band, false);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun rtw_hal_notification(phl_info->hal, MSG_EVT_SCAN_END, wifi_role->hw_band);
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (param->ops->scan_complete)
329*4882a593Smuzhiyun param->ops->scan_complete(param->priv, param);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* Notification complete */
_cmd_abort_notify_cb(void * drv,struct phl_msg * msg)333*4882a593Smuzhiyun void _cmd_abort_notify_cb(
334*4882a593Smuzhiyun void *drv, struct phl_msg *msg)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param *)msg->inbuf;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun if(IS_MSG_CANNOT_IO(msg->msg_id))
339*4882a593Smuzhiyun SET_STATUS_FLAG(param->state, CMD_SCAN_DF_IO);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun _cmd_scan_end(drv, param);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
_cmd_abort_notify(void * dispr,void * drv,struct rtw_phl_scan_param * param,bool abort)344*4882a593Smuzhiyun void _cmd_abort_notify(void *dispr, void *drv,
345*4882a593Smuzhiyun struct rtw_phl_scan_param *param, bool abort)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
348*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = param_to_phlcom(param);
349*4882a593Smuzhiyun struct phl_msg msg = {0};
350*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
351*4882a593Smuzhiyun struct phl_info_t *phl = (struct phl_info_t *) phl_com->phl_priv;
352*4882a593Smuzhiyun u8 idx = 0xff;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun if(TEST_STATUS_FLAG(param->state, CMD_SCAN_ACQUIRE))
355*4882a593Smuzhiyun {
356*4882a593Smuzhiyun param->result = SCAN_REQ_CANCEL;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_SCAN);
359*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SCAN_END);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun if(abort)
362*4882a593Smuzhiyun attr.opt = MSG_OPT_SEND_IN_ABORT;
363*4882a593Smuzhiyun attr.completion.completion = _cmd_abort_notify_cb;
364*4882a593Smuzhiyun attr.completion.priv = drv;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun msg.inbuf = (u8*)param;
367*4882a593Smuzhiyun msg.rsvd[0] = (u8*)param->wifi_role;
368*4882a593Smuzhiyun #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
369*4882a593Smuzhiyun msg.rsvd[1] = (u8*)param->ops->scan_issue_null_data;
370*4882a593Smuzhiyun #endif
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun phl_dispr_get_idx(dispr, &idx);
373*4882a593Smuzhiyun msg.band_idx = idx;
374*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl, &msg, &attr, NULL);
375*4882a593Smuzhiyun if (RTW_PHL_STATUS_SUCCESS != pstatus) {
376*4882a593Smuzhiyun /* (1) dispr_stop
377*4882a593Smuzhiyun (2) idle msg empty .*/
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun PHL_ERR("%s :: [Abort] dispr_send_msg failed (0x%X)\n",
380*4882a593Smuzhiyun __func__, pstatus);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun if(pstatus == RTW_PHL_STATUS_UNEXPECTED_ERROR ||
383*4882a593Smuzhiyun TEST_STATUS_FLAG(phl_com->dev_state, RTW_DEV_SURPRISE_REMOVAL)) {
384*4882a593Smuzhiyun /* clean sw resource only */
385*4882a593Smuzhiyun /* (1) driver is going to unload */
386*4882a593Smuzhiyun /* (2) Supprise remove */
387*4882a593Smuzhiyun SET_STATUS_FLAG(param->state, CMD_SCAN_DF_IO);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun _cmd_abort_notify_cb(drv, &msg);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun else {
393*4882a593Smuzhiyun param->result = SCAN_REQ_ABORT;
394*4882a593Smuzhiyun pq_deinit(drv, ¶m->chlist);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if (param->ops->scan_complete)
397*4882a593Smuzhiyun param->ops->scan_complete(param->priv, param);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
_cmd_scan_fail_ev_hdlr(void * dispr,void * priv,struct phl_msg * msg)401*4882a593Smuzhiyun enum phl_mdl_ret_code _cmd_scan_fail_ev_hdlr(
402*4882a593Smuzhiyun void* dispr, void* priv, struct phl_msg* msg)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
405*4882a593Smuzhiyun struct rtw_wifi_role_t *wifi_role = param->wifi_role;
406*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
407*4882a593Smuzhiyun struct phl_info_t *phl_info = phl_com->phl_priv;
408*4882a593Smuzhiyun void *d = phlcom_to_drvpriv(phl_com);
409*4882a593Smuzhiyun u8 idx = 0xff;
410*4882a593Smuzhiyun struct phl_msg nextmsg = {0};
411*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
412*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(nextmsg.msg_id, PHL_FG_MDL_SCAN);
415*4882a593Smuzhiyun phl_dispr_get_idx(dispr, &idx);
416*4882a593Smuzhiyun nextmsg.band_idx = idx;
417*4882a593Smuzhiyun switch(MSG_EVT_ID_FIELD(msg->msg_id)) {
418*4882a593Smuzhiyun case MSG_EVT_SCAN_START:
419*4882a593Smuzhiyun /* fall through */
420*4882a593Smuzhiyun case MSG_EVT_SWCH_START:
421*4882a593Smuzhiyun /* fall through */
422*4882a593Smuzhiyun case MSG_EVT_SWCH_DONE:
423*4882a593Smuzhiyun PHL_INFO("SCAN_START/SWCH_START/SWCH_DONE:: failed/timeout handler \n");
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(nextmsg.msg_id, MSG_EVT_SCAN_END);
426*4882a593Smuzhiyun nextmsg.rsvd[0] = (u8*)param->wifi_role;
427*4882a593Smuzhiyun #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
428*4882a593Smuzhiyun nextmsg.rsvd[1] = (u8*)param->ops->scan_issue_null_data;
429*4882a593Smuzhiyun #endif
430*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl_info, &nextmsg, &attr, NULL);
431*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS)
432*4882a593Smuzhiyun PHL_ERR("%s :: [SWCH_START][1] phl_disp_eng_send_msg failed\n", __func__);
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun case MSG_EVT_SCAN_END:
436*4882a593Smuzhiyun // free token
437*4882a593Smuzhiyun // release timer
438*4882a593Smuzhiyun PHL_INFO("MSG_EVT_SCAN_END:: failed/timeout handler \n");
439*4882a593Smuzhiyun pstatus = phl_disp_eng_free_token(phl_info, idx, ¶m->token);
440*4882a593Smuzhiyun if(pstatus == RTW_PHL_STATUS_SUCCESS)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun if(IS_MSG_CANNOT_IO(msg->msg_id))
443*4882a593Smuzhiyun SET_STATUS_FLAG(param->state, CMD_SCAN_DF_IO);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun _cmd_scan_end(d, param);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun break;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun default:
450*4882a593Smuzhiyun /* unknown state */
451*4882a593Smuzhiyun break;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun return MDL_RET_SUCCESS;
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun
_cmd_scan_hdl_external_evt(void * dispr,void * priv,struct phl_msg * msg)457*4882a593Smuzhiyun enum phl_mdl_ret_code _cmd_scan_hdl_external_evt(
458*4882a593Smuzhiyun void* dispr, void* priv, struct phl_msg* msg)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun PHL_DBG("%s :: From others MDL =%d , EVT_ID=%d\n", __func__,
461*4882a593Smuzhiyun MSG_MDL_ID_FIELD(msg->msg_id), MSG_EVT_ID_FIELD(msg->msg_id));
462*4882a593Smuzhiyun return MDL_RET_IGNORE;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
_cmd_chk_ext_act_scan(struct rtw_phl_scan_param * param)465*4882a593Smuzhiyun u8 _cmd_chk_ext_act_scan(struct rtw_phl_scan_param *param)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun #ifdef RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN
468*4882a593Smuzhiyun /** suppose to query the time of last recieved beacon in current channel here
469*4882a593Smuzhiyun * then change state to EXT_ACT_SCAN_TRIGGER if needed
470*4882a593Smuzhiyun * but, PHL does not store bss list at the moment, therefore,
471*4882a593Smuzhiyun * core layer use set_info (FG_REQ_OP_NOTIFY_BCN_RCV) to notify scan module incoming bcn
472*4882a593Smuzhiyun * and change state to EXT_ACT_SCAN_TRIGGER accordingly.
473*4882a593Smuzhiyun */
474*4882a593Smuzhiyun #endif
475*4882a593Smuzhiyun if (param->scan_ch->type == RTW_PHL_SCAN_PASSIVE &&
476*4882a593Smuzhiyun param->scan_ch->ext_act_scan == EXT_ACT_SCAN_TRIGGER) {
477*4882a593Smuzhiyun if (param->ops->scan_issue_pbreq)
478*4882a593Smuzhiyun param->ops->scan_issue_pbreq(param->priv, param);
479*4882a593Smuzhiyun param->scan_ch->ext_act_scan = EXT_ACT_SCAN_DONE;
480*4882a593Smuzhiyun return true;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun return false;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun void
_cmd_scan_start(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wifi_role,struct rtw_phl_scan_param * param)486*4882a593Smuzhiyun _cmd_scan_start(struct phl_info_t *phl_info,
487*4882a593Smuzhiyun struct rtw_wifi_role_t *wifi_role,
488*4882a593Smuzhiyun struct rtw_phl_scan_param *param)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun rtw_hal_scan_pause_tx_fifo(phl_info->hal, wifi_role->hw_band, true);
491*4882a593Smuzhiyun rtw_hal_scan_set_rxfltr_by_mode(phl_info->hal, wifi_role->hw_band,
492*4882a593Smuzhiyun true, ¶m->fltr_mode);
493*4882a593Smuzhiyun rtw_hal_com_scan_set_tx_lifetime(phl_info->hal, wifi_role->hw_band);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
_cmd_scan_hdl_internal_evt(void * dispr,void * priv,struct phl_msg * msg)496*4882a593Smuzhiyun enum phl_mdl_ret_code _cmd_scan_hdl_internal_evt(
497*4882a593Smuzhiyun void* dispr, void* priv, struct phl_msg* msg)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
500*4882a593Smuzhiyun struct rtw_wifi_role_t *wifi_role = param->wifi_role;
501*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
502*4882a593Smuzhiyun struct phl_info_t *phl_info = phl_com->phl_priv;
503*4882a593Smuzhiyun void *d = phlcom_to_drvpriv(phl_com);
504*4882a593Smuzhiyun u32 diff_time = 0;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun struct phl_msg nextmsg = {0};
507*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
508*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
509*4882a593Smuzhiyun u8 idx = 0xff;
510*4882a593Smuzhiyun struct phl_scan_channel *scan_ch = NULL;
511*4882a593Smuzhiyun bool tx_pause = true;
512*4882a593Smuzhiyun struct rtw_chan_def chdef = {0};
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun phl_dispr_get_idx(dispr, &idx);
515*4882a593Smuzhiyun diff_time = phl_get_passing_time_ms(param->enqueue_time);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (param->max_scan_time && diff_time >= param->max_scan_time) {
518*4882a593Smuzhiyun PHL_WARN("%s:: Timeout! %d > max_time %d\n",
519*4882a593Smuzhiyun __func__, diff_time, param->max_scan_time);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* Abort scan request */
522*4882a593Smuzhiyun /* Based on [CN3AXSW-552]
523*4882a593Smuzhiyun * ex. max_scan_time = 4sec
524*4882a593Smuzhiyun * Usb dongle would abort scan_req in 29~33th chnl
525*4882a593Smuzhiyun * If chnllist insert op-chnl, scan_req would be aborted in 21~23th chnl.
526*4882a593Smuzhiyun * It means that usb dongle always can't do fully scan.
527*4882a593Smuzhiyun * So, abort scan_req or not, depend on core layer.
528*4882a593Smuzhiyun */
529*4882a593Smuzhiyun /*_cmd_scan_fail_ev_hdlr(dispr, priv, msg);
530*4882a593Smuzhiyun return MDL_RET_FAIL; */
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun else {
533*4882a593Smuzhiyun PHL_INFO("%s:: TimeIntvl: %u \n", __func__, diff_time);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN_BKOP_TIME
537*4882a593Smuzhiyun if (param->max_listen_time && diff_time >= param->max_listen_time) {
538*4882a593Smuzhiyun PHL_WARN("%s:: Timeout! %d > max_listen_time %d\n",
539*4882a593Smuzhiyun __func__, diff_time, param->max_listen_time);
540*4882a593Smuzhiyun #if 0
541*4882a593Smuzhiyun _cmd_scan_fail_ev_hdlr(dispr, priv, msg);
542*4882a593Smuzhiyun return MDL_RET_FAIL;
543*4882a593Smuzhiyun #endif
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun #endif
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(nextmsg.msg_id, PHL_FG_MDL_SCAN);
548*4882a593Smuzhiyun nextmsg.band_idx = idx;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun switch(MSG_EVT_ID_FIELD(msg->msg_id)) {
551*4882a593Smuzhiyun case MSG_EVT_SCAN_START:
552*4882a593Smuzhiyun _cmd_scan_start(phl_info, wifi_role, param);
553*4882a593Smuzhiyun rtw_hal_notification(phl_info->hal, MSG_EVT_SCAN_START,
554*4882a593Smuzhiyun wifi_role->hw_band);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun /* [scan start notify] */
557*4882a593Smuzhiyun if (param->ops->scan_start)
558*4882a593Smuzhiyun param->ops->scan_start(param->priv, param);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun SET_STATUS_FLAG(param->state, CMD_SCAN_STARTED);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(nextmsg.msg_id, MSG_EVT_SWCH_START);
563*4882a593Smuzhiyun nextmsg.rsvd[0] = (u8*)wifi_role;
564*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl_info, &nextmsg, &attr, NULL);
565*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS)
566*4882a593Smuzhiyun PHL_ERR("%s :: [SCAN_START] phl_disp_eng_send_msg failed\n", __func__);
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun case MSG_EVT_LISTEN_STATE_EXPIRE:
569*4882a593Smuzhiyun if (_cmd_chk_ext_act_scan(param)) {
570*4882a593Smuzhiyun _os_set_timer(d, ¶m->scan_timer, param->ext_act_scan_period);
571*4882a593Smuzhiyun PHL_INFO("%s :: extend listen state of ch %d by %d ms, and reset timer\n",
572*4882a593Smuzhiyun __func__, param->scan_ch->channel, param->ext_act_scan_period);
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(nextmsg.msg_id, MSG_EVT_SWCH_START);
576*4882a593Smuzhiyun nextmsg.rsvd[0] = (u8*)wifi_role;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl_info, &nextmsg, &attr, NULL);
579*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS)
580*4882a593Smuzhiyun PHL_ERR("%s :: [LISTEN_STATE_EXPIRE] dispr_send_msg failed\n", __func__);
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun break;
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun case MSG_EVT_SWCH_START:
585*4882a593Smuzhiyun /* ycx++
586*4882a593Smuzhiyun ycx > length(yclist) ? SCAN_EV_END : switch channel */
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun PHL_INFO("MSG_EVT_SWCH_START \n");
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /* For the first time, param->scan_ch would be NULL */
591*4882a593Smuzhiyun /* Current channel scan_mode */
592*4882a593Smuzhiyun if (param->scan_ch && param->scan_ch->scan_mode == BACKOP_MODE) {
593*4882a593Smuzhiyun tx_pause = false;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun scan_ch = _cmd_scan_select_chnl(d, param);
597*4882a593Smuzhiyun if (scan_ch == NULL) {
598*4882a593Smuzhiyun /* no more channel, we are done */
599*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(nextmsg.msg_id, MSG_EVT_SCAN_END);
600*4882a593Smuzhiyun nextmsg.rsvd[0] = (u8*)param->wifi_role;
601*4882a593Smuzhiyun #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
602*4882a593Smuzhiyun nextmsg.rsvd[1] = (u8*)param->ops->scan_issue_null_data;
603*4882a593Smuzhiyun #endif
604*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl_info, &nextmsg, &attr, NULL);
605*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS)
606*4882a593Smuzhiyun PHL_ERR("%s :: [SWCH_START][1] dispr_send_msg failed\n", __func__);
607*4882a593Smuzhiyun break;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun /* Next channel scan_mode */
611*4882a593Smuzhiyun if ((scan_ch->scan_mode != BACKOP_MODE) && !tx_pause) {
612*4882a593Smuzhiyun /* Tx pause */
613*4882a593Smuzhiyun rtw_hal_scan_pause_tx_fifo(phl_info->hal, wifi_role->hw_band, true);
614*4882a593Smuzhiyun tx_pause = true;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun chdef.band = scan_ch->band;
617*4882a593Smuzhiyun chdef.chan = (u8)scan_ch->channel;
618*4882a593Smuzhiyun chdef.bw = scan_ch->bw;
619*4882a593Smuzhiyun chdef.offset = scan_ch->offset;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun phl_set_ch_bw(wifi_role, &chdef, false);
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun if ((scan_ch->scan_mode != BACKOP_MODE) &&
624*4882a593Smuzhiyun (scan_ch->type == RTW_PHL_SCAN_ACTIVE)) {
625*4882a593Smuzhiyun /* Notify RF to do tssi backup */
626*4882a593Smuzhiyun rtw_hal_notification(phl_info->hal, MSG_EVT_SWCH_START, wifi_role->hw_band);
627*4882a593Smuzhiyun if (param->ops->scan_issue_pbreq)
628*4882a593Smuzhiyun param->ops->scan_issue_pbreq(param->priv, param);
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if ((scan_ch->scan_mode == BACKOP_MODE) && tx_pause) {
632*4882a593Smuzhiyun /* Tx un-pause */
633*4882a593Smuzhiyun rtw_hal_scan_pause_tx_fifo(phl_info->hal, wifi_role->hw_band, false);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun _os_set_timer(d, ¶m->scan_timer, scan_ch->duration);
637*4882a593Smuzhiyun #ifdef DBG_SCAN_CHAN_DUMP
638*4882a593Smuzhiyun PHL_INFO("[SCAN] band:%d chan:%d bw:%d offset:%d duration:%d (ms)\n",
639*4882a593Smuzhiyun scan_ch->band, scan_ch->channel, scan_ch->bw,
640*4882a593Smuzhiyun scan_ch->offset, scan_ch->duration);
641*4882a593Smuzhiyun #endif
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun pstatus = _cmd_swch_done_notify(dispr, d, param);
644*4882a593Smuzhiyun break;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun case MSG_EVT_SWCH_DONE:
647*4882a593Smuzhiyun if (param->ops->scan_ch_ready)
648*4882a593Smuzhiyun param->ops->scan_ch_ready(param->priv, param);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun PHL_INFO("MSG_EVT_SWCH_DONE :: duration=%d\n", param->scan_ch->duration);
651*4882a593Smuzhiyun break;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun case MSG_EVT_SCAN_END:
654*4882a593Smuzhiyun PHL_INFO("MSG_EVT_SCAN_END \n");
655*4882a593Smuzhiyun pstatus = phl_disp_eng_free_token(phl_info, idx, ¶m->token);
656*4882a593Smuzhiyun if(pstatus == RTW_PHL_STATUS_SUCCESS) {
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun param->result = SCAN_REQ_COMPLETE;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun _cmd_scan_end(d, param);
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun else
663*4882a593Smuzhiyun PHL_WARN("%s :: [SCAN_END] Abort occurred, skip!\n", __func__);
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun break;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun default:
668*4882a593Smuzhiyun /* unknown state */
669*4882a593Smuzhiyun break;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun return MDL_RET_SUCCESS;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun
_phl_cmd_scan_req_acquired(void * dispr,void * priv)676*4882a593Smuzhiyun enum phl_mdl_ret_code _phl_cmd_scan_req_acquired(
677*4882a593Smuzhiyun void* dispr, void* priv)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
680*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
681*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = param_to_phlcom(param);
682*4882a593Smuzhiyun void *d = phlcom_to_drvpriv(phl_com);
683*4882a593Smuzhiyun u32 diff_time = 0;
684*4882a593Smuzhiyun struct phl_info_t *phl_info = phl_com->phl_priv;
685*4882a593Smuzhiyun u8 idx = 0xff;
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun struct phl_msg msg = {0};
688*4882a593Smuzhiyun struct phl_msg_attribute attr = {0};
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun FUNCIN();
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun param->start_time = _os_get_cur_time_ms();
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun /* check max scan time */
695*4882a593Smuzhiyun if (param->max_scan_time > 0) {
696*4882a593Smuzhiyun diff_time = phl_get_passing_time_ms(param->enqueue_time);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (diff_time >= param->max_scan_time) {
699*4882a593Smuzhiyun PHL_WARN("%s:: Timeout! %u > max_time %d\n",
700*4882a593Smuzhiyun __func__, diff_time, param->max_scan_time);
701*4882a593Smuzhiyun goto error;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun _os_init_timer(d, ¶m->scan_timer, _cmd_scan_timer,
706*4882a593Smuzhiyun param->wifi_role, "phl_cmd_scan_req_timer");
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_SCAN);
709*4882a593Smuzhiyun SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SCAN_START);
710*4882a593Smuzhiyun msg.rsvd[0] = (u8*)param->wifi_role;
711*4882a593Smuzhiyun phl_dispr_get_idx(dispr, &idx);
712*4882a593Smuzhiyun msg.band_idx = idx;
713*4882a593Smuzhiyun pstatus = phl_disp_eng_send_msg(phl_info, &msg, &attr, NULL);
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun if(pstatus != RTW_PHL_STATUS_SUCCESS) {
716*4882a593Smuzhiyun _os_release_timer(d, ¶m->scan_timer);
717*4882a593Smuzhiyun goto error;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun else {
720*4882a593Smuzhiyun SET_STATUS_FLAG(param->state, CMD_SCAN_ACQUIRE);
721*4882a593Smuzhiyun return MDL_RET_SUCCESS;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun error:
725*4882a593Smuzhiyun _cmd_abort_notify(dispr, d, param, false);
726*4882a593Smuzhiyun return MDL_RET_FAIL;
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun
_phl_cmd_scan_req_abort(void * dispr,void * priv)729*4882a593Smuzhiyun enum phl_mdl_ret_code _phl_cmd_scan_req_abort(
730*4882a593Smuzhiyun void* dispr, void* priv)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
733*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = param_to_phlcom(param);
734*4882a593Smuzhiyun void *d = phlcom_to_drvpriv(phl_com);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun PHL_INFO("_phl_cmd_scan_req_abort \n");
737*4882a593Smuzhiyun _cmd_abort_notify(dispr, d, param, true);
738*4882a593Smuzhiyun return MDL_RET_SUCCESS;
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
_phl_cmd_scan_req_ev_hdlr(void * dispr,void * priv,struct phl_msg * msg)741*4882a593Smuzhiyun enum phl_mdl_ret_code _phl_cmd_scan_req_ev_hdlr(
742*4882a593Smuzhiyun void* dispr, void* priv,
743*4882a593Smuzhiyun struct phl_msg* msg)
744*4882a593Smuzhiyun {
745*4882a593Smuzhiyun enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun if(IS_MSG_FAIL(msg->msg_id)) {
748*4882a593Smuzhiyun PHL_INFO("%s :: MSG(%d)_FAIL - EVT_ID=%d \n", __func__,
749*4882a593Smuzhiyun MSG_MDL_ID_FIELD(msg->msg_id), MSG_EVT_ID_FIELD(msg->msg_id));
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun _cmd_scan_fail_ev_hdlr(dispr, priv, msg);
752*4882a593Smuzhiyun return MDL_RET_FAIL;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun switch(MSG_MDL_ID_FIELD(msg->msg_id)) {
756*4882a593Smuzhiyun case PHL_FG_MDL_SCAN:
757*4882a593Smuzhiyun ret = _cmd_scan_hdl_internal_evt(dispr, priv, msg);
758*4882a593Smuzhiyun break;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun default:
761*4882a593Smuzhiyun ret = _cmd_scan_hdl_external_evt(dispr, priv, msg);
762*4882a593Smuzhiyun break;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun return ret;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
_phl_cmd_scan_req_set_info(void * dispr,void * priv,struct phl_module_op_info * info)767*4882a593Smuzhiyun enum phl_mdl_ret_code _phl_cmd_scan_req_set_info(
768*4882a593Smuzhiyun void* dispr, void* priv, struct phl_module_op_info* info)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun #ifdef RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN
773*4882a593Smuzhiyun switch(info->op_code) {
774*4882a593Smuzhiyun case FG_REQ_OP_NOTIFY_BCN_RCV:
775*4882a593Smuzhiyun {
776*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
777*4882a593Smuzhiyun u16 channel = 0;
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun /* this workaround might have race condition with background thread*/
780*4882a593Smuzhiyun channel = *(u8*)info->inbuf;
781*4882a593Smuzhiyun if (param->scan_ch &&
782*4882a593Smuzhiyun param->scan_ch->channel == channel &&
783*4882a593Smuzhiyun param->scan_ch->ext_act_scan == EXT_ACT_SCAN_ENABLE) {
784*4882a593Smuzhiyun param->scan_ch->ext_act_scan = EXT_ACT_SCAN_TRIGGER;
785*4882a593Smuzhiyun PHL_INFO(" %s :: channel %d extend for active scan\n", __func__, channel);
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun if (param->scan_ch &&
788*4882a593Smuzhiyun param->scan_ch->channel != channel)
789*4882a593Smuzhiyun PHL_INFO(" %s :: channel %d mismatch from listen channel %d\n", __func__, channel, param->scan_ch->channel);
790*4882a593Smuzhiyun ret = MDL_RET_SUCCESS;
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun break;
793*4882a593Smuzhiyun default:
794*4882a593Smuzhiyun break;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun #endif
797*4882a593Smuzhiyun /* PHL_INFO(" %s :: info->op_code=%d \n", __func__, info->op_code); */
798*4882a593Smuzhiyun return ret;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
_phl_cmd_scan_req_query_info(void * dispr,void * priv,struct phl_module_op_info * info)801*4882a593Smuzhiyun enum phl_mdl_ret_code _phl_cmd_scan_req_query_info(
802*4882a593Smuzhiyun void* dispr, void* priv, struct phl_module_op_info* info)
803*4882a593Smuzhiyun {
804*4882a593Smuzhiyun struct rtw_phl_scan_param *param = (struct rtw_phl_scan_param*)priv;
805*4882a593Smuzhiyun struct rtw_phl_com_t *phl_com = param_to_phlcom(param);
806*4882a593Smuzhiyun void *d = phlcom_to_drvpriv(phl_com);
807*4882a593Smuzhiyun u8 ucInfo = 0;
808*4882a593Smuzhiyun void* pInfo = NULL;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
811*4882a593Smuzhiyun /* PHL_INFO(" %s :: info->op_code=%d \n", __func__, info->op_code); */
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun switch(info->op_code) {
814*4882a593Smuzhiyun case FG_REQ_OP_GET_ROLE:
815*4882a593Smuzhiyun info->outbuf = (u8*)param->wifi_role;
816*4882a593Smuzhiyun ret = MDL_RET_SUCCESS;
817*4882a593Smuzhiyun break;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun case FG_REQ_OP_GET_MDL_ID:
820*4882a593Smuzhiyun ucInfo= PHL_FG_MDL_SCAN;
821*4882a593Smuzhiyun pInfo = (void*) &ucInfo;
822*4882a593Smuzhiyun info->outlen=1;
823*4882a593Smuzhiyun _os_mem_cpy(d, (void*)info->outbuf, pInfo, info->outlen);
824*4882a593Smuzhiyun ret = MDL_RET_SUCCESS;
825*4882a593Smuzhiyun break;
826*4882a593Smuzhiyun #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
827*4882a593Smuzhiyun case FG_REQ_OP_GET_SCAN_PARAM:
828*4882a593Smuzhiyun info->outbuf = (u8*)param;
829*4882a593Smuzhiyun ret = MDL_RET_SUCCESS;
830*4882a593Smuzhiyun break;
831*4882a593Smuzhiyun #endif
832*4882a593Smuzhiyun default:
833*4882a593Smuzhiyun break;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun return ret;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN_BKOP_TIME
840*4882a593Smuzhiyun static void
_cmd_scan_update_chparam(void * drv,struct rtw_phl_scan_param * param)841*4882a593Smuzhiyun _cmd_scan_update_chparam(void *drv, struct rtw_phl_scan_param *param)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun u8 idx = 0;
844*4882a593Smuzhiyun u16 scan_section_ms = 0;
845*4882a593Smuzhiyun u16 total_scan_ms = 0;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun for(idx = 0; idx < param->ch_num; idx++) {
848*4882a593Smuzhiyun if (param->ch[idx].scan_mode == P2P_LISTEN_MODE) {
849*4882a593Smuzhiyun param->max_listen_time = param->ch[idx].duration;
850*4882a593Smuzhiyun total_scan_ms = param->ch[idx].duration;
851*4882a593Smuzhiyun break;
852*4882a593Smuzhiyun }
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun scan_section_ms = param->back_op_ch_dur_ms + param->back_op_off_ch_dur_ms;
856*4882a593Smuzhiyun if (scan_section_ms)
857*4882a593Smuzhiyun param->repeat = total_scan_ms / scan_section_ms;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun #endif
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun static void
_phl_cmd_scan_req_init(void * phl,struct phl_cmd_token_req * fgreq,struct rtw_phl_scan_param * param)862*4882a593Smuzhiyun _phl_cmd_scan_req_init(void *phl, struct phl_cmd_token_req *fgreq,
863*4882a593Smuzhiyun struct rtw_phl_scan_param *param)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
866*4882a593Smuzhiyun void *drv = phl_to_drvpriv(phl_info);
867*4882a593Smuzhiyun struct rtw_chan_def chdef_list[MAX_WIFI_ROLE_NUMBER] = {0};
868*4882a593Smuzhiyun u8 op_num = 0;
869*4882a593Smuzhiyun u8 idx = 0;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun pq_init(drv, ¶m->chlist);
872*4882a593Smuzhiyun param->enqueue_time = _os_get_cur_time_ms();
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun _cmd_scan_update_chlist(drv, param);
875*4882a593Smuzhiyun if (param->back_op_mode != SCAN_BKOP_NONE) {
876*4882a593Smuzhiyun op_num = rtw_phl_mr_get_opch_list(phl_info, param->wifi_role,
877*4882a593Smuzhiyun chdef_list, (u8)MAX_WIFI_ROLE_NUMBER);
878*4882a593Smuzhiyun if(op_num) {
879*4882a593Smuzhiyun for(idx = 0; idx < op_num; idx++) {
880*4882a593Smuzhiyun if(chdef_list[idx].chan) {
881*4882a593Smuzhiyun INIT_LIST_HEAD(¶m->back_op_ch[idx].list);
882*4882a593Smuzhiyun param->back_op_ch[idx].channel = chdef_list[idx].chan;
883*4882a593Smuzhiyun param->back_op_ch[idx].bw = chdef_list[idx].bw;
884*4882a593Smuzhiyun param->back_op_ch[idx].offset = chdef_list[idx].offset;
885*4882a593Smuzhiyun param->back_op_ch[idx].duration = param->back_op_ch_dur_ms;
886*4882a593Smuzhiyun param->back_op_ch[idx].scan_mode = BACKOP_MODE;
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun }
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun #ifdef CONFIG_PHL_CMD_SCAN_BKOP_TIME
891*4882a593Smuzhiyun if (op_num && param->back_op_mode == SCAN_BKOP_TIMER)
892*4882a593Smuzhiyun _cmd_scan_update_chparam(drv, param);
893*4882a593Smuzhiyun #endif
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun #ifdef DBG_SCAN_CHAN_DUMP
897*4882a593Smuzhiyun /* debug information*/
898*4882a593Smuzhiyun _cmd_estimated_swch_seq(param, op_num);
899*4882a593Smuzhiyun #endif
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun /* Fill foreground command request */
902*4882a593Smuzhiyun fgreq->module_id= PHL_FG_MDL_SCAN;
903*4882a593Smuzhiyun fgreq->priv = param;
904*4882a593Smuzhiyun fgreq->role = param->wifi_role;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun fgreq->acquired = _phl_cmd_scan_req_acquired;
907*4882a593Smuzhiyun fgreq->abort = _phl_cmd_scan_req_abort;
908*4882a593Smuzhiyun fgreq->msg_hdlr = _phl_cmd_scan_req_ev_hdlr;
909*4882a593Smuzhiyun fgreq->set_info = _phl_cmd_scan_req_set_info;
910*4882a593Smuzhiyun fgreq->query_info = _phl_cmd_scan_req_query_info;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun /* For EXTERNAL application to request scan (expose) */
915*4882a593Smuzhiyun /* @pscan: scan object
916*4882a593Smuzhiyun * @pbuf: scan parameter, will be freed by caller after retrun
917*4882a593Smuzhiyun * @order: queuing order
918*4882a593Smuzhiyun */
rtw_phl_cmd_scan_request(void * phl,struct rtw_phl_scan_param * param,enum PRECEDE order)919*4882a593Smuzhiyun enum rtw_phl_status rtw_phl_cmd_scan_request(void *phl,
920*4882a593Smuzhiyun struct rtw_phl_scan_param *param, enum PRECEDE order)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
923*4882a593Smuzhiyun u8 band_idx = param->wifi_role->hw_band;
924*4882a593Smuzhiyun struct phl_cmd_token_req fgreq={0};
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun _phl_cmd_scan_req_init(phl, &fgreq, param);
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun /* cmd_dispatcher would copy whole phl_cmd_token_req */
929*4882a593Smuzhiyun pstatus = phl_disp_eng_add_token_req(phl, band_idx, &fgreq, ¶m->token);
930*4882a593Smuzhiyun if((pstatus != RTW_PHL_STATUS_SUCCESS) &&
931*4882a593Smuzhiyun (pstatus != RTW_PHL_STATUS_PENDING))
932*4882a593Smuzhiyun goto error;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun pstatus = RTW_PHL_STATUS_SUCCESS;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun error:
937*4882a593Smuzhiyun return pstatus;
938*4882a593Smuzhiyun }
rtw_phl_cmd_scan_cancel(void * phl,struct rtw_phl_scan_param * param)939*4882a593Smuzhiyun enum rtw_phl_status rtw_phl_cmd_scan_cancel(void *phl,
940*4882a593Smuzhiyun struct rtw_phl_scan_param *param)
941*4882a593Smuzhiyun {
942*4882a593Smuzhiyun struct phl_info_t *phl_info = (struct phl_info_t *)phl;
943*4882a593Smuzhiyun u8 band_idx = param->wifi_role->hw_band;
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun return phl_disp_eng_cancel_token_req(phl_info, band_idx, ¶m->token);
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
rtw_phl_cmd_scan_inprogress(void * phl,u8 band_idx)948*4882a593Smuzhiyun int rtw_phl_cmd_scan_inprogress(void *phl, u8 band_idx)
949*4882a593Smuzhiyun {
950*4882a593Smuzhiyun struct phl_module_op_info op_info = {0};
951*4882a593Smuzhiyun u32 mdl = 0;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun op_info.op_code = FG_REQ_OP_GET_MDL_ID;
954*4882a593Smuzhiyun op_info.outbuf = (u8*)&mdl;
955*4882a593Smuzhiyun op_info.outlen = 4;
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if(phl_disp_eng_query_cur_cmd_info(phl, band_idx,
958*4882a593Smuzhiyun &op_info)== RTW_PHL_STATUS_SUCCESS ) {
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun if(mdl == PHL_FG_MDL_SCAN)
961*4882a593Smuzhiyun return true;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun return false;
964*4882a593Smuzhiyun }
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun #endif /* CONFIG_PHL_CMD_SCAN */
967