net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_msg_rx.c
1 /**
2  ****************************************************************************************
3  *
4  * @file ecrnx_msg_rx.c
5  *
6  * @brief RX function definitions
7  *
8  * Copyright (C) ESWIN 2015-2020
9  *
10  ****************************************************************************************
11  */
12 #include "ecrnx_defs.h"
13 #include "ecrnx_prof.h"
14 #include "ecrnx_tx.h"
15 #ifdef CONFIG_ECRNX_BFMER
16 #include "ecrnx_bfmer.h"
17 #endif //(CONFIG_ECRNX_BFMER)
18 #ifdef CONFIG_ECRNX_FULLMAC
19 #include "ecrnx_debugfs.h"
20 #include "ecrnx_msg_tx.h"
21 #include "ecrnx_tdls.h"
22 #endif /* CONFIG_ECRNX_FULLMAC */
23 #include "ecrnx_events.h"
24 #include "ecrnx_compat.h"
25 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
26 #include <linux/time.h>
27 #endif
28
29 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
30 #include "ecrnx_debugfs_func.h"
31 #endif
32 static int ecrnx_freq_to_idx(struct ecrnx_hw *ecrnx_hw, int freq)
33 {
34     struct ieee80211_supported_band *sband;
35     int band, ch, idx = 0;
36
37 #ifdef CONFIG_ECRNX_5G
38     for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
39 #else
40         for (band = NL80211_BAND_2GHZ; band <= NL80211_BAND_2GHZ; band++) {
41 #endif
42 #ifdef CONFIG_ECRNX_SOFTMAC
43         sband = ecrnx_hw->hw->wiphy->bands[band];
44 #else
45         sband = ecrnx_hw->wiphy->bands[band];
46 #endif /* CONFIG_ECRNX_SOFTMAC */
47         if (!sband) {
48             continue;
49         }
50
51         for (ch = 0; ch < sband->n_channels; ch++, idx++) {
52             if (sband->channels[ch].center_freq == freq) {
53                 goto exit;
54             }
55         }
56     }
57
58         ECRNX_ERR("--!!!!!!!!error freq-----%d\n", freq);
59     //BUG_ON(1);
60
61 exit:
62     // Channel has been found, return the index
63     return idx;
64 }
65
66 /***************************************************************************
67  * Messages from MM task
68  **************************************************************************/
69 static inline int ecrnx_rx_chan_pre_switch_ind(struct ecrnx_hw *ecrnx_hw,
70                                               struct ecrnx_cmd *cmd,
71                                               struct ipc_e2a_msg *msg)
72 {
73 #ifdef CONFIG_ECRNX_SOFTMAC
74     struct ecrnx_chanctx *chan_ctxt;
75 #endif
76     struct ecrnx_vif *ecrnx_vif;
77     int chan_idx = ((struct mm_channel_pre_switch_ind *)msg->param)->chan_index;
78
79     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
80
81     REG_SW_SET_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT);
82
83 #ifdef CONFIG_ECRNX_SOFTMAC
84     list_for_each_entry(chan_ctxt, &ecrnx_hw->chan_ctxts, list) {
85         if (chan_ctxt->index == chan_idx) {
86             chan_ctxt->active = false;
87             break;
88         }
89     }
90
91     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
92         if (ecrnx_vif->chanctx && (ecrnx_vif->chanctx->index == chan_idx)) {
93             ecrnx_txq_vif_stop(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
94         }
95     }
96 #else
97     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
98         if (ecrnx_vif->up && ecrnx_vif->ch_index == chan_idx) {
99             ecrnx_txq_vif_stop(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
100         }
101     }
102 #endif /* CONFIG_ECRNX_SOFTMAC */
103
104     REG_SW_CLEAR_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT);
105
106     return 0;
107 }
108
109 static inline int ecrnx_rx_chan_switch_ind(struct ecrnx_hw *ecrnx_hw,
110                                           struct ecrnx_cmd *cmd,
111                                           struct ipc_e2a_msg *msg)
112 {
113 #ifdef CONFIG_ECRNX_SOFTMAC
114     struct ecrnx_chanctx *chan_ctxt;
115     struct ecrnx_sta *ecrnx_sta;
116 #endif
117     struct ecrnx_vif *ecrnx_vif;
118     int chan_idx = ((struct mm_channel_switch_ind *)msg->param)->chan_index;
119     bool roc_req = ((struct mm_channel_switch_ind *)msg->param)->roc;
120     bool roc_tdls = ((struct mm_channel_switch_ind *)msg->param)->roc_tdls;
121
122     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
123
124     REG_SW_SET_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT);
125
126 #ifdef CONFIG_ECRNX_SOFTMAC
127     if (roc_tdls) {
128         u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index;
129         // Enable traffic only for TDLS station
130         list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
131             if (ecrnx_vif->vif_index == vif_index) {
132                 list_for_each_entry(ecrnx_sta, &ecrnx_vif->stations, list) {
133                     if (ecrnx_sta->tdls.active) {
134                         ecrnx_vif->roc_tdls = true;
135                         ecrnx_txq_tdls_sta_start(ecrnx_sta, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
136                         break;
137                     }
138                 }
139                 break;
140             }
141         }
142     } else if (!roc_req) {
143         list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
144             if (ecrnx_vif->chanctx && (ecrnx_vif->chanctx->index == chan_idx)) {
145                 ecrnx_txq_vif_start(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
146             }
147         }
148     } else {
149         u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index;
150
151         // Inform the host that the offchannel period has been started
152         ieee80211_ready_on_channel(ecrnx_hw->hw);
153
154         // Enable traffic for associated VIF (roc may happen without chanctx)
155         list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
156             if (ecrnx_vif->vif_index == vif_index) {
157                 ecrnx_txq_vif_start(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
158             }
159         }
160     }
161
162     /* keep cur_chan up to date */
163     list_for_each_entry(chan_ctxt, &ecrnx_hw->chan_ctxts, list) {
164         if (chan_ctxt->index == chan_idx) {
165             chan_ctxt->active = true;
166             ecrnx_hw->cur_freq = chan_ctxt->ctx->def.center_freq1;
167             ecrnx_hw->cur_band = chan_ctxt->ctx->def.chan->band;
168             if (chan_ctxt->ctx->def.chan->flags & IEEE80211_CHAN_RADAR) {
169                 ecrnx_radar_detection_enable(&ecrnx_hw->radar,
170                                             ECRNX_RADAR_DETECT_REPORT,
171                                             ECRNX_RADAR_RIU);
172             } else {
173                 ecrnx_radar_detection_enable(&ecrnx_hw->radar,
174                                             ECRNX_RADAR_DETECT_DISABLE,
175                                             ECRNX_RADAR_RIU);
176             }
177             break;
178         }
179     }
180
181 #else
182     if (roc_tdls) {
183         u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index;
184         list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
185             if (ecrnx_vif->vif_index == vif_index) {
186                 ecrnx_vif->roc_tdls = true;
187                 ecrnx_txq_tdls_sta_start(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
188             }
189         }
190     } else if (!roc_req) {
191         list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
192             if (ecrnx_vif->up && ecrnx_vif->ch_index == chan_idx) {
193                 ecrnx_txq_vif_start(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
194             }
195         }
196     } else {
197         /* Retrieve the allocated RoC element */
198         struct ecrnx_roc *roc = ecrnx_hw->roc;
199
200         if (roc && roc->vif) {
201             /* Get VIF on which RoC has been started */
202             ecrnx_vif = roc->vif;
203             /* For debug purpose (use ftrace kernel option) */
204             trace_switch_roc(ecrnx_vif->vif_index);
205
206             if (!roc->internal) {
207             /* If mgmt_roc is true, remain on channel has been started by ourself */
208                 /* Inform the host that we have switch on the indicated off-channel */
209                 cfg80211_ready_on_channel(&ecrnx_vif->wdev, (u64)(ecrnx_hw->roc_cookie),
210                                           roc->chan, roc->duration, GFP_ATOMIC);
211             }
212
213             /* Keep in mind that we have switched on the channel */
214             roc->on_chan = true;
215         }
216
217         // Enable traffic on OFF channel queue
218         ecrnx_txq_offchan_start(ecrnx_hw);
219 #if defined(CONFIG_ECRNX_P2P)
220     if (roc && roc->internal) {
221         ecrnx_hw->p2p_listen.rxdatas = 1;
222         wake_up(&ecrnx_hw->p2p_listen.rxdataq);
223     }
224 #endif
225     }
226
227     ecrnx_hw->cur_chanctx = chan_idx;
228     ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
229
230 #endif /* CONFIG_ECRNX_SOFTMAC */
231
232     REG_SW_CLEAR_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT);
233
234     return 0;
235 }
236
237 static inline int ecrnx_rx_tdls_chan_switch_cfm(struct ecrnx_hw *ecrnx_hw,
238                                                 struct ecrnx_cmd *cmd,
239                                                 struct ipc_e2a_msg *msg)
240 {
241     return 0;
242 }
243
244 static inline int ecrnx_rx_tdls_chan_switch_ind(struct ecrnx_hw *ecrnx_hw,
245                                                struct ecrnx_cmd *cmd,
246                                                struct ipc_e2a_msg *msg)
247 {
248 #ifdef CONFIG_ECRNX_SOFTMAC
249     struct ecrnx_chanctx *chan_ctxt;
250     u8 chan_idx = ((struct tdls_chan_switch_ind *)msg->param)->chan_ctxt_index;
251
252     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
253
254     // Enable channel context
255     list_for_each_entry(chan_ctxt, &ecrnx_hw->chan_ctxts, list) {
256         if (chan_ctxt->index == chan_idx) {
257             chan_ctxt->active = true;
258             ecrnx_hw->cur_freq = chan_ctxt->ctx->def.center_freq1;
259             ecrnx_hw->cur_band = chan_ctxt->ctx->def.chan->band;
260         }
261     }
262
263     return 0;
264 #else
265     // Enable traffic on OFF channel queue
266     ecrnx_txq_offchan_start(ecrnx_hw);
267
268     return 0;
269 #endif
270 }
271
272 static inline int ecrnx_rx_tdls_chan_switch_base_ind(struct ecrnx_hw *ecrnx_hw,
273                                                     struct ecrnx_cmd *cmd,
274                                                     struct ipc_e2a_msg *msg)
275 {
276     struct ecrnx_vif *ecrnx_vif;
277     u8 vif_index = ((struct tdls_chan_switch_base_ind *)msg->param)->vif_index;
278 #ifdef CONFIG_ECRNX_SOFTMAC
279     struct ecrnx_sta *ecrnx_sta;
280 #endif
281
282     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
283
284 #ifdef CONFIG_ECRNX_SOFTMAC
285     // Disable traffic for associated VIF
286     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
287         if (ecrnx_vif->vif_index == vif_index) {
288             if (ecrnx_vif->chanctx)
289                 ecrnx_vif->chanctx->active = false;
290             list_for_each_entry(ecrnx_sta, &ecrnx_vif->stations, list) {
291                 if (ecrnx_sta->tdls.active) {
292                     ecrnx_vif->roc_tdls = false;
293                     ecrnx_txq_tdls_sta_stop(ecrnx_sta, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
294                     break;
295                 }
296             }
297             break;
298         }
299     }
300     return 0;
301 #else
302     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
303         if (ecrnx_vif->vif_index == vif_index) {
304             ecrnx_vif->roc_tdls = false;
305             ecrnx_txq_tdls_sta_stop(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
306         }
307     }
308     return 0;
309 #endif
310 }
311
312 static inline int ecrnx_rx_tdls_peer_ps_ind(struct ecrnx_hw *ecrnx_hw,
313                                            struct ecrnx_cmd *cmd,
314                                            struct ipc_e2a_msg *msg)
315 {
316     struct ecrnx_vif *ecrnx_vif;
317     u8 vif_index = ((struct tdls_peer_ps_ind *)msg->param)->vif_index;
318     bool ps_on = ((struct tdls_peer_ps_ind *)msg->param)->ps_on;
319
320 #ifdef CONFIG_ECRNX_SOFTMAC
321     u8 sta_idx = ((struct tdls_peer_ps_ind *)msg->param)->sta_idx;
322     struct ecrnx_sta *ecrnx_sta;
323     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
324         if (ecrnx_vif->vif_index == vif_index) {
325             list_for_each_entry(ecrnx_sta, &ecrnx_vif->stations, list) {
326                 if (ecrnx_sta->sta_idx == sta_idx) {
327                     ecrnx_sta->tdls.ps_on = ps_on;
328                     if (ps_on) {
329                         // disable TXQ for TDLS peer
330                         ecrnx_txq_tdls_sta_stop(ecrnx_sta, ECRNX_TXQ_STOP_STA_PS, ecrnx_hw);
331                     } else {
332                         // Enable TXQ for TDLS peer
333                         ecrnx_txq_tdls_sta_start(ecrnx_sta, ECRNX_TXQ_STOP_STA_PS, ecrnx_hw);
334                     }
335                     break;
336                 }
337             }
338             break;
339         }
340     }
341     return 0;
342 #else
343     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
344         if (ecrnx_vif->vif_index == vif_index) {
345             ecrnx_vif->sta.tdls_sta->tdls.ps_on = ps_on;
346             // Update PS status for the TDLS station
347             ecrnx_ps_bh_enable(ecrnx_hw, ecrnx_vif->sta.tdls_sta, ps_on);
348         }
349     }
350
351     return 0;
352 #endif
353 }
354
355 static inline int ecrnx_rx_remain_on_channel_exp_ind(struct ecrnx_hw *ecrnx_hw,
356                                                     struct ecrnx_cmd *cmd,
357                                                     struct ipc_e2a_msg *msg)
358 {
359 #ifdef CONFIG_ECRNX_SOFTMAC
360     struct ecrnx_vif *ecrnx_vif;
361     u8 vif_index = ((struct mm_remain_on_channel_exp_ind *)msg->param)->vif_index;
362
363     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
364
365     ieee80211_remain_on_channel_expired(ecrnx_hw->hw);
366
367     // Disable traffic for associated VIF
368     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
369         if (ecrnx_vif->vif_index == vif_index) {
370             if (ecrnx_vif->chanctx)
371                 ecrnx_vif->chanctx->active = false;
372
373             ecrnx_txq_vif_stop(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
374             break;
375         }
376     }
377
378     return 0;
379
380 #else
381     if(!ecrnx_hw->roc || !ecrnx_hw->roc->chan){
382         ECRNX_ERR("error!!!:ecrnx_hw->roc or !ecrnx_hw->roc->chan is null \n");
383         return 0;
384     }
385     /* Retrieve the allocated RoC element */
386     struct ecrnx_roc *roc = ecrnx_hw->roc;
387     /* Get VIF on which RoC has been started */
388     struct ecrnx_vif *ecrnx_vif = roc->vif;
389
390     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
391
392     /* For debug purpose (use ftrace kernel option) */
393     trace_roc_exp(ecrnx_vif->vif_index);
394
395     /* If mgmt_roc is true, remain on channel has been started by ourself */
396     /* If RoC has been cancelled before we switched on channel, do not call cfg80211 */
397     if (!roc->internal && roc->on_chan) {
398         /* Inform the host that off-channel period has expired */
399         cfg80211_remain_on_channel_expired(&ecrnx_vif->wdev, (u64)(ecrnx_hw->roc_cookie),
400                                            roc->chan, GFP_ATOMIC);
401     }
402
403     /* De-init offchannel TX queue */
404     ecrnx_txq_offchan_deinit(ecrnx_vif);
405
406     /* Increase the cookie counter cannot be zero */
407     ecrnx_hw->roc_cookie++;
408
409     if (ecrnx_hw->roc_cookie == 0)
410         ecrnx_hw->roc_cookie = 1;
411
412 #if CONFIG_ECRNX_P2P
413         ecrnx_hw->p2p_listen.listen_started = 0;
414 #endif
415
416     /* Free the allocated RoC element */
417     kfree(roc);
418     ecrnx_hw->roc = NULL;
419     
420 #if defined(CONFIG_ECRNX_P2P)
421         wake_up(&ecrnx_hw->p2p_listen.rxdataq);
422 #endif
423
424 #endif /* CONFIG_ECRNX_SOFTMAC */
425     return 0;
426 }
427
428 static inline int ecrnx_rx_p2p_vif_ps_change_ind(struct ecrnx_hw *ecrnx_hw,
429                                                 struct ecrnx_cmd *cmd,
430                                                 struct ipc_e2a_msg *msg)
431 {
432     int vif_idx  = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->vif_index;
433     int ps_state = ((struct mm_p2p_vif_ps_change_ind *)msg->param)->ps_state;
434     struct ecrnx_vif *vif_entry;
435
436     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
437
438 #ifdef CONFIG_ECRNX_SOFTMAC
439     // Look for VIF entry
440     list_for_each_entry(vif_entry, &ecrnx_hw->vifs, list) {
441         if (vif_entry->vif_index == vif_idx) {
442             goto found_vif;
443         }
444     }
445 #else
446     vif_entry = ecrnx_hw->vif_table[vif_idx];
447
448     if (vif_entry) {
449         goto found_vif;
450     }
451 #endif /* CONFIG_ECRNX_SOFTMAC */
452
453     goto exit;
454
455 found_vif:
456
457 #ifdef CONFIG_ECRNX_SOFTMAC
458     if (ps_state == MM_PS_MODE_OFF) {
459         ecrnx_txq_vif_start(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
460     }
461     else {
462         ecrnx_txq_vif_stop(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
463     }
464 #else
465     if (ps_state == MM_PS_MODE_OFF) {
466         // Start TX queues for provided VIF
467         ecrnx_txq_vif_start(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
468     }
469     else {
470         // Stop TX queues for provided VIF
471         ecrnx_txq_vif_stop(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
472     }
473 #endif /* CONFIG_ECRNX_SOFTMAC */
474
475 exit:
476     return 0;
477 }
478
479 static inline int ecrnx_rx_channel_survey_ind(struct ecrnx_hw *ecrnx_hw,
480                                              struct ecrnx_cmd *cmd,
481                                              struct ipc_e2a_msg *msg)
482 {
483     struct mm_channel_survey_ind *ind = (struct mm_channel_survey_ind *)msg->param;
484     // Get the channel index
485     int idx = ecrnx_freq_to_idx(ecrnx_hw, ind->freq);
486     // Get the survey
487     struct ecrnx_survey_info *ecrnx_survey;
488
489     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
490
491     if (idx >  ARRAY_SIZE(ecrnx_hw->survey))
492         return 0;
493
494     ecrnx_survey = &ecrnx_hw->survey[idx];
495
496     // Store the received parameters
497     ecrnx_survey->chan_time_ms = ind->chan_time_ms;
498     ecrnx_survey->chan_time_busy_ms = ind->chan_time_busy_ms;
499     ecrnx_survey->noise_dbm = ind->noise_dbm;
500     ecrnx_survey->filled = (SURVEY_INFO_TIME |
501                            SURVEY_INFO_TIME_BUSY);
502
503     if (ind->noise_dbm != 0) {
504         ecrnx_survey->filled |= SURVEY_INFO_NOISE_DBM;
505     }
506
507 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
508         ecrnx_debugfs_noise_of_survey_info_update(ecrnx_hw, ecrnx_survey, idx);
509 #endif
510
511     return 0;
512 }
513
514 static inline int ecrnx_rx_p2p_noa_upd_ind(struct ecrnx_hw *ecrnx_hw,
515                                           struct ecrnx_cmd *cmd,
516                                           struct ipc_e2a_msg *msg)
517 {
518     return 0;
519 }
520
521 static inline int ecrnx_rx_rssi_status_ind(struct ecrnx_hw *ecrnx_hw,
522                                           struct ecrnx_cmd *cmd,
523                                           struct ipc_e2a_msg *msg)
524 {
525     struct mm_rssi_status_ind *ind = (struct mm_rssi_status_ind *)msg->param;
526     int vif_idx  = ind->vif_index;
527     bool rssi_status = ind->rssi_status;
528
529     struct ecrnx_vif *vif_entry;
530
531     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
532
533 #ifdef CONFIG_ECRNX_SOFTMAC
534     list_for_each_entry(vif_entry, &ecrnx_hw->vifs, list) {
535         if (vif_entry->vif_index == vif_idx) {
536             ecrnx_ieee80211_cqm_rssi_notify(vif_entry->vif,
537                                       rssi_status ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
538                                                     NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
539                                       ind->rssi, GFP_ATOMIC);
540         }
541     }
542 #else
543     vif_entry = ecrnx_hw->vif_table[vif_idx];
544     if (vif_entry) {
545         ecrnx_cfg80211_cqm_rssi_notify(vif_entry->ndev,
546                                  rssi_status ? NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW :
547                                                NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
548                                  ind->rssi, GFP_ATOMIC);
549     }
550 #endif /* CONFIG_ECRNX_SOFTMAC */
551
552     return 0;
553 }
554
555 static inline int ecrnx_rx_pktloss_notify_ind(struct ecrnx_hw *ecrnx_hw,
556                                              struct ecrnx_cmd *cmd,
557                                              struct ipc_e2a_msg *msg)
558 {
559 #ifdef CONFIG_ECRNX_FULLMAC
560     struct mm_pktloss_ind *ind = (struct mm_pktloss_ind *)msg->param;
561     struct ecrnx_vif *vif_entry;
562     int vif_idx  = ind->vif_index;
563
564     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
565
566     vif_entry = ecrnx_hw->vif_table[vif_idx];
567     if (vif_entry) {
568         cfg80211_cqm_pktloss_notify(vif_entry->ndev, (const u8 *)ind->mac_addr.array,
569                                     ind->num_packets, GFP_ATOMIC);
570     }
571 #endif /* CONFIG_ECRNX_FULLMAC */
572
573     return 0;
574 }
575
576 static inline int ecrnx_rx_csa_counter_ind(struct ecrnx_hw *ecrnx_hw,
577                                           struct ecrnx_cmd *cmd,
578                                           struct ipc_e2a_msg *msg)
579 {
580     struct mm_csa_counter_ind *ind = (struct mm_csa_counter_ind *)msg->param;
581     struct ecrnx_vif *vif;
582     bool found = false;
583
584     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
585
586     // Look for VIF entry
587     list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
588         if (vif->vif_index == ind->vif_index) {
589             found=true;
590             break;
591         }
592     }
593
594     if (found) {
595 #ifdef CONFIG_ECRNX_SOFTMAC
596         if (ind->csa_count == 1)
597             ieee80211_csa_finish(vif->vif);
598         else
599             ieee80211_csa_update_counter(vif->vif);
600 #else
601         if (vif->ap.csa)
602             vif->ap.csa->count = ind->csa_count;
603         else
604             netdev_err(vif->ndev, "CSA counter update but no active CSA");
605
606 #endif
607     }
608
609     return 0;
610 }
611
612 #ifdef CONFIG_ECRNX_SOFTMAC
613 static inline int ecrnx_rx_connection_loss_ind(struct ecrnx_hw *ecrnx_hw,
614                                               struct ecrnx_cmd *cmd,
615                                               struct ipc_e2a_msg *msg)
616 {
617     struct ecrnx_vif *ecrnx_vif;
618     u8 inst_nbr;
619
620     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
621
622     inst_nbr = ((struct mm_connection_loss_ind *)msg->param)->inst_nbr;
623
624     /* Search the VIF entry corresponding to the instance number */
625     list_for_each_entry(ecrnx_vif, &ecrnx_hw->vifs, list) {
626         if (ecrnx_vif->vif_index == inst_nbr) {
627             ieee80211_connection_loss(ecrnx_vif->vif);
628             break;
629         }
630     }
631
632     return 0;
633 }
634
635
636 #ifdef CONFIG_ECRNX_BCN
637 static inline int ecrnx_rx_prm_tbtt_ind(struct ecrnx_hw *ecrnx_hw,
638                                        struct ecrnx_cmd *cmd,
639                                        struct ipc_e2a_msg *msg)
640 {
641     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
642
643     ecrnx_tx_bcns(ecrnx_hw);
644
645     return 0;
646 }
647 #endif
648
649 #else /* !CONFIG_ECRNX_SOFTMAC */
650 static inline int ecrnx_rx_csa_finish_ind(struct ecrnx_hw *ecrnx_hw,
651                                          struct ecrnx_cmd *cmd,
652                                          struct ipc_e2a_msg *msg)
653 {
654     struct mm_csa_finish_ind *ind = (struct mm_csa_finish_ind *)msg->param;
655     struct ecrnx_vif *vif;
656     bool found = false;
657
658     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
659
660     // Look for VIF entry
661     list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
662         if (vif->vif_index == ind->vif_index) {
663             found=true;
664             break;
665         }
666     }
667
668     if (found) {
669         if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP ||
670             ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) {
671             if (vif->ap.csa) {
672                 vif->ap.csa->status = ind->status;
673                 vif->ap.csa->ch_idx = ind->chan_idx;
674                 schedule_work(&vif->ap.csa->work);
675             } else
676                 netdev_err(vif->ndev, "CSA finish indication but no active CSA");
677         } else {
678             if (ind->status == 0) {
679                 ecrnx_chanctx_unlink(vif);
680                 ecrnx_chanctx_link(vif, ind->chan_idx, NULL);
681                 if (ecrnx_hw->cur_chanctx == ind->chan_idx) {
682                     ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
683                     ecrnx_txq_vif_start(vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
684                 } else
685                     ecrnx_txq_vif_stop(vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
686             }
687         }
688     }
689
690     return 0;
691 }
692
693 static inline int ecrnx_rx_csa_traffic_ind(struct ecrnx_hw *ecrnx_hw,
694                                           struct ecrnx_cmd *cmd,
695                                           struct ipc_e2a_msg *msg)
696 {
697     struct mm_csa_traffic_ind *ind = (struct mm_csa_traffic_ind *)msg->param;
698     struct ecrnx_vif *vif;
699     bool found = false;
700
701     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
702
703     // Look for VIF entry
704     list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
705         if (vif->vif_index == ind->vif_index) {
706             found=true;
707             break;
708         }
709     }
710
711     if (found) {
712         if (ind->enable)
713             ecrnx_txq_vif_start(vif, ECRNX_TXQ_STOP_CSA, ecrnx_hw);
714         else
715             ecrnx_txq_vif_stop(vif, ECRNX_TXQ_STOP_CSA, ecrnx_hw);
716     }
717
718     return 0;
719 }
720
721 static inline int ecrnx_rx_ps_change_ind(struct ecrnx_hw *ecrnx_hw,
722                                         struct ecrnx_cmd *cmd,
723                                         struct ipc_e2a_msg *msg)
724 {
725     struct mm_ps_change_ind *ind = (struct mm_ps_change_ind *)msg->param;
726     struct ecrnx_sta *sta = &ecrnx_hw->sta_table[ind->sta_idx];
727
728     if (ind->sta_idx >= (NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX)) {
729         wiphy_err(ecrnx_hw->wiphy, "Invalid sta index reported by fw %d\n",
730                   ind->sta_idx);
731         return 1;
732     }
733
734     netdev_dbg(ecrnx_hw->vif_table[sta->vif_idx]->ndev,
735                "Sta %d, change PS mode to %s", sta->sta_idx,
736                ind->ps_state ? "ON" : "OFF");
737
738     ECRNX_DBG("Sta:0x%p, sta_idx:%d, sta->valid:%d, sta_mac:%pM, change PS mode to: %s \n",sta, sta->sta_idx, sta->valid, sta->mac_addr, ind->ps_state ? "ON" : "OFF");
739
740     if (sta->valid) {
741         ecrnx_ps_bh_enable(ecrnx_hw, sta, ind->ps_state);
742     } else if (test_bit(ECRNX_DEV_ADDING_STA, &ecrnx_hw->flags)) {
743         sta->ps.active = ind->ps_state ? true : false;
744     } else {
745         netdev_err(ecrnx_hw->vif_table[sta->vif_idx]->ndev,
746                    "Ignore PS mode change on invalid sta\n");
747     }
748
749     return 0;
750 }
751
752
753 static inline int ecrnx_rx_traffic_req_ind(struct ecrnx_hw *ecrnx_hw,
754                                           struct ecrnx_cmd *cmd,
755                                           struct ipc_e2a_msg *msg)
756 {
757     struct mm_traffic_req_ind *ind = (struct mm_traffic_req_ind *)msg->param;
758     struct ecrnx_sta *sta = &ecrnx_hw->sta_table[ind->sta_idx];
759
760     ECRNX_DBG("%s-%d:Sta:0x%p, sta_idx:%d, sta->valid:%d, sta_mac:%pM \n",__func__, __LINE__, sta, ind->sta_idx, sta->valid, sta->mac_addr);
761
762     netdev_dbg(ecrnx_hw->vif_table[sta->vif_idx]->ndev,
763                "Sta %d, asked for %d pkt", sta->sta_idx, ind->pkt_cnt);
764
765     ecrnx_ps_bh_traffic_req(ecrnx_hw, sta, ind->pkt_cnt,
766                            ind->uapsd ? UAPSD_ID : LEGACY_PS_ID);
767
768     return 0;
769 }
770 #endif /* CONFIG_ECRNX_SOFTMAC */
771
772 /***************************************************************************
773  * Messages from SCAN task
774  **************************************************************************/
775 #ifdef CONFIG_ECRNX_SOFTMAC
776 static inline int ecrnx_rx_scan_done_ind(struct ecrnx_hw *ecrnx_hw,
777                                         struct ecrnx_cmd *cmd,
778                                         struct ipc_e2a_msg *msg)
779 {
780 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
781     struct cfg80211_scan_info info = {
782         .aborted = false,
783     };
784 #endif
785     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
786
787     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &ecrnx_hw->scan_ie);
788 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
789     ieee80211_scan_completed(ecrnx_hw->hw, &info);
790 #else
791     ieee80211_scan_completed(ecrnx_hw->hw, false);
792 #endif
793
794     return 0;
795 }
796 #endif /* CONFIG_ECRNX_SOFTMAC */
797
798 /***************************************************************************
799  * Messages from SCANU task
800  **************************************************************************/
801 #ifdef CONFIG_ECRNX_FULLMAC
802 static inline int ecrnx_scanu_cancel_cfm(struct ecrnx_hw *ecrnx_hw,
803                                            struct ecrnx_cmd *cmd,
804                                            struct ipc_e2a_msg *msg)
805 {
806     struct scanu_cancel_cfm *cfm = (struct scanu_cancel_cfm *)msg;
807     bool abort = false;
808
809 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
810     struct cfg80211_scan_info info = {
811         .aborted = abort,
812     };
813 #endif
814
815     ECRNX_PRINT("%s: cfm status:%d, scan_request:0x%p \n", __func__, cfm->status, ecrnx_hw->scan_request);
816
817 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
818     cfg80211_scan_done(ecrnx_hw->scan_request, &info);
819 #else
820     cfg80211_scan_done(ecrnx_hw->scan_request, false);
821 #endif
822     ecrnx_hw->scan_request = NULL;
823
824     return 0;
825 }
826
827 static inline int ecrnx_rx_scanu_start_cfm(struct ecrnx_hw *ecrnx_hw,
828                                           struct ecrnx_cmd *cmd,
829                                           struct ipc_e2a_msg *msg)
830 {
831     struct scanu_start_cfm* cfm = (struct scanu_start_cfm*)msg->param;
832     u8_l abort_status;
833     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
834     ECRNX_DBG("receive scanu cfm, status:%d \n", cfm->status);
835     abort_status = cfm->status?true:false;
836
837 #ifndef CONFIG_ECRNX_ESWIN
838     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &ecrnx_hw->scan_ie);
839 #endif
840
841     spin_lock_bh(&ecrnx_hw->scan_req_lock);
842     if (ecrnx_hw->scan_request) {
843 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
844         struct cfg80211_scan_info info = {
845             .aborted = abort_status,
846         };
847
848         ECRNX_PRINT("%s: cfm status:%d, scan_request:0x%p \n", __func__, cfm->status, ecrnx_hw->scan_request);
849         cfg80211_scan_done(ecrnx_hw->scan_request, &info);
850 #else
851         cfg80211_scan_done(ecrnx_hw->scan_request, abort_status);
852 #endif
853     }
854
855     ecrnx_hw->scan_request = NULL;
856     spin_unlock_bh(&ecrnx_hw->scan_req_lock);
857
858     return 0;
859 }
860
861 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
862 u64_l getBootTime(void)
863 {
864         struct timespec64 ts;
865         u64_l bootTime = 0;
866
867         ts = ktime_to_timespec64(ktime_get_boottime());
868         bootTime = ts.tv_sec;
869         bootTime *= 1000000;
870         bootTime += ts.tv_nsec / 1000;
871         return bootTime;
872 }
873 #endif
874 static inline int ecrnx_rx_scanu_result_ind(struct ecrnx_hw *ecrnx_hw,
875                                            struct ecrnx_cmd *cmd,
876                                            struct ipc_e2a_msg *msg)
877 {
878     struct cfg80211_bss *bss = NULL;
879     struct ieee80211_channel *chan;
880     struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param;
881     struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload;
882     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
883
884     chan = ieee80211_get_channel(ecrnx_hw->wiphy, ind->center_freq);
885
886     if (chan != NULL)
887     {
888 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
889         if(ieee80211_is_beacon(mgmt->frame_control))
890         {
891              mgmt->u.beacon.timestamp = getBootTime();
892         }
893         if(ieee80211_is_probe_resp(mgmt->frame_control))
894         {
895              mgmt->u.probe_resp.timestamp = getBootTime();
896         }
897 #endif
898         bss = cfg80211_inform_bss_frame(ecrnx_hw->wiphy, chan,
899                                         mgmt,
900                                         ind->length, ind->rssi * 100, GFP_ATOMIC);
901     }
902
903     if (bss != NULL)
904 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
905         cfg80211_put_bss(ecrnx_hw->wiphy, bss);
906 #else
907         cfg80211_put_bss(bss);
908 #endif
909
910 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
911         ecrnx_debugfs_survey_info_update(ecrnx_hw, bss);
912 #endif
913
914     return 0;
915 }
916 #endif /* CONFIG_ECRNX_FULLMAC */
917
918 /***************************************************************************
919  * Messages from ME task
920  **************************************************************************/
921 #ifdef CONFIG_ECRNX_FULLMAC
922 static inline int ecrnx_rx_me_tkip_mic_failure_ind(struct ecrnx_hw *ecrnx_hw,
923                                                   struct ecrnx_cmd *cmd,
924                                                   struct ipc_e2a_msg *msg)
925 {
926     struct me_tkip_mic_failure_ind *ind = (struct me_tkip_mic_failure_ind *)msg->param;
927     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
928     struct net_device *dev = ecrnx_vif->ndev;
929
930     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
931
932     cfg80211_michael_mic_failure(dev, (u8 *)&ind->addr, (ind->ga?NL80211_KEYTYPE_GROUP:
933                                  NL80211_KEYTYPE_PAIRWISE), ind->keyid,
934                                  (u8 *)&ind->tsc, GFP_ATOMIC);
935
936     return 0;
937 }
938
939 static inline int ecrnx_rx_me_tx_credits_update_ind(struct ecrnx_hw *ecrnx_hw,
940                                                    struct ecrnx_cmd *cmd,
941                                                    struct ipc_e2a_msg *msg)
942 {
943     struct me_tx_credits_update_ind *ind = (struct me_tx_credits_update_ind *)msg->param;
944
945     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
946
947     ecrnx_txq_credit_update(ecrnx_hw, ind->sta_idx, ind->tid, ind->credits);
948
949     return 0;
950 }
951 #endif /* CONFIG_ECRNX_FULLMAC */
952
953 /***************************************************************************
954  * Messages from SM task
955  **************************************************************************/
956 #ifdef CONFIG_ECRNX_FULLMAC
957 static inline int ecrnx_rx_sm_connect_ind(struct ecrnx_hw *ecrnx_hw,
958                                          struct ecrnx_cmd *cmd,
959                                          struct ipc_e2a_msg *msg)
960 {
961     struct sm_connect_ind *ind = (struct sm_connect_ind *)msg->param;
962     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
963     struct net_device *dev = ecrnx_vif->ndev;
964     const u8 *req_ie, *rsp_ie;
965     const u8 *extcap_ie;
966     const struct ieee_types_extcap *extcap;
967
968     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
969
970     spin_lock_bh(&ecrnx_hw->connect_req_lock);
971     /* Retrieve IE addresses and lengths */
972     req_ie = (const u8 *)ind->assoc_ie_buf;
973     rsp_ie = req_ie + ind->assoc_req_ie_len;
974
975     // Fill-in the AP information
976     if (ind->status_code == 0)
977     {
978         struct ecrnx_sta *sta = &ecrnx_hw->sta_table[ind->ap_idx];
979         u8 txq_status;
980         struct ieee80211_channel *chan;
981         struct cfg80211_chan_def chandef;
982
983         sta->valid = true;
984         memset(&sta->rx_pn, 0, TID_MAX * sizeof(uint64_t));
985         memset(&ecrnx_vif->rx_pn, 0, TID_MAX * sizeof(uint64_t));
986         sta->sta_idx = ind->ap_idx;
987         sta->ch_idx = ind->ch_idx;
988         sta->vif_idx = ind->vif_idx;
989         sta->vlan_idx = sta->vif_idx;
990         sta->qos = ind->qos;
991         sta->acm = ind->acm;
992         sta->ps.active = false;
993         sta->aid = ind->aid;
994         sta->band = ind->chan.band;
995         sta->width = ind->chan.type;
996         sta->center_freq = ind->chan.prim20_freq;
997         sta->center_freq1 = ind->chan.center1_freq;
998         sta->center_freq2 = ind->chan.center2_freq;
999         ecrnx_vif->sta.ap = sta;
1000         ecrnx_vif->generation++;
1001         chan = ieee80211_get_channel(ecrnx_hw->wiphy, ind->chan.prim20_freq);
1002         cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
1003         if (!ecrnx_hw->mod_params->ht_on)
1004             chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
1005         else
1006             chandef.width = chnl2bw[ind->chan.type];
1007         chandef.center_freq1 = ind->chan.center1_freq;
1008         chandef.center_freq2 = ind->chan.center2_freq;
1009         ecrnx_chanctx_link(ecrnx_vif, ind->ch_idx, &chandef);
1010         memcpy(sta->mac_addr, ind->bssid.array, ETH_ALEN);
1011         if (ind->ch_idx == ecrnx_hw->cur_chanctx) {
1012             txq_status = 0;
1013         } else {
1014             txq_status = ECRNX_TXQ_STOP_CHAN;
1015         }
1016         memcpy(sta->ac_param, ind->ac_param, sizeof(sta->ac_param));
1017         ecrnx_txq_sta_init(ecrnx_hw, sta, txq_status);
1018         ecrnx_rx_reord_sta_init(ecrnx_hw, ecrnx_hw->vif_table[sta->vif_idx], sta->sta_idx);
1019         ecrnx_dbgfs_register_sta(ecrnx_hw, sta);
1020         ECRNX_PRINT("ecrnx_rx_sm_connect_ind, mac[%02x:%02x:%02x:%02x:%02x:%02x], status_code:%d \n", \
1021                 sta->mac_addr[0], sta->mac_addr[1], sta->mac_addr[2], sta->mac_addr[3], sta->mac_addr[4], sta->mac_addr[5], ind->status_code);
1022         ecrnx_txq_tdls_vif_init(ecrnx_vif);
1023         ecrnx_mu_group_sta_init(sta, NULL);
1024         /* Look for TDLS Channel Switch Prohibited flag in the Extended Capability
1025          * Information Element*/
1026         extcap_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, rsp_ie, ind->assoc_rsp_ie_len);
1027         if (extcap_ie && extcap_ie[1] >= 5) {
1028             extcap = (void *)(extcap_ie);
1029             ecrnx_vif->tdls_chsw_prohibited = extcap->ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED;
1030         }
1031
1032 #ifdef CONFIG_ECRNX_BFMER
1033         /* If Beamformer feature is activated, check if features can be used
1034          * with the new peer device
1035          */
1036         if (ecrnx_hw->mod_params->bfmer) {
1037             const u8 *vht_capa_ie;
1038             const struct ieee80211_vht_cap *vht_cap;
1039
1040             do {
1041                 /* Look for VHT Capability Information Element */
1042                 vht_capa_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, rsp_ie,
1043                                                ind->assoc_rsp_ie_len);
1044
1045                 /* Stop here if peer device does not support VHT */
1046                 if (!vht_capa_ie) {
1047                     break;
1048                 }
1049
1050                 vht_cap = (const struct ieee80211_vht_cap *)(vht_capa_ie + 2);
1051
1052                 /* Send MM_BFMER_ENABLE_REQ message if needed */
1053                 ecrnx_send_bfmer_enable(ecrnx_hw, sta, vht_cap);
1054             } while (0);
1055         }
1056 #endif //(CONFIG_ECRNX_BFMER)
1057
1058 #ifdef CONFIG_ECRNX_MON_DATA
1059         // If there are 1 sta and 1 monitor interface active at the same time then
1060         // monitor interface channel context is always the same as the STA interface.
1061         // This doesn't work with 2 STA interfaces but we don't want to support it.
1062         if (ecrnx_hw->monitor_vif != ECRNX_INVALID_VIF) {
1063             struct ecrnx_vif *ecrnx_mon_vif = ecrnx_hw->vif_table[ecrnx_hw->monitor_vif];
1064             ecrnx_chanctx_unlink(ecrnx_mon_vif);
1065             ecrnx_chanctx_link(ecrnx_mon_vif, ind->ch_idx, NULL);
1066         }
1067 #endif
1068     }
1069
1070     if (ind->roamed) {
1071         struct cfg80211_roam_info info;
1072         memset(&info, 0, sizeof(info));
1073         if (ecrnx_vif->ch_index < NX_CHAN_CTXT_CNT)
1074             info.channel = ecrnx_hw->chanctx_table[ecrnx_vif->ch_index].chan_def.chan;
1075         info.bssid = (const u8 *)ind->bssid.array;
1076         info.req_ie = req_ie;
1077         info.req_ie_len = ind->assoc_req_ie_len;
1078         info.resp_ie = rsp_ie;
1079         info.resp_ie_len = ind->assoc_rsp_ie_len;
1080         cfg80211_roamed(dev, &info, GFP_ATOMIC);
1081     } else {
1082         cfg80211_connect_result(dev, (const u8 *)ind->bssid.array, req_ie,
1083                                 ind->assoc_req_ie_len, rsp_ie,
1084                                 ind->assoc_rsp_ie_len, ind->status_code,
1085                                 GFP_ATOMIC);
1086     }
1087
1088     netif_tx_start_all_queues(dev);
1089     netif_carrier_on(dev);
1090     spin_unlock_bh(&ecrnx_hw->connect_req_lock);
1091
1092     return 0;
1093 }
1094
1095 static inline int ecrnx_rx_sm_disconnect_ind(struct ecrnx_hw *ecrnx_hw,
1096                                             struct ecrnx_cmd *cmd,
1097                                             struct ipc_e2a_msg *msg)
1098 {
1099     struct sm_disconnect_ind *ind = (struct sm_disconnect_ind *)msg->param;
1100     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1101     struct net_device *dev = ecrnx_vif->ndev;
1102
1103     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1104
1105     ECRNX_PRINT("%s:dev:%p, vif_up:%d, reason_code:%d \n", __func__, dev, ecrnx_vif->up, ind->reason_code);
1106     /* if vif is not up, ecrnx_close has already been called */
1107     if (ecrnx_vif->up) {
1108         if (!ind->reassoc) {
1109             cfg80211_disconnected(dev, ind->reason_code, NULL, 0,
1110                                   (ind->reason_code <= 1), GFP_ATOMIC);
1111             if (ecrnx_vif->sta.ft_assoc_ies) {
1112                 kfree(ecrnx_vif->sta.ft_assoc_ies);
1113                 ecrnx_vif->sta.ft_assoc_ies = NULL;
1114                 ecrnx_vif->sta.ft_assoc_ies_len = 0;
1115             }
1116         }
1117         netif_tx_stop_all_queues(dev);
1118         netif_carrier_off(dev);
1119     }
1120
1121     if (ecrnx_vif->sta.ap && ecrnx_vif->sta.ap->valid)
1122     {
1123         ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_vif->sta.ap);
1124 #ifdef CONFIG_ECRNX_BFMER
1125         /* Disable Beamformer if supported */
1126         ecrnx_bfmer_report_del(ecrnx_hw, ecrnx_vif->sta.ap);
1127 #endif //(CONFIG_ECRNX_BFMER)
1128
1129         ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_vif->sta.ap);
1130         ecrnx_rx_reord_sta_deinit(ecrnx_hw, ecrnx_vif->sta.ap->sta_idx, true);
1131         ecrnx_vif->sta.ap->valid = false;
1132         ecrnx_vif->sta.ap = NULL;
1133     }
1134     ecrnx_txq_tdls_vif_deinit(ecrnx_vif);
1135     //ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_vif->sta.ap);
1136     ecrnx_vif->generation++;
1137     ecrnx_external_auth_disable(ecrnx_vif);
1138     ecrnx_chanctx_unlink(ecrnx_vif);
1139
1140     return 0;
1141 }
1142
1143 static inline int ecrnx_rx_sm_external_auth_required_ind(struct ecrnx_hw *ecrnx_hw,
1144                                                         struct ecrnx_cmd *cmd,
1145                                                         struct ipc_e2a_msg *msg)
1146 {
1147     struct sm_external_auth_required_ind *ind =
1148         (struct sm_external_auth_required_ind *)msg->param;
1149     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1150 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
1151     struct net_device *dev = ecrnx_vif->ndev;
1152     struct cfg80211_external_auth_params params;
1153
1154     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1155
1156     params.action = NL80211_EXTERNAL_AUTH_START;
1157     memcpy(params.bssid, ind->bssid.array, ETH_ALEN);
1158     params.ssid.ssid_len = ind->ssid.length;
1159     memcpy(params.ssid.ssid, ind->ssid.array,
1160            min_t(size_t, ind->ssid.length, sizeof(params.ssid.ssid)));
1161     params.key_mgmt_suite = ind->akm;
1162
1163     if ((ind->vif_idx > NX_VIRT_DEV_MAX) || !ecrnx_vif->up ||
1164         (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_STATION) ||
1165         cfg80211_external_auth_request(dev, &params, GFP_ATOMIC)) {
1166         wiphy_err(ecrnx_hw->wiphy, "Failed to start external auth on vif %d",
1167                   ind->vif_idx);
1168         ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1169                                                 WLAN_STATUS_UNSPECIFIED_FAILURE);
1170         return 0;
1171     }
1172
1173     ecrnx_external_auth_enable(ecrnx_vif);
1174 #else
1175     ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1176                                             WLAN_STATUS_UNSPECIFIED_FAILURE);
1177 #endif
1178     return 0;
1179 }
1180
1181 static inline int ecrnx_rx_sm_ft_auth_ind(struct ecrnx_hw *ecrnx_hw,
1182                                          struct ecrnx_cmd *cmd,
1183                                          struct ipc_e2a_msg *msg)
1184 {
1185     struct sm_ft_auth_ind *ind = (struct sm_ft_auth_ind *)msg->param;
1186     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1187     struct sk_buff *skb;
1188     size_t data_len = (offsetof(struct ieee80211_mgmt, u.auth.variable) +
1189                        ind->ft_ie_len);
1190     skb = dev_alloc_skb(data_len);
1191     if (skb) {
1192         struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb_put(skb, data_len);
1193         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
1194         memcpy(mgmt->u.auth.variable, ind->ft_ie_buf, ind->ft_ie_len);
1195         ecrnx_rx_defer_skb(ecrnx_hw, ecrnx_vif, skb);
1196         dev_kfree_skb(skb);
1197     } else {
1198         netdev_warn(ecrnx_vif->ndev, "Allocation failed for FT auth ind\n");
1199     }
1200     return 0;
1201 }
1202 static inline int ecrnx_rx_twt_setup_ind(struct ecrnx_hw *ecrnx_hw,
1203                                         struct ecrnx_cmd *cmd,
1204                                         struct ipc_e2a_msg *msg)
1205 {
1206     struct twt_setup_ind *ind = (struct twt_setup_ind *)msg->param;
1207     struct ecrnx_sta *ecrnx_sta = &ecrnx_hw->sta_table[ind->sta_idx];
1208     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1209     memcpy(&ecrnx_sta->twt_ind, ind, sizeof(struct twt_setup_ind));
1210     return 0;
1211 }
1212
1213 static inline int ecrnx_rx_mesh_path_create_cfm(struct ecrnx_hw *ecrnx_hw,
1214                                                struct ecrnx_cmd *cmd,
1215                                                struct ipc_e2a_msg *msg)
1216 {
1217     struct mesh_path_create_cfm *cfm = (struct mesh_path_create_cfm *)msg->param;
1218     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[cfm->vif_idx];
1219
1220     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1221
1222     /* Check we well have a Mesh Point Interface */
1223     if (ecrnx_vif && (ECRNX_VIF_TYPE(ecrnx_vif) == NL80211_IFTYPE_MESH_POINT))
1224         ecrnx_vif->ap.flags &= ~ECRNX_AP_CREATE_MESH_PATH;
1225
1226     return 0;
1227 }
1228
1229 static inline int ecrnx_rx_mesh_peer_update_ind(struct ecrnx_hw *ecrnx_hw,
1230                                                struct ecrnx_cmd *cmd,
1231                                                struct ipc_e2a_msg *msg)
1232 {
1233     struct mesh_peer_update_ind *ind = (struct mesh_peer_update_ind *)msg->param;
1234     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1235     struct ecrnx_sta *ecrnx_sta = &ecrnx_hw->sta_table[ind->sta_idx];
1236
1237     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1238
1239     if ((ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX)) ||
1240         (ecrnx_vif && (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT)) ||
1241         (ind->sta_idx >= NX_REMOTE_STA_MAX))
1242         return 1;
1243
1244     if (ecrnx_vif->ap.flags & ECRNX_AP_USER_MESH_PM)
1245     {
1246         if (!ind->estab && ecrnx_sta->valid) {
1247             ecrnx_sta->ps.active = false;
1248             ecrnx_sta->valid = false;
1249             list_del_init(&ecrnx_sta->list);
1250             ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_sta);
1251             ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_sta);
1252         } else {
1253             WARN_ON(0);
1254         }
1255     } else {
1256         /* Check if peer link has been established or lost */
1257         if (ind->estab) {
1258             if (!ecrnx_sta->valid) {
1259                 u8 txq_status;
1260
1261                 ecrnx_sta->valid = true;
1262                 ecrnx_sta->sta_idx = ind->sta_idx;
1263                 ecrnx_sta->ch_idx = ecrnx_vif->ch_index;
1264                 ecrnx_sta->vif_idx = ind->vif_idx;
1265                 ecrnx_sta->vlan_idx = ecrnx_sta->vif_idx;
1266                 ecrnx_sta->ps.active = false;
1267                 ecrnx_sta->qos = true;
1268                 ecrnx_sta->aid = ind->sta_idx + 1;
1269                 //ecrnx_sta->acm = ind->acm;
1270                 memcpy(ecrnx_sta->mac_addr, ind->peer_addr.array, ETH_ALEN);
1271
1272                 ecrnx_chanctx_link(ecrnx_vif, ecrnx_sta->ch_idx, NULL);
1273
1274                 /* Add the station in the list of VIF's stations */
1275                 INIT_LIST_HEAD(&ecrnx_sta->list);
1276                 list_add_tail(&ecrnx_sta->list, &ecrnx_vif->ap.sta_list);
1277
1278                 /* Initialize the TX queues */
1279                 if (ecrnx_sta->ch_idx == ecrnx_hw->cur_chanctx) {
1280                     txq_status = 0;
1281                 } else {
1282                     txq_status = ECRNX_TXQ_STOP_CHAN;
1283                 }
1284
1285                 ecrnx_txq_sta_init(ecrnx_hw, ecrnx_sta, txq_status);
1286                 ecrnx_dbgfs_register_sta(ecrnx_hw, ecrnx_sta);
1287
1288 #ifdef CONFIG_ECRNX_BFMER
1289                 // TODO: update indication to contains vht capabilties
1290                 if (ecrnx_hw->mod_params->bfmer)
1291                     ecrnx_send_bfmer_enable(ecrnx_hw, ecrnx_sta, NULL);
1292
1293                 ecrnx_mu_group_sta_init(ecrnx_sta, NULL);
1294 #endif /* CONFIG_ECRNX_BFMER */
1295
1296             } else {
1297                 WARN_ON(0);
1298             }
1299         } else {
1300             if (ecrnx_sta->valid) {
1301                 ecrnx_sta->ps.active = false;
1302                 ecrnx_sta->valid = false;
1303
1304                 /* Remove the station from the list of VIF's station */
1305                 list_del_init(&ecrnx_sta->list);
1306
1307                 ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_sta);
1308                 ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_sta);
1309             } else {
1310                 WARN_ON(0);
1311             }
1312             /* There is no way to inform upper layer for lost of peer, still
1313                clean everything in the driver */
1314
1315             /* Remove the station from the list of VIF's station */
1316
1317         }
1318     }
1319
1320     return 0;
1321 }
1322
1323 static inline int ecrnx_rx_mesh_path_update_ind(struct ecrnx_hw *ecrnx_hw,
1324                                                struct ecrnx_cmd *cmd,
1325                                                struct ipc_e2a_msg *msg)
1326 {
1327     struct mesh_path_update_ind *ind = (struct mesh_path_update_ind *)msg->param;
1328     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1329     struct ecrnx_mesh_path *mesh_path;
1330     bool found = false;
1331
1332     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1333
1334     if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX))
1335         return 1;
1336
1337     if (!ecrnx_vif || (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT))
1338         return 0;
1339
1340     /* Look for path with provided target address */
1341     list_for_each_entry(mesh_path, &ecrnx_vif->ap.mpath_list, list) {
1342         if (mesh_path->path_idx == ind->path_idx) {
1343             found = true;
1344             break;
1345         }
1346     }
1347
1348     /* Check if element has been deleted */
1349     if (ind->delete) {
1350         if (found) {
1351             trace_mesh_delete_path(mesh_path);
1352             /* Remove element from list */
1353             list_del_init(&mesh_path->list);
1354             /* Free the element */
1355             kfree(mesh_path);
1356         }
1357     }
1358     else {
1359         if (found) {
1360             // Update the Next Hop STA
1361             mesh_path->nhop_sta = &ecrnx_hw->sta_table[ind->nhop_sta_idx];
1362             trace_mesh_update_path(mesh_path);
1363         } else {
1364             // Allocate a Mesh Path structure
1365             mesh_path = kmalloc(sizeof(struct ecrnx_mesh_path), GFP_ATOMIC);
1366
1367             if (mesh_path) {
1368                 INIT_LIST_HEAD(&mesh_path->list);
1369
1370                 mesh_path->path_idx = ind->path_idx;
1371                 mesh_path->nhop_sta = &ecrnx_hw->sta_table[ind->nhop_sta_idx];
1372                 memcpy(&mesh_path->tgt_mac_addr, &ind->tgt_mac_addr, MAC_ADDR_LEN);
1373
1374                 // Insert the path in the list of path
1375                 list_add_tail(&mesh_path->list, &ecrnx_vif->ap.mpath_list);
1376
1377                 trace_mesh_create_path(mesh_path);
1378             }
1379         }
1380     }
1381
1382     return 0;
1383 }
1384
1385 static inline int ecrnx_rx_mesh_proxy_update_ind(struct ecrnx_hw *ecrnx_hw,
1386                                                struct ecrnx_cmd *cmd,
1387                                                struct ipc_e2a_msg *msg)
1388 {
1389     struct mesh_proxy_update_ind *ind = (struct mesh_proxy_update_ind *)msg->param;
1390     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1391     struct ecrnx_mesh_proxy *mesh_proxy;
1392     bool found = false;
1393
1394     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1395
1396     if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX))
1397         return 1;
1398
1399     if (!ecrnx_vif || (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT))
1400         return 0;
1401
1402     /* Look for path with provided external STA address */
1403     list_for_each_entry(mesh_proxy, &ecrnx_vif->ap.proxy_list, list) {
1404         if (!memcmp(&ind->ext_sta_addr, &mesh_proxy->ext_sta_addr, ETH_ALEN)) {
1405             found = true;
1406             break;
1407         }
1408     }
1409
1410     if (ind->delete && found) {
1411         /* Delete mesh path */
1412         list_del_init(&mesh_proxy->list);
1413         kfree(mesh_proxy);
1414     } else if (!ind->delete && !found) {
1415         /* Allocate a Mesh Path structure */
1416         mesh_proxy = (struct ecrnx_mesh_proxy *)kmalloc(sizeof(*mesh_proxy),
1417                                                        GFP_ATOMIC);
1418
1419         if (mesh_proxy) {
1420             INIT_LIST_HEAD(&mesh_proxy->list);
1421
1422             memcpy(&mesh_proxy->ext_sta_addr, &ind->ext_sta_addr, MAC_ADDR_LEN);
1423             mesh_proxy->local = ind->local;
1424
1425             if (!ind->local) {
1426                 memcpy(&mesh_proxy->proxy_addr, &ind->proxy_mac_addr, MAC_ADDR_LEN);
1427             }
1428
1429             /* Insert the path in the list of path */
1430             list_add_tail(&mesh_proxy->list, &ecrnx_vif->ap.proxy_list);
1431         }
1432     }
1433
1434     return 0;
1435 }
1436
1437 /***************************************************************************
1438  * Messages from APM task
1439  **************************************************************************/
1440 static inline int ecrnx_rx_apm_probe_client_ind(struct ecrnx_hw *ecrnx_hw,
1441                                                struct ecrnx_cmd *cmd,
1442                                                struct ipc_e2a_msg *msg)
1443 {
1444     struct apm_probe_client_ind *ind = (struct apm_probe_client_ind *)msg->param;
1445     struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[ind->vif_idx];
1446     struct ecrnx_sta *ecrnx_sta = &ecrnx_hw->sta_table[ind->sta_idx];
1447
1448     ecrnx_sta->stats.last_act = jiffies;
1449     cfg80211_probe_status(ecrnx_vif->ndev, ecrnx_sta->mac_addr, (u64)ind->probe_id,
1450                           ind->client_present, 0, false, GFP_ATOMIC);
1451     return 0;
1452 }
1453 #endif /* CONFIG_ECRNX_FULLMAC */
1454
1455 /***************************************************************************
1456  * Messages from DEBUG task
1457  **************************************************************************/
1458 static inline int ecrnx_rx_dbg_error_ind(struct ecrnx_hw *ecrnx_hw,
1459                                         struct ecrnx_cmd *cmd,
1460                                         struct ipc_e2a_msg *msg)
1461 {
1462     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1463
1464     ecrnx_error_ind(ecrnx_hw);
1465
1466     return 0;
1467 }
1468
1469
1470
1471
1472 #ifdef CONFIG_ECRNX_SOFTMAC
1473
1474 static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = {
1475     [MSG_I(MM_CONNECTION_LOSS_IND)]       = ecrnx_rx_connection_loss_ind,
1476     [MSG_I(MM_CHANNEL_SWITCH_IND)]        = ecrnx_rx_chan_switch_ind,
1477     [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)]    = ecrnx_rx_chan_pre_switch_ind,
1478     [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = ecrnx_rx_remain_on_channel_exp_ind,
1479 #ifdef CONFIG_ECRNX_BCN
1480     [MSG_I(MM_PRIMARY_TBTT_IND)]          = ecrnx_rx_prm_tbtt_ind,
1481 #endif
1482     [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)]     = ecrnx_rx_p2p_vif_ps_change_ind,
1483     [MSG_I(MM_CSA_COUNTER_IND)]           = ecrnx_rx_csa_counter_ind,
1484     [MSG_I(MM_CHANNEL_SURVEY_IND)]        = ecrnx_rx_channel_survey_ind,
1485     [MSG_I(MM_RSSI_STATUS_IND)]           = ecrnx_rx_rssi_status_ind,
1486 };
1487
1488 static msg_cb_fct scan_hdlrs[MSG_I(SCAN_MAX)] = {
1489     [MSG_I(SCAN_DONE_IND)]                = ecrnx_rx_scan_done_ind,
1490 };
1491
1492 #else  /* CONFIG_ECRNX_FULLMAC */
1493
1494 static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = {
1495     [MSG_I(MM_CHANNEL_SWITCH_IND)]     = ecrnx_rx_chan_switch_ind,
1496     [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = ecrnx_rx_chan_pre_switch_ind,
1497     [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = ecrnx_rx_remain_on_channel_exp_ind,
1498     [MSG_I(MM_PS_CHANGE_IND)]          = ecrnx_rx_ps_change_ind,
1499     [MSG_I(MM_TRAFFIC_REQ_IND)]        = ecrnx_rx_traffic_req_ind,
1500     [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)]  = ecrnx_rx_p2p_vif_ps_change_ind,
1501     [MSG_I(MM_CSA_COUNTER_IND)]        = ecrnx_rx_csa_counter_ind,
1502     [MSG_I(MM_CSA_FINISH_IND)]         = ecrnx_rx_csa_finish_ind,
1503     [MSG_I(MM_CSA_TRAFFIC_IND)]        = ecrnx_rx_csa_traffic_ind,
1504     [MSG_I(MM_CHANNEL_SURVEY_IND)]     = ecrnx_rx_channel_survey_ind,
1505     [MSG_I(MM_P2P_NOA_UPD_IND)]        = ecrnx_rx_p2p_noa_upd_ind,
1506     [MSG_I(MM_RSSI_STATUS_IND)]        = ecrnx_rx_rssi_status_ind,
1507     [MSG_I(MM_PKTLOSS_IND)]            = ecrnx_rx_pktloss_notify_ind,
1508 };
1509
1510 static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = {
1511     [MSG_I(SCANU_START_CFM)]           = ecrnx_rx_scanu_start_cfm,
1512     [MSG_I(SCANU_RESULT_IND)]          = ecrnx_rx_scanu_result_ind,
1513     [MSG_I(SCANU_CANCEL_CFM)]          = ecrnx_scanu_cancel_cfm,
1514 };
1515
1516 static msg_cb_fct me_hdlrs[MSG_I(ME_MAX)] = {
1517     [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = ecrnx_rx_me_tkip_mic_failure_ind,
1518     [MSG_I(ME_TX_CREDITS_UPDATE_IND)] = ecrnx_rx_me_tx_credits_update_ind,
1519 };
1520
1521 static msg_cb_fct sm_hdlrs[MSG_I(SM_MAX)] = {
1522     [MSG_I(SM_CONNECT_IND)]    = ecrnx_rx_sm_connect_ind,
1523     [MSG_I(SM_DISCONNECT_IND)] = ecrnx_rx_sm_disconnect_ind,
1524     [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = ecrnx_rx_sm_external_auth_required_ind,
1525     [MSG_I(SM_FT_AUTH_IND)] = ecrnx_rx_sm_ft_auth_ind,
1526 };
1527
1528 static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = {
1529     [MSG_I(APM_PROBE_CLIENT_IND)] = ecrnx_rx_apm_probe_client_ind,
1530 };
1531 static msg_cb_fct twt_hdlrs[MSG_I(TWT_MAX)] = {
1532     [MSG_I(TWT_SETUP_IND)]    = ecrnx_rx_twt_setup_ind,
1533 };
1534
1535 static msg_cb_fct mesh_hdlrs[MSG_I(MESH_MAX)] = {
1536     [MSG_I(MESH_PATH_CREATE_CFM)]  = ecrnx_rx_mesh_path_create_cfm,
1537     [MSG_I(MESH_PEER_UPDATE_IND)]  = ecrnx_rx_mesh_peer_update_ind,
1538     [MSG_I(MESH_PATH_UPDATE_IND)]  = ecrnx_rx_mesh_path_update_ind,
1539     [MSG_I(MESH_PROXY_UPDATE_IND)] = ecrnx_rx_mesh_proxy_update_ind,
1540 };
1541
1542
1543 #endif /* CONFIG_ECRNX_SOFTMAC */
1544
1545 static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = {
1546     [MSG_I(DBG_ERROR_IND)]                = ecrnx_rx_dbg_error_ind,
1547 };
1548
1549 static msg_cb_fct tdls_hdlrs[MSG_I(TDLS_MAX)] = {
1550     [MSG_I(TDLS_CHAN_SWITCH_CFM)] = ecrnx_rx_tdls_chan_switch_cfm,
1551     [MSG_I(TDLS_CHAN_SWITCH_IND)] = ecrnx_rx_tdls_chan_switch_ind,
1552     [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = ecrnx_rx_tdls_chan_switch_base_ind,
1553     [MSG_I(TDLS_PEER_PS_IND)] = ecrnx_rx_tdls_peer_ps_ind,
1554 };
1555
1556 static msg_cb_fct *msg_hdlrs[] = {
1557     [TASK_MM]    = mm_hdlrs,
1558     [TASK_DBG]   = dbg_hdlrs,
1559 #ifdef CONFIG_ECRNX_SOFTMAC
1560     [TASK_SCAN]  = scan_hdlrs,
1561     [TASK_TDLS]  = tdls_hdlrs,
1562 #else
1563     [TASK_TDLS]  = tdls_hdlrs,
1564     [TASK_SCANU] = scan_hdlrs,
1565     [TASK_ME]    = me_hdlrs,
1566     [TASK_SM]    = sm_hdlrs,
1567     [TASK_APM]   = apm_hdlrs,
1568     [TASK_MESH]  = mesh_hdlrs,
1569     [TASK_TWT]   = twt_hdlrs,
1570 #if 0//(CONFIG_ECRNX_P2P)
1571     [TASK_P2P_LISTEN]   = p2p_listen_hdlrs,
1572 #endif
1573 #endif /* CONFIG_ECRNX_SOFTMAC */
1574 };
1575
1576 /**
1577  *
1578  */
1579 void ecrnx_rx_handle_msg(struct ecrnx_hw *ecrnx_hw, struct ipc_e2a_msg *msg)
1580 {
1581
1582     if(!ecrnx_hw || !msg || !(&ecrnx_hw->cmd_mgr))
1583     {
1584         ECRNX_ERR("ecrnx_rx_handle_msg:receive msg info error \n");
1585         return;
1586     }
1587
1588 #if defined(CONFIG_ECRNX_P2P)
1589     if (MSG_T(msg->id) != TASK_P2P_LISTEN && (MSG_T(msg->id) < TASK_MM || MSG_T(msg->id) > TASK_MESH || MSG_I(msg->id) >= MSG_I(MM_MAX)))
1590 #else
1591     if (MSG_T(msg->id) < TASK_MM || MSG_T(msg->id) > TASK_MESH || MSG_I(msg->id) >= MSG_I(MM_MAX))
1592 #endif
1593     {
1594         ECRNX_ERR("msg id 0x%x,%d,%d, max %d, dst:0x%x, src:0x%x\n", msg->id, MSG_T(msg->id), MSG_I(msg->id), MSG_I(MM_MAX), msg->dummy_dest_id, msg->dummy_src_id);
1595         ECRNX_ERR("skip msg %p\n", msg);
1596         return;
1597     }
1598
1599     if(ecrnx_hw->wiphy != NULL)
1600     {
1601         ecrnx_hw->cmd_mgr.msgind(&ecrnx_hw->cmd_mgr, msg,
1602                                 msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]);
1603     }
1604 }