2 ****************************************************************************************
6 * @brief RX function definitions
8 * Copyright (C) ESWIN 2015-2020
10 ****************************************************************************************
12 #include "ecrnx_defs.h"
13 #include "ecrnx_prof.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>
29 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
30 #include "ecrnx_debugfs_func.h"
32 static int ecrnx_freq_to_idx(struct ecrnx_hw *ecrnx_hw, int freq)
34 struct ieee80211_supported_band *sband;
35 int band, ch, idx = 0;
37 #ifdef CONFIG_ECRNX_5G
38 for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
40 for (band = NL80211_BAND_2GHZ; band <= NL80211_BAND_2GHZ; band++) {
42 #ifdef CONFIG_ECRNX_SOFTMAC
43 sband = ecrnx_hw->hw->wiphy->bands[band];
45 sband = ecrnx_hw->wiphy->bands[band];
46 #endif /* CONFIG_ECRNX_SOFTMAC */
51 for (ch = 0; ch < sband->n_channels; ch++, idx++) {
52 if (sband->channels[ch].center_freq == freq) {
58 ECRNX_ERR("--!!!!!!!!error freq-----%d\n", freq);
62 // Channel has been found, return the index
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)
73 #ifdef CONFIG_ECRNX_SOFTMAC
74 struct ecrnx_chanctx *chan_ctxt;
76 struct ecrnx_vif *ecrnx_vif;
77 int chan_idx = ((struct mm_channel_pre_switch_ind *)msg->param)->chan_index;
79 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
81 REG_SW_SET_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT);
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;
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);
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);
102 #endif /* CONFIG_ECRNX_SOFTMAC */
104 REG_SW_CLEAR_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_PSWTCH_BIT);
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)
113 #ifdef CONFIG_ECRNX_SOFTMAC
114 struct ecrnx_chanctx *chan_ctxt;
115 struct ecrnx_sta *ecrnx_sta;
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;
122 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
124 REG_SW_SET_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT);
126 #ifdef CONFIG_ECRNX_SOFTMAC
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);
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);
149 u8 vif_index = ((struct mm_channel_switch_ind *)msg->param)->vif_index;
151 // Inform the host that the offchannel period has been started
152 ieee80211_ready_on_channel(ecrnx_hw->hw);
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);
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,
173 ecrnx_radar_detection_enable(&ecrnx_hw->radar,
174 ECRNX_RADAR_DETECT_DISABLE,
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);
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);
197 /* Retrieve the allocated RoC element */
198 struct ecrnx_roc *roc = ecrnx_hw->roc;
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);
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);
213 /* Keep in mind that we have switched on the channel */
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);
227 ecrnx_hw->cur_chanctx = chan_idx;
228 ecrnx_radar_detection_enable_on_cur_channel(ecrnx_hw);
230 #endif /* CONFIG_ECRNX_SOFTMAC */
232 REG_SW_CLEAR_PROFILING_CHAN(ecrnx_hw, SW_PROF_CHAN_CTXT_SWTCH_BIT);
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)
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)
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;
252 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
265 // Enable traffic on OFF channel queue
266 ecrnx_txq_offchan_start(ecrnx_hw);
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)
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;
282 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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);
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);
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)
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;
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;
329 // disable TXQ for TDLS peer
330 ecrnx_txq_tdls_sta_stop(ecrnx_sta, ECRNX_TXQ_STOP_STA_PS, ecrnx_hw);
332 // Enable TXQ for TDLS peer
333 ecrnx_txq_tdls_sta_start(ecrnx_sta, ECRNX_TXQ_STOP_STA_PS, ecrnx_hw);
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);
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)
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;
363 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
365 ieee80211_remain_on_channel_expired(ecrnx_hw->hw);
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;
373 ecrnx_txq_vif_stop(ecrnx_vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
381 if(!ecrnx_hw->roc || !ecrnx_hw->roc->chan){
382 ECRNX_ERR("error!!!:ecrnx_hw->roc or !ecrnx_hw->roc->chan is null \n");
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;
390 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
392 /* For debug purpose (use ftrace kernel option) */
393 trace_roc_exp(ecrnx_vif->vif_index);
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);
403 /* De-init offchannel TX queue */
404 ecrnx_txq_offchan_deinit(ecrnx_vif);
406 /* Increase the cookie counter cannot be zero */
407 ecrnx_hw->roc_cookie++;
409 if (ecrnx_hw->roc_cookie == 0)
410 ecrnx_hw->roc_cookie = 1;
413 ecrnx_hw->p2p_listen.listen_started = 0;
416 /* Free the allocated RoC element */
418 ecrnx_hw->roc = NULL;
420 #if defined(CONFIG_ECRNX_P2P)
421 wake_up(&ecrnx_hw->p2p_listen.rxdataq);
424 #endif /* CONFIG_ECRNX_SOFTMAC */
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)
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;
436 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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) {
446 vif_entry = ecrnx_hw->vif_table[vif_idx];
451 #endif /* CONFIG_ECRNX_SOFTMAC */
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);
462 ecrnx_txq_vif_stop(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
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);
470 // Stop TX queues for provided VIF
471 ecrnx_txq_vif_stop(vif_entry, ECRNX_TXQ_STOP_VIF_PS, ecrnx_hw);
473 #endif /* CONFIG_ECRNX_SOFTMAC */
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)
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);
487 struct ecrnx_survey_info *ecrnx_survey;
489 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
491 if (idx > ARRAY_SIZE(ecrnx_hw->survey))
494 ecrnx_survey = &ecrnx_hw->survey[idx];
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);
503 if (ind->noise_dbm != 0) {
504 ecrnx_survey->filled |= SURVEY_INFO_NOISE_DBM;
507 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
508 ecrnx_debugfs_noise_of_survey_info_update(ecrnx_hw, ecrnx_survey, idx);
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)
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)
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;
529 struct ecrnx_vif *vif_entry;
531 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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);
543 vif_entry = ecrnx_hw->vif_table[vif_idx];
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);
550 #endif /* CONFIG_ECRNX_SOFTMAC */
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)
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;
564 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
566 vif_entry = ecrnx_hw->vif_table[vif_idx];
568 cfg80211_cqm_pktloss_notify(vif_entry->ndev, (const u8 *)ind->mac_addr.array,
569 ind->num_packets, GFP_ATOMIC);
571 #endif /* CONFIG_ECRNX_FULLMAC */
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)
580 struct mm_csa_counter_ind *ind = (struct mm_csa_counter_ind *)msg->param;
581 struct ecrnx_vif *vif;
584 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
586 // Look for VIF entry
587 list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
588 if (vif->vif_index == ind->vif_index) {
595 #ifdef CONFIG_ECRNX_SOFTMAC
596 if (ind->csa_count == 1)
597 ieee80211_csa_finish(vif->vif);
599 ieee80211_csa_update_counter(vif->vif);
602 vif->ap.csa->count = ind->csa_count;
604 netdev_err(vif->ndev, "CSA counter update but no active CSA");
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)
617 struct ecrnx_vif *ecrnx_vif;
620 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
622 inst_nbr = ((struct mm_connection_loss_ind *)msg->param)->inst_nbr;
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);
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)
641 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
643 ecrnx_tx_bcns(ecrnx_hw);
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)
654 struct mm_csa_finish_ind *ind = (struct mm_csa_finish_ind *)msg->param;
655 struct ecrnx_vif *vif;
658 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
660 // Look for VIF entry
661 list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
662 if (vif->vif_index == ind->vif_index) {
669 if (ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP ||
670 ECRNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) {
672 vif->ap.csa->status = ind->status;
673 vif->ap.csa->ch_idx = ind->chan_idx;
674 schedule_work(&vif->ap.csa->work);
676 netdev_err(vif->ndev, "CSA finish indication but no active CSA");
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);
685 ecrnx_txq_vif_stop(vif, ECRNX_TXQ_STOP_CHAN, ecrnx_hw);
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)
697 struct mm_csa_traffic_ind *ind = (struct mm_csa_traffic_ind *)msg->param;
698 struct ecrnx_vif *vif;
701 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
703 // Look for VIF entry
704 list_for_each_entry(vif, &ecrnx_hw->vifs, list) {
705 if (vif->vif_index == ind->vif_index) {
713 ecrnx_txq_vif_start(vif, ECRNX_TXQ_STOP_CSA, ecrnx_hw);
715 ecrnx_txq_vif_stop(vif, ECRNX_TXQ_STOP_CSA, ecrnx_hw);
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)
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];
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",
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");
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");
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;
745 netdev_err(ecrnx_hw->vif_table[sta->vif_idx]->ndev,
746 "Ignore PS mode change on invalid sta\n");
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)
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];
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);
762 netdev_dbg(ecrnx_hw->vif_table[sta->vif_idx]->ndev,
763 "Sta %d, asked for %d pkt", sta->sta_idx, ind->pkt_cnt);
765 ecrnx_ps_bh_traffic_req(ecrnx_hw, sta, ind->pkt_cnt,
766 ind->uapsd ? UAPSD_ID : LEGACY_PS_ID);
770 #endif /* CONFIG_ECRNX_SOFTMAC */
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)
780 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
781 struct cfg80211_scan_info info = {
785 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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);
791 ieee80211_scan_completed(ecrnx_hw->hw, false);
796 #endif /* CONFIG_ECRNX_SOFTMAC */
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)
806 struct scanu_cancel_cfm *cfm = (struct scanu_cancel_cfm *)msg;
809 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
810 struct cfg80211_scan_info info = {
815 ECRNX_PRINT("%s: cfm status:%d, scan_request:0x%p \n", __func__, cfm->status, ecrnx_hw->scan_request);
817 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
818 cfg80211_scan_done(ecrnx_hw->scan_request, &info);
820 cfg80211_scan_done(ecrnx_hw->scan_request, false);
822 ecrnx_hw->scan_request = NULL;
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)
831 struct scanu_start_cfm* cfm = (struct scanu_start_cfm*)msg->param;
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;
837 #ifndef CONFIG_ECRNX_ESWIN
838 ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &ecrnx_hw->scan_ie);
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,
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);
851 cfg80211_scan_done(ecrnx_hw->scan_request, abort_status);
855 ecrnx_hw->scan_request = NULL;
856 spin_unlock_bh(&ecrnx_hw->scan_req_lock);
861 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
862 u64_l getBootTime(void)
864 struct timespec64 ts;
867 ts = ktime_to_timespec64(ktime_get_boottime());
868 bootTime = ts.tv_sec;
870 bootTime += ts.tv_nsec / 1000;
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)
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);
884 chan = ieee80211_get_channel(ecrnx_hw->wiphy, ind->center_freq);
888 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
889 if(ieee80211_is_beacon(mgmt->frame_control))
891 mgmt->u.beacon.timestamp = getBootTime();
893 if(ieee80211_is_probe_resp(mgmt->frame_control))
895 mgmt->u.probe_resp.timestamp = getBootTime();
898 bss = cfg80211_inform_bss_frame(ecrnx_hw->wiphy, chan,
900 ind->length, ind->rssi * 100, GFP_ATOMIC);
904 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
905 cfg80211_put_bss(ecrnx_hw->wiphy, bss);
907 cfg80211_put_bss(bss);
910 #if defined(CONFIG_ECRNX_DEBUGFS_CUSTOM)
911 ecrnx_debugfs_survey_info_update(ecrnx_hw, bss);
916 #endif /* CONFIG_ECRNX_FULLMAC */
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)
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;
930 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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);
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)
943 struct me_tx_credits_update_ind *ind = (struct me_tx_credits_update_ind *)msg->param;
945 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
947 ecrnx_txq_credit_update(ecrnx_hw, ind->sta_idx, ind->tid, ind->credits);
951 #endif /* CONFIG_ECRNX_FULLMAC */
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)
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;
966 const struct ieee_types_extcap *extcap;
968 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
975 // Fill-in the AP information
976 if (ind->status_code == 0)
978 struct ecrnx_sta *sta = &ecrnx_hw->sta_table[ind->ap_idx];
980 struct ieee80211_channel *chan;
981 struct cfg80211_chan_def chandef;
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;
992 sta->ps.active = false;
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;
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) {
1014 txq_status = ECRNX_TXQ_STOP_CHAN;
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;
1032 #ifdef CONFIG_ECRNX_BFMER
1033 /* If Beamformer feature is activated, check if features can be used
1034 * with the new peer device
1036 if (ecrnx_hw->mod_params->bfmer) {
1037 const u8 *vht_capa_ie;
1038 const struct ieee80211_vht_cap *vht_cap;
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);
1045 /* Stop here if peer device does not support VHT */
1050 vht_cap = (const struct ieee80211_vht_cap *)(vht_capa_ie + 2);
1052 /* Send MM_BFMER_ENABLE_REQ message if needed */
1053 ecrnx_send_bfmer_enable(ecrnx_hw, sta, vht_cap);
1056 #endif //(CONFIG_ECRNX_BFMER)
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);
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);
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,
1088 netif_tx_start_all_queues(dev);
1089 netif_carrier_on(dev);
1090 spin_unlock_bh(&ecrnx_hw->connect_req_lock);
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)
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;
1103 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
1117 netif_tx_stop_all_queues(dev);
1118 netif_carrier_off(dev);
1121 if (ecrnx_vif->sta.ap && ecrnx_vif->sta.ap->valid)
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)
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;
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);
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)
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;
1154 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
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, ¶ms, GFP_ATOMIC)) {
1166 wiphy_err(ecrnx_hw->wiphy, "Failed to start external auth on vif %d",
1168 ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1169 WLAN_STATUS_UNSPECIFIED_FAILURE);
1173 ecrnx_external_auth_enable(ecrnx_vif);
1175 ecrnx_send_sm_external_auth_required_rsp(ecrnx_hw, ecrnx_vif,
1176 WLAN_STATUS_UNSPECIFIED_FAILURE);
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)
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) +
1190 skb = dev_alloc_skb(data_len);
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);
1198 netdev_warn(ecrnx_vif->ndev, "Allocation failed for FT auth ind\n");
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)
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));
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)
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];
1220 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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;
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)
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];
1237 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
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))
1244 if (ecrnx_vif->ap.flags & ECRNX_AP_USER_MESH_PM)
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);
1256 /* Check if peer link has been established or lost */
1258 if (!ecrnx_sta->valid) {
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);
1272 ecrnx_chanctx_link(ecrnx_vif, ecrnx_sta->ch_idx, NULL);
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);
1278 /* Initialize the TX queues */
1279 if (ecrnx_sta->ch_idx == ecrnx_hw->cur_chanctx) {
1282 txq_status = ECRNX_TXQ_STOP_CHAN;
1285 ecrnx_txq_sta_init(ecrnx_hw, ecrnx_sta, txq_status);
1286 ecrnx_dbgfs_register_sta(ecrnx_hw, ecrnx_sta);
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);
1293 ecrnx_mu_group_sta_init(ecrnx_sta, NULL);
1294 #endif /* CONFIG_ECRNX_BFMER */
1300 if (ecrnx_sta->valid) {
1301 ecrnx_sta->ps.active = false;
1302 ecrnx_sta->valid = false;
1304 /* Remove the station from the list of VIF's station */
1305 list_del_init(&ecrnx_sta->list);
1307 ecrnx_txq_sta_deinit(ecrnx_hw, ecrnx_sta);
1308 ecrnx_dbgfs_unregister_sta(ecrnx_hw, ecrnx_sta);
1312 /* There is no way to inform upper layer for lost of peer, still
1313 clean everything in the driver */
1315 /* Remove the station from the list of VIF's station */
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)
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;
1332 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1334 if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX))
1337 if (!ecrnx_vif || (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT))
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) {
1348 /* Check if element has been deleted */
1351 trace_mesh_delete_path(mesh_path);
1352 /* Remove element from list */
1353 list_del_init(&mesh_path->list);
1354 /* Free the element */
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);
1364 // Allocate a Mesh Path structure
1365 mesh_path = kmalloc(sizeof(struct ecrnx_mesh_path), GFP_ATOMIC);
1368 INIT_LIST_HEAD(&mesh_path->list);
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);
1374 // Insert the path in the list of path
1375 list_add_tail(&mesh_path->list, &ecrnx_vif->ap.mpath_list);
1377 trace_mesh_create_path(mesh_path);
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)
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;
1394 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1396 if (ind->vif_idx >= (NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX))
1399 if (!ecrnx_vif || (ECRNX_VIF_TYPE(ecrnx_vif) != NL80211_IFTYPE_MESH_POINT))
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)) {
1410 if (ind->delete && found) {
1411 /* Delete mesh path */
1412 list_del_init(&mesh_proxy->list);
1414 } else if (!ind->delete && !found) {
1415 /* Allocate a Mesh Path structure */
1416 mesh_proxy = (struct ecrnx_mesh_proxy *)kmalloc(sizeof(*mesh_proxy),
1420 INIT_LIST_HEAD(&mesh_proxy->list);
1422 memcpy(&mesh_proxy->ext_sta_addr, &ind->ext_sta_addr, MAC_ADDR_LEN);
1423 mesh_proxy->local = ind->local;
1426 memcpy(&mesh_proxy->proxy_addr, &ind->proxy_mac_addr, MAC_ADDR_LEN);
1429 /* Insert the path in the list of path */
1430 list_add_tail(&mesh_proxy->list, &ecrnx_vif->ap.proxy_list);
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)
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];
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);
1453 #endif /* CONFIG_ECRNX_FULLMAC */
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)
1462 ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1464 ecrnx_error_ind(ecrnx_hw);
1472 #ifdef CONFIG_ECRNX_SOFTMAC
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,
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,
1488 static msg_cb_fct scan_hdlrs[MSG_I(SCAN_MAX)] = {
1489 [MSG_I(SCAN_DONE_IND)] = ecrnx_rx_scan_done_ind,
1492 #else /* CONFIG_ECRNX_FULLMAC */
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,
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,
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,
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,
1528 static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = {
1529 [MSG_I(APM_PROBE_CLIENT_IND)] = ecrnx_rx_apm_probe_client_ind,
1531 static msg_cb_fct twt_hdlrs[MSG_I(TWT_MAX)] = {
1532 [MSG_I(TWT_SETUP_IND)] = ecrnx_rx_twt_setup_ind,
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,
1543 #endif /* CONFIG_ECRNX_SOFTMAC */
1545 static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = {
1546 [MSG_I(DBG_ERROR_IND)] = ecrnx_rx_dbg_error_ind,
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,
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,
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,
1573 #endif /* CONFIG_ECRNX_SOFTMAC */
1579 void ecrnx_rx_handle_msg(struct ecrnx_hw *ecrnx_hw, struct ipc_e2a_msg *msg)
1582 if(!ecrnx_hw || !msg || !(&ecrnx_hw->cmd_mgr))
1584 ECRNX_ERR("ecrnx_rx_handle_msg:receive msg info error \n");
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)))
1591 if (MSG_T(msg->id) < TASK_MM || MSG_T(msg->id) > TASK_MESH || MSG_I(msg->id) >= MSG_I(MM_MAX))
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);
1599 if(ecrnx_hw->wiphy != NULL)
1601 ecrnx_hw->cmd_mgr.msgind(&ecrnx_hw->cmd_mgr, msg,
1602 msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]);