net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_msg_tx.c
1 /**
2  ******************************************************************************
3  *
4  * @file ecrnx_msg_tx.c
5  *
6  * @brief TX function definitions
7  *
8  * Copyright (C) ESWIN 2015-2020
9  *
10  ******************************************************************************
11  */
12
13 #include "ecrnx_msg_tx.h"
14 #include "ecrnx_mod_params.h"
15 #include "reg_access.h"
16 #ifdef CONFIG_ECRNX_BFMER
17 #include "ecrnx_bfmer.h"
18 #endif //(CONFIG_ECRNX_BFMER)
19 #include "ecrnx_compat.h"
20 #include "ecrnx_defs.h"
21 #include "ecrnx_calibration_data.h"
22 #include "eswin_utils.h"
23 #include "core.h"
24
25 const struct mac_addr mac_addr_bcst = {{0xFFFF, 0xFFFF, 0xFFFF}};
26
27 /* Default MAC Rx filters that can be changed by mac80211
28  * (via the configure_filter() callback) */
29 #define ECRNX_MAC80211_CHANGEABLE        (                                       \
30                                          NXMAC_ACCEPT_BA_BIT                  | \
31                                          NXMAC_ACCEPT_BAR_BIT                 | \
32                                          NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT   | \
33                                          NXMAC_ACCEPT_PROBE_REQ_BIT           | \
34                                          NXMAC_ACCEPT_PS_POLL_BIT               \
35                                         )
36
37 /* Default MAC Rx filters that cannot be changed by mac80211 */
38 #define ECRNX_MAC80211_NOT_CHANGEABLE    (                                       \
39                                          NXMAC_ACCEPT_QO_S_NULL_BIT           | \
40                                          NXMAC_ACCEPT_Q_DATA_BIT              | \
41                                          NXMAC_ACCEPT_DATA_BIT                | \
42                                          NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT   | \
43                                          NXMAC_ACCEPT_MY_UNICAST_BIT          | \
44                                          NXMAC_ACCEPT_BROADCAST_BIT           | \
45                                          NXMAC_ACCEPT_BEACON_BIT              | \
46                                          NXMAC_ACCEPT_PROBE_RESP_BIT            \
47                                         )
48
49 /* Default MAC Rx filter */
50 #define ECRNX_DEFAULT_RX_FILTER  (ECRNX_MAC80211_CHANGEABLE | ECRNX_MAC80211_NOT_CHANGEABLE)
51
52 const int bw2chnl[] = {
53     [NL80211_CHAN_WIDTH_20_NOHT] = PHY_CHNL_BW_20,
54     [NL80211_CHAN_WIDTH_20]      = PHY_CHNL_BW_20,
55     [NL80211_CHAN_WIDTH_40]      = PHY_CHNL_BW_40,
56     [NL80211_CHAN_WIDTH_80]      = PHY_CHNL_BW_80,
57     [NL80211_CHAN_WIDTH_160]     = PHY_CHNL_BW_160,
58     [NL80211_CHAN_WIDTH_80P80]   = PHY_CHNL_BW_80P80,
59 };
60
61 const int chnl2bw[] = {
62     [PHY_CHNL_BW_20]      = NL80211_CHAN_WIDTH_20,
63     [PHY_CHNL_BW_40]      = NL80211_CHAN_WIDTH_40,
64     [PHY_CHNL_BW_80]      = NL80211_CHAN_WIDTH_80,
65     [PHY_CHNL_BW_160]     = NL80211_CHAN_WIDTH_160,
66     [PHY_CHNL_BW_80P80]   = NL80211_CHAN_WIDTH_80P80,
67 };
68
69 /*****************************************************************************/
70 /*
71  * Parse the ampdu density to retrieve the value in usec, according to the
72  * values defined in ieee80211.h
73  */
74 static inline u8 ecrnx_ampdudensity2usec(u8 ampdudensity)
75 {
76     switch (ampdudensity) {
77     case IEEE80211_HT_MPDU_DENSITY_NONE:
78         return 0;
79         /* 1 microsecond is our granularity */
80     case IEEE80211_HT_MPDU_DENSITY_0_25:
81     case IEEE80211_HT_MPDU_DENSITY_0_5:
82     case IEEE80211_HT_MPDU_DENSITY_1:
83         return 1;
84     case IEEE80211_HT_MPDU_DENSITY_2:
85         return 2;
86     case IEEE80211_HT_MPDU_DENSITY_4:
87         return 4;
88     case IEEE80211_HT_MPDU_DENSITY_8:
89         return 8;
90     case IEEE80211_HT_MPDU_DENSITY_16:
91         return 16;
92     default:
93         return 0;
94     }
95 }
96
97 static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto)
98 {
99     if ((crypto->cipher_group ==  WLAN_CIPHER_SUITE_WEP40) ||
100         (crypto->cipher_group ==  WLAN_CIPHER_SUITE_WEP104))
101         return false;
102
103     return true;
104 }
105
106 static inline bool is_non_blocking_msg(int id)
107 {
108     return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) ||
109             (id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ) ||
110             (id == TDLS_PEER_TRAFFIC_IND_REQ) ||
111             (id == MESH_PATH_CREATE_REQ) || (id == MESH_PROXY_ADD_REQ) ||
112             (id == SM_EXTERNAL_AUTH_REQUIRED_RSP));
113 }
114
115 #ifdef CONFIG_ECRNX_FULLMAC
116 /**
117  * copy_connect_ies -- Copy Association Elements in the the request buffer
118  * send to the firmware
119  *
120  * @vif: Vif that received the connection request
121  * @req: Connection request to send to the firmware
122  * @sme: Connection info
123  *
124  * For driver that do not use userspace SME (like this one) the host connection
125  * request doesn't explicitly mentions that the connection can use FT over the
126  * air. if FT is possible, send the FT elements (as received in update_ft_ies callback)
127  * to the firmware
128  *
129  * In all other cases simply copy the list povided by the user space in the
130  * request buffer
131  */
132 static void copy_connect_ies(struct ecrnx_vif *vif, struct sm_connect_req *req,
133                             struct cfg80211_connect_params *sme)
134 {
135     if ((sme->auth_type == NL80211_AUTHTYPE_FT) && !(vif->sta.flags & ECRNX_STA_FT_OVER_DS))
136     {
137         const struct ecrnx_element *rsne, *fte, *mde;
138         uint8_t *pos;
139         rsne = cfg80211_find_ecrnx_elem(WLAN_EID_RSN, vif->sta.ft_assoc_ies,
140                                     vif->sta.ft_assoc_ies_len);
141         fte = cfg80211_find_ecrnx_elem(WLAN_EID_FAST_BSS_TRANSITION, vif->sta.ft_assoc_ies,
142                                     vif->sta.ft_assoc_ies_len);
143         mde = cfg80211_find_ecrnx_elem(WLAN_EID_MOBILITY_DOMAIN,
144                                          vif->sta.ft_assoc_ies, vif->sta.ft_assoc_ies_len);
145         pos = (uint8_t *)req->ie_buf;
146
147         // We can use FT over the air
148         memcpy(&vif->sta.ft_target_ap, sme->bssid, ETH_ALEN);
149
150         if (rsne) {
151             memcpy(pos, rsne, sizeof(struct ecrnx_element) + rsne->datalen);
152             pos += sizeof(struct ecrnx_element) + rsne->datalen;
153         }
154         memcpy(pos, mde, sizeof(struct ecrnx_element) + mde->datalen);
155         pos += sizeof(struct ecrnx_element) + mde->datalen;
156         if (fte) {
157             memcpy(pos, fte, sizeof(struct ecrnx_element) + fte->datalen);
158             pos += sizeof(struct ecrnx_element) + fte->datalen;
159         }
160
161         req->ie_len = pos - (uint8_t *)req->ie_buf;
162     }
163     else
164     {
165         memcpy(req->ie_buf, sme->ie, sme->ie_len);
166         req->ie_len = sme->ie_len;
167     }
168 }
169
170 /**
171  * update_connect_req -- Return the length of the association request IEs
172  *
173  * @vif: Vif that received the connection request
174  * @sme: Connection info
175  *
176  * Return the ft_ie_len in case of FT.
177  * FT over the air is possible if:
178  * - auth_type = AUTOMATIC (if already set to FT then it means FT over DS)
179  * - already associated to a FT BSS
180  * - Target Mobility domain is the same as the curent one
181  *
182  * If FT is not possible return ie length of the connection info
183  */
184 static int update_connect_req(struct ecrnx_vif *vif, struct cfg80211_connect_params *sme)
185 {
186     if ((vif->sta.ap) &&
187         (vif->sta.ft_assoc_ies) &&
188         (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC))
189     {
190         const struct ecrnx_element *rsne, *fte, *mde, *mde_req;
191         int ft_ie_len = 0;
192
193         mde_req = cfg80211_find_ecrnx_elem(WLAN_EID_MOBILITY_DOMAIN,
194                                      sme->ie, sme->ie_len);
195         mde = cfg80211_find_ecrnx_elem(WLAN_EID_MOBILITY_DOMAIN,
196                                  vif->sta.ft_assoc_ies, vif->sta.ft_assoc_ies_len);
197         if (!mde || !mde_req ||
198             memcmp(mde, mde_req, sizeof(struct ecrnx_element) + mde->datalen))
199         {
200             return sme->ie_len;
201         }
202
203         ft_ie_len += sizeof(struct ecrnx_element) + mde->datalen;
204
205         rsne = cfg80211_find_ecrnx_elem(WLAN_EID_RSN, vif->sta.ft_assoc_ies,
206                                     vif->sta.ft_assoc_ies_len);
207         fte = cfg80211_find_ecrnx_elem(WLAN_EID_FAST_BSS_TRANSITION, vif->sta.ft_assoc_ies,
208                                     vif->sta.ft_assoc_ies_len);
209
210         if (rsne && fte)
211         {
212             ft_ie_len += 2 * sizeof(struct ecrnx_element) + rsne->datalen + fte->datalen;
213             sme->auth_type = NL80211_AUTHTYPE_FT;
214             return ft_ie_len;
215         }
216         else if (rsne || fte)
217         {
218             netdev_warn(vif->ndev, "Missing RSNE or FTE element, skip FT over air");
219         }
220         else
221         {
222             sme->auth_type = NL80211_AUTHTYPE_FT;
223             return ft_ie_len;
224         }
225     }
226     return sme->ie_len;
227 }
228 #endif
229 static inline u8_l get_chan_flags(uint32_t flags)
230 {
231     u8_l chan_flags = 0;
232 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
233     if (flags & IEEE80211_CHAN_PASSIVE_SCAN)
234 #else
235     if (flags & IEEE80211_CHAN_NO_IR)
236         chan_flags |= CHAN_NO_IR;
237     if (flags & IEEE80211_CHAN_RADAR)
238         chan_flags |= CHAN_RADAR;
239 #endif
240     return chan_flags;
241 }
242
243 static inline s8_l chan_to_fw_pwr(int power)
244 {
245     return power > 127 ? 127 : (s8_l)power;
246 }
247
248 static void cfg80211_to_ecrnx_chan(const struct cfg80211_chan_def *chandef,
249                                   struct mac_chan_op *chan)
250 {
251     chan->band = chandef->chan->band;
252     chan->type = bw2chnl[chandef->width];
253     chan->prim20_freq = chandef->chan->center_freq;
254     chan->center1_freq = chandef->center_freq1;
255     chan->center2_freq = chandef->center_freq2;
256     chan->flags = get_chan_flags(chandef->chan->flags);
257     chan->tx_power = chan_to_fw_pwr(chandef->chan->max_power);
258 }
259
260 static inline void limit_chan_bw(u8_l *bw, u16_l primary, u16_l *center1)
261 {
262     int oft, new_oft = 10;
263
264     if (*bw <= PHY_CHNL_BW_40)
265         return;
266
267     oft = *center1 - primary;
268     *bw = PHY_CHNL_BW_40;
269
270     if (oft < 0)
271         new_oft = new_oft * -1;
272     if (abs(oft) == 10 || abs(oft) == 50)
273         new_oft = new_oft * -1;
274
275     *center1 = primary + new_oft;
276 }
277
278 /**
279  ******************************************************************************
280  * @brief Allocate memory for a message
281  *
282  * This primitive allocates memory for a message that has to be sent. The memory
283  * is allocated dynamically on the heap and the length of the variable parameter
284  * structure has to be provided in order to allocate the correct size.
285  *
286  * Several additional parameters are provided which will be preset in the message
287  * and which may be used internally to choose the kind of memory to allocate.
288  *
289  * The memory allocated will be automatically freed by the kernel, after the
290  * pointer has been sent to ke_msg_send(). If the message is not sent, it must
291  * be freed explicitly with ke_msg_free().
292  *
293  * Allocation failure is considered critical and should not happen.
294  *
295  * @param[in] id        Message identifier
296  * @param[in] dest_id   Destination Task Identifier
297  * @param[in] src_id    Source Task Identifier
298  * @param[in] param_len Size of the message parameters to be allocated
299  *
300  * @return Pointer to the parameter member of the ke_msg. If the parameter
301  *         structure is empty, the pointer will point to the end of the message
302  *         and should not be used (except to retrieve the message pointer or to
303  *         send the message)
304  ******************************************************************************
305  */
306 static inline void *ecrnx_msg_zalloc(lmac_msg_id_t const id,
307                                     lmac_task_id_t const dest_id,
308                                     lmac_task_id_t const src_id,
309                                     uint16_t const param_len)
310 {
311     struct lmac_msg *msg;
312     gfp_t flags;
313
314     if (is_non_blocking_msg(id) && in_softirq())
315         flags = GFP_ATOMIC;
316     else
317         flags = GFP_KERNEL;
318
319     msg = (struct lmac_msg *)kzalloc(sizeof(struct lmac_msg) + param_len,
320                                      flags);
321     if (msg == NULL) {
322         ECRNX_ERR(KERN_CRIT "%s: msg allocation failed\n", __func__);
323         return NULL;
324     }
325
326     msg->id = id;
327     msg->dest_id = dest_id;
328     msg->src_id = src_id;
329     msg->param_len = param_len;
330
331     return msg->param;
332 }
333
334 static void ecrnx_msg_free(struct ecrnx_hw *ecrnx_hw, const void *msg_params)
335 {
336     struct lmac_msg *msg = container_of((void *)msg_params,
337                                         struct lmac_msg, param);
338
339     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
340
341     /* Free the message */
342     kfree(msg);
343 }
344
345 static int ecrnx_send_msg(struct ecrnx_hw *ecrnx_hw, const void *msg_params,
346                          int reqcfm, lmac_msg_id_t reqid, void *cfm)
347 {
348     struct lmac_msg *msg;
349     struct ecrnx_cmd *cmd;
350     bool nonblock;
351     int ret;
352
353     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
354
355     msg = container_of((void *)msg_params, struct lmac_msg, param);
356
357     if (!test_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags) &&
358         reqid != MM_RESET_CFM && reqid != MM_VERSION_CFM &&
359         reqid != MM_START_CFM && reqid != MM_SET_IDLE_CFM &&
360         reqid != ME_CONFIG_CFM && reqid != MM_SET_PS_MODE_CFM &&
361         reqid != ME_CHAN_CONFIG_CFM && reqid != MM_SET_GAIN_DELTA_CFM &&
362         reqid != MM_GET_CAL_RESULT_CFM) {
363         ECRNX_ERR(KERN_CRIT "%s: bypassing (ECRNX_DEV_RESTARTING set) 0x%02x\n",
364                __func__, reqid);
365         kfree(msg);
366         return -EBUSY;
367     } else if (!ecrnx_hw->ipc_env) {
368         ECRNX_ERR(KERN_CRIT "%s: bypassing (restart must have failed)\n", __func__);
369         kfree(msg);
370         return -EBUSY;
371     }
372
373     nonblock = is_non_blocking_msg(msg->id);
374     
375 #if defined(CONFIG_ECRNX_ESWIN_USB)
376     if(register_status == false){
377         kfree(msg);
378         return -ENODEV;
379     }
380 #endif
381
382     cmd = kzalloc(sizeof(struct ecrnx_cmd), nonblock ? GFP_ATOMIC : GFP_KERNEL);
383     cmd->result  = -EINTR;
384     cmd->id      = msg->id;
385     cmd->reqid   = reqid;
386     cmd->a2e_msg = msg;
387     cmd->e2a_msg = cfm;
388     if (nonblock)
389         cmd->flags = ECRNX_CMD_FLAG_NONBLOCK;
390     if (reqcfm)
391         cmd->flags |= ECRNX_CMD_FLAG_REQ_CFM;
392     if(ecrnx_hw->wiphy != NULL)
393     {
394         ret = ecrnx_hw->cmd_mgr.queue(&ecrnx_hw->cmd_mgr, cmd);
395     }
396     if (!nonblock)
397         kfree(cmd);
398
399     if (!ret)
400         ret = cmd->result;
401
402     return ret;
403 }
404
405 /******************************************************************************
406  *    Control messages handling functions (SOFTMAC and  FULLMAC)
407  *****************************************************************************/
408 int ecrnx_send_reset(struct ecrnx_hw *ecrnx_hw)
409 {
410     void *void_param;
411
412     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
413
414     /* RESET REQ has no parameter */
415     void_param = ecrnx_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0);
416     if (!void_param)
417         return -ENOMEM;
418
419     return ecrnx_send_msg(ecrnx_hw, void_param, 1, MM_RESET_CFM, NULL);
420 }
421
422 int ecrnx_send_start(struct ecrnx_hw *ecrnx_hw)
423 {
424     struct mm_start_req *start_req_param;
425
426     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
427
428     /* Build the START REQ message */
429     start_req_param = ecrnx_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID,
430                                       sizeof(struct mm_start_req));
431     if (!start_req_param)
432         return -ENOMEM;
433
434     /* Set parameters for the START message */
435     memcpy(&start_req_param->phy_cfg, &ecrnx_hw->phy.cfg, sizeof(ecrnx_hw->phy.cfg));
436     start_req_param->uapsd_timeout = (u32_l)ecrnx_hw->mod_params->uapsd_timeout;
437     start_req_param->lp_clk_accuracy = (u16_l)ecrnx_hw->mod_params->lp_clk_ppm;
438     start_req_param->tx_timeout[AC_BK] = (u16_l)ecrnx_hw->mod_params->tx_to_bk;
439     start_req_param->tx_timeout[AC_BE] = (u16_l)ecrnx_hw->mod_params->tx_to_be;
440     start_req_param->tx_timeout[AC_VI] = (u16_l)ecrnx_hw->mod_params->tx_to_vi;
441     start_req_param->tx_timeout[AC_VO] = (u16_l)ecrnx_hw->mod_params->tx_to_vo;
442
443     /* Send the START REQ message to LMAC FW */
444     return ecrnx_send_msg(ecrnx_hw, start_req_param, 1, MM_START_CFM, NULL);
445 }
446
447 int ecrnx_send_version_req(struct ecrnx_hw *ecrnx_hw, struct mm_version_cfm *cfm)
448 {
449     void *void_param;
450
451     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
452     /* VERSION REQ has no parameter */
453     void_param = ecrnx_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0);
454     if (!void_param)
455         return -ENOMEM;
456
457     return ecrnx_send_msg(ecrnx_hw, void_param, 1, MM_VERSION_CFM, cfm);
458 }
459
460 int ecrnx_send_add_if(struct ecrnx_hw *ecrnx_hw, const unsigned char *mac,
461                      enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm)
462 {
463     struct mm_add_if_req *add_if_req_param;
464
465     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
466
467     /* Build the ADD_IF_REQ message */
468     add_if_req_param = ecrnx_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID,
469                                        sizeof(struct mm_add_if_req));
470     if (!add_if_req_param)
471         return -ENOMEM;
472
473     /* Set parameters for the ADD_IF_REQ message */
474     memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN);
475     switch (iftype) {
476     #ifdef CONFIG_ECRNX_FULLMAC
477     case NL80211_IFTYPE_P2P_CLIENT:
478         add_if_req_param->p2p = true;
479         add_if_req_param->type = MM_STA;
480         break;
481     #endif /* CONFIG_ECRNX_FULLMAC */
482     case NL80211_IFTYPE_STATION:
483         add_if_req_param->type = MM_STA;
484         break;
485
486     case NL80211_IFTYPE_ADHOC:
487         add_if_req_param->type = MM_IBSS;
488         break;
489
490     #ifdef CONFIG_ECRNX_FULLMAC
491     case NL80211_IFTYPE_P2P_GO:
492         add_if_req_param->p2p = true;
493         add_if_req_param->type = MM_AP;
494         break;
495     #endif /* CONFIG_ECRNX_FULLMAC */
496     case NL80211_IFTYPE_AP:
497         add_if_req_param->type = MM_AP;
498         break;
499     case NL80211_IFTYPE_MESH_POINT:
500         add_if_req_param->type = MM_MESH_POINT;
501         break;
502     case NL80211_IFTYPE_AP_VLAN:
503         return -1;
504     case NL80211_IFTYPE_MONITOR:
505         add_if_req_param->type = MM_MONITOR;
506         break;
507     default:
508         add_if_req_param->type = MM_STA;
509         break;
510     }
511
512     #ifdef CONFIG_ECRNX_SOFTMAC
513     add_if_req_param->p2p = p2p;
514     #endif /* CONFIG_ECRNX_SOFTMAC */
515
516     /* Send the ADD_IF_REQ message to LMAC FW */
517     return ecrnx_send_msg(ecrnx_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm);
518 }
519
520 int ecrnx_send_remove_if(struct ecrnx_hw *ecrnx_hw, u8 vif_index)
521 {
522     struct mm_remove_if_req *remove_if_req;
523
524     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
525
526     /* Build the MM_REMOVE_IF_REQ message */
527     remove_if_req = ecrnx_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID,
528                                     sizeof(struct mm_remove_if_req));
529     if (!remove_if_req)
530         return -ENOMEM;
531
532     /* Set parameters for the MM_REMOVE_IF_REQ message */
533     remove_if_req->inst_nbr = vif_index;
534
535     /* Send the MM_REMOVE_IF_REQ message to LMAC FW */
536     return ecrnx_send_msg(ecrnx_hw, remove_if_req, 1, MM_REMOVE_IF_CFM, NULL);
537 }
538
539 int ecrnx_send_set_channel(struct ecrnx_hw *ecrnx_hw, int phy_idx,
540                           struct mm_set_channel_cfm *cfm)
541 {
542 #ifdef CONFIG_ECRNX_SOFTMAC
543     struct cfg80211_chan_def *chandef = &ecrnx_hw->hw->conf.chandef;
544 #endif /* CONFIG_ECRNX_SOFTMAC */
545     struct mm_set_channel_req *req;
546
547     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
548
549     if (phy_idx >= ecrnx_hw->phy.cnt)
550         return -ENOTSUPP;
551
552     req = ecrnx_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID,
553                           sizeof(struct mm_set_channel_req));
554     if (!req)
555         return -ENOMEM;
556
557     if (phy_idx == 0) {
558 #ifdef CONFIG_ECRNX_SOFTMAC
559         cfg80211_to_ecrnx_chan(chandef, &req->chan);
560 #else
561         /* On FULLMAC only setting channel of secondary chain */
562         wiphy_err(ecrnx_hw->wiphy, "Trying to set channel of primary chain");
563         return 0;
564 #endif /* CONFIG_ECRNX_SOFTMAC */
565     } else {
566         req->chan = ecrnx_hw->phy.sec_chan;
567     }
568
569     req->index = phy_idx;
570
571     if (ecrnx_hw->phy.limit_bw)
572         limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq);
573
574     /*ECRNX_DBG("mac80211:   freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n"
575              "   hw(%d): prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n",
576              center_freq, center_freq1, center_freq2, width, band,
577              phy_idx, req->chan.prim20_freq, req->chan.center1_freq,
578              req->chan.center2_freq, req->chan.type, req->chan.band);*/
579
580     /* Send the MM_SET_CHANNEL_REQ REQ message to LMAC FW */
581     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_SET_CHANNEL_CFM, cfm);
582 }
583
584
585 int ecrnx_send_key_add(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise,
586                       u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite,
587                       struct mm_key_add_cfm *cfm)
588 {
589     struct mm_key_add_req *key_add_req;
590
591     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
592
593     /* Build the MM_KEY_ADD_REQ message */
594     key_add_req = ecrnx_msg_zalloc(MM_KEY_ADD_REQ, TASK_MM, DRV_TASK_ID,
595                                   sizeof(struct mm_key_add_req));
596     if (!key_add_req)
597         return -ENOMEM;
598
599     /* Set parameters for the MM_KEY_ADD_REQ message */
600     if (sta_idx != 0xFF) {
601         /* Pairwise key */
602         key_add_req->sta_idx = sta_idx;
603     } else {
604         /* Default key */
605         key_add_req->sta_idx = sta_idx;
606         key_add_req->key_idx = (u8_l)key_idx; /* only useful for default keys */
607     }
608     key_add_req->pairwise = pairwise;
609     key_add_req->inst_nbr = vif_idx;
610     key_add_req->key.length = key_len;
611     memcpy(&(key_add_req->key.array[0]), key, key_len);
612
613     key_add_req->cipher_suite = cipher_suite;
614
615     ECRNX_DBG("%s: sta_idx:%d key_idx:%d inst_nbr:%d cipher:%d key_len:%d\n", __func__,
616              key_add_req->sta_idx, key_add_req->key_idx, key_add_req->inst_nbr,
617              key_add_req->cipher_suite, key_add_req->key.length);
618 #if defined(CONFIG_ECRNX_DBG) || defined(CONFIG_DYNAMIC_DEBUG)
619     print_hex_dump_bytes("key: ", DUMP_PREFIX_OFFSET, key_add_req->key.array, key_add_req->key.length);
620 #endif
621
622     /* Send the MM_KEY_ADD_REQ message to LMAC FW */
623     return ecrnx_send_msg(ecrnx_hw, key_add_req, 1, MM_KEY_ADD_CFM, cfm);
624 }
625
626 int ecrnx_send_key_del(struct ecrnx_hw *ecrnx_hw, uint8_t hw_key_idx)
627 {
628     struct mm_key_del_req *key_del_req;
629
630     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
631
632     /* Build the MM_KEY_DEL_REQ message */
633     key_del_req = ecrnx_msg_zalloc(MM_KEY_DEL_REQ, TASK_MM, DRV_TASK_ID,
634                                   sizeof(struct mm_key_del_req));
635     if (!key_del_req)
636         return -ENOMEM;
637
638     /* Set parameters for the MM_KEY_DEL_REQ message */
639     key_del_req->hw_key_idx = hw_key_idx;
640
641     /* Send the MM_KEY_DEL_REQ message to LMAC FW */
642     return ecrnx_send_msg(ecrnx_hw, key_del_req, 1, MM_KEY_DEL_CFM, NULL);
643 }
644
645 int ecrnx_send_bcn_change(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, dma_addr_t bcn_addr,
646                          u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft)
647 {
648     struct mm_bcn_change_req *req;
649
650     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
651
652     /* Build the MM_BCN_CHANGE_REQ message */
653     req = ecrnx_msg_zalloc(MM_BCN_CHANGE_REQ, TASK_MM, DRV_TASK_ID,
654                           sizeof(struct mm_bcn_change_req));
655     if (!req)
656         return -ENOMEM;
657
658     /* Set parameters for the MM_BCN_CHANGE_REQ message */
659     req->bcn_ptr = bcn_addr;
660     req->bcn_len = bcn_len;
661     req->tim_oft = tim_oft;
662     req->tim_len = tim_len;
663     req->inst_nbr = vif_idx;
664
665 #if defined(CONFIG_ECRNX_SOFTMAC)
666     BUILD_BUG_ON_MSG(IEEE80211_MAX_CSA_COUNTERS_NUM != BCN_MAX_CSA_CPT,
667                      "BCN_MAX_CSA_CPT and IEEE80211_MAX_CSA_COUNTERS_NUM "
668                      "have different value");
669 #endif /* CONFIG_ECRNX_SOFTMAC */
670     if (csa_oft) {
671         int i;
672         for (i = 0; i < BCN_MAX_CSA_CPT; i++) {
673             req->csa_oft[i] = csa_oft[i];
674         }
675     }
676
677     /* Send the MM_BCN_CHANGE_REQ message to LMAC FW */
678     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_BCN_CHANGE_CFM, NULL);
679 }
680
681 int ecrnx_send_roc(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
682                   struct ieee80211_channel *chan, unsigned  int duration)
683 {
684     struct mm_remain_on_channel_req *req;
685     struct cfg80211_chan_def chandef;
686
687     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
688
689     /* Create channel definition structure */
690     cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
691
692     /* Build the MM_REMAIN_ON_CHANNEL_REQ message */
693     req = ecrnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID,
694                           sizeof(struct mm_remain_on_channel_req));
695     if (!req)
696         return -ENOMEM;
697
698     /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */
699     req->op_code      = MM_ROC_OP_START;
700     req->vif_index    = vif->vif_index;
701     req->duration_ms  = duration;
702     cfg80211_to_ecrnx_chan(&chandef, &req->chan);
703
704     /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */
705     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, NULL);
706 }
707
708 int ecrnx_send_cancel_roc(struct ecrnx_hw *ecrnx_hw)
709 {
710     struct mm_remain_on_channel_req *req;
711
712     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
713
714     /* Build the MM_REMAIN_ON_CHANNEL_REQ message */
715     req = ecrnx_msg_zalloc(MM_REMAIN_ON_CHANNEL_REQ, TASK_MM, DRV_TASK_ID,
716                           sizeof(struct mm_remain_on_channel_req));
717     if (!req)
718         return -ENOMEM;
719
720     /* Set parameters for the MM_REMAIN_ON_CHANNEL_REQ message */
721     req->op_code = MM_ROC_OP_CANCEL;
722
723     /* Send the MM_REMAIN_ON_CHANNEL_REQ message to LMAC FW */
724     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_REMAIN_ON_CHANNEL_CFM, NULL);
725 }
726
727 int ecrnx_send_set_power(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, s8 pwr,
728                         struct mm_set_power_cfm *cfm)
729 {
730     struct mm_set_power_req *req;
731
732     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
733
734     /* Build the MM_SET_POWER_REQ message */
735     req = ecrnx_msg_zalloc(MM_SET_POWER_REQ, TASK_MM, DRV_TASK_ID,
736                           sizeof(struct mm_set_power_req));
737     if (!req)
738         return -ENOMEM;
739
740     /* Set parameters for the MM_SET_POWER_REQ message */
741     req->inst_nbr = vif_idx;
742     req->power = pwr;
743
744     /* Send the MM_SET_POWER_REQ message to LMAC FW */
745     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_SET_POWER_CFM, cfm);
746 }
747
748 int ecrnx_send_set_edca(struct ecrnx_hw *ecrnx_hw, u8 hw_queue, u32 param,
749                        bool uapsd, u8 inst_nbr)
750 {
751     struct mm_set_edca_req *set_edca_req;
752
753     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
754
755     /* Build the MM_SET_EDCA_REQ message */
756     set_edca_req = ecrnx_msg_zalloc(MM_SET_EDCA_REQ, TASK_MM, DRV_TASK_ID,
757                                    sizeof(struct mm_set_edca_req));
758     if (!set_edca_req)
759         return -ENOMEM;
760
761     /* Set parameters for the MM_SET_EDCA_REQ message */
762     set_edca_req->ac_param = param;
763     set_edca_req->uapsd = uapsd;
764     set_edca_req->hw_queue = hw_queue;
765     set_edca_req->inst_nbr = inst_nbr;
766
767     /* Send the MM_SET_EDCA_REQ message to LMAC FW */
768     return ecrnx_send_msg(ecrnx_hw, set_edca_req, 1, MM_SET_EDCA_CFM, NULL);
769 }
770
771 #ifdef CONFIG_ECRNX_P2P_DEBUGFS
772 int ecrnx_send_p2p_oppps_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
773                             u8 ctw, struct mm_set_p2p_oppps_cfm *cfm)
774 {
775     struct mm_set_p2p_oppps_req *p2p_oppps_req;
776     int error;
777
778     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
779
780     /* Build the MM_SET_P2P_OPPPS_REQ message */
781     p2p_oppps_req = ecrnx_msg_zalloc(MM_SET_P2P_OPPPS_REQ, TASK_MM, DRV_TASK_ID,
782                                     sizeof(struct mm_set_p2p_oppps_req));
783
784     if (!p2p_oppps_req) {
785         return -ENOMEM;
786     }
787
788     /* Fill the message parameters */
789     p2p_oppps_req->vif_index = ecrnx_vif->vif_index;
790     p2p_oppps_req->ctwindow = ctw;
791
792     /* Send the MM_P2P_OPPPS_REQ message to LMAC FW */
793     error = ecrnx_send_msg(ecrnx_hw, p2p_oppps_req, 1, MM_SET_P2P_OPPPS_CFM, cfm);
794
795     return (error);
796 }
797
798 int ecrnx_send_p2p_noa_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
799                           int count, int interval, int duration, bool dyn_noa,
800                           struct mm_set_p2p_noa_cfm *cfm)
801 {
802     struct mm_set_p2p_noa_req *p2p_noa_req;
803     int error;
804
805     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
806
807     /* Param check */
808     if (count > 255)
809         count = 255;
810
811     if (duration >= interval) {
812         dev_err(ecrnx_hw->dev, "Invalid p2p NOA config: interval=%d <= duration=%d\n",
813                 interval, duration);
814         return -EINVAL;
815     }
816
817     /* Build the MM_SET_P2P_NOA_REQ message */
818     p2p_noa_req = ecrnx_msg_zalloc(MM_SET_P2P_NOA_REQ, TASK_MM, DRV_TASK_ID,
819                                   sizeof(struct mm_set_p2p_noa_req));
820
821     if (!p2p_noa_req) {
822         return -ENOMEM;
823     }
824
825     /* Fill the message parameters */
826     p2p_noa_req->vif_index = ecrnx_vif->vif_index;
827     p2p_noa_req->noa_inst_nb = 0;
828     p2p_noa_req->count = count;
829
830     if (count) {
831         p2p_noa_req->duration_us = duration * 1024;
832         p2p_noa_req->interval_us = interval * 1024;
833         p2p_noa_req->start_offset = (interval - duration - 10) * 1024;
834         p2p_noa_req->dyn_noa = dyn_noa;
835     }
836
837     /* Send the MM_SET_2P_NOA_REQ message to LMAC FW */
838     error = ecrnx_send_msg(ecrnx_hw, p2p_noa_req, 1, MM_SET_P2P_NOA_CFM, cfm);
839
840     return (error);
841 }
842 #endif /* CONFIG_ECRNX_P2P_DEBUGFS */
843
844 /******************************************************************************
845  *    Control messages handling functions (SOFTMAC only)
846  *****************************************************************************/
847 #ifdef CONFIG_ECRNX_SOFTMAC
848 int ecrnx_send_sta_add(struct ecrnx_hw *ecrnx_hw, struct ieee80211_sta *sta,
849                       u8 inst_nbr, struct mm_sta_add_cfm *cfm)
850 {
851     struct mm_sta_add_req *sta_add_req;
852     union ecrnx_thd_phy_ctrl_info *phy;
853     struct ecrnx_sta *ecrnx_sta;
854     int error;
855
856     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
857
858     /* Build the MM_STA_ADD_REQ message */
859     sta_add_req = ecrnx_msg_zalloc(MM_STA_ADD_REQ, TASK_MM, DRV_TASK_ID,
860                                   sizeof(struct mm_sta_add_req));
861     if (!sta_add_req)
862         return -ENOMEM;
863
864     /* Set parameters for the MM_STA_ADD_REQ message */
865     memcpy(&(sta_add_req->mac_addr.array[0]), &(sta->addr[0]), ETH_ALEN);
866
867     if (sta->wme)
868         sta_add_req->capa_flags |= STA_QOS_CAPA;
869     /* TODO: check if a density of 0 microseconds is OK or not for LMAC */
870     if (sta->ht_cap.ht_supported) {
871         int ht_exp = sta->ht_cap.ampdu_factor;
872         int vht_exp = 0;
873
874         sta_add_req->capa_flags |= STA_HT_CAPA;
875         sta_add_req->ampdu_size_max_ht =
876             (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + ht_exp)) - 1;
877         sta_add_req->ampdu_spacing_min =
878             ecrnx_ampdudensity2usec(sta->ht_cap.ampdu_density);
879
880         if (sta->vht_cap.vht_supported) {
881             sta_add_req->capa_flags |= STA_VHT_CAPA;
882             vht_exp = (sta->vht_cap.cap &
883                 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
884                 IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
885             sta_add_req->ampdu_size_max_vht =
886                 (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + vht_exp)) - 1;
887         }
888
889 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) && defined(CONFIG_ECRNX_HE)
890         if (sta->he_cap.has_he) {
891             int he_exp_ext = (sta->he_cap.he_cap_elem.mac_cap_info[3] &
892                               IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >> 3;
893
894             sta_add_req->capa_flags |= STA_HE_CAPA;
895             if (sta->vht_cap.vht_supported) {
896                 if ((vht_exp == 7) && he_exp_ext)
897                     sta_add_req->ampdu_size_max_he =
898                         (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + vht_exp + he_exp_ext)) - 1;
899                 else
900                     sta_add_req->ampdu_size_max_he = sta_add_req->ampdu_size_max_vht;
901             } else {
902                 if ((ht_exp == 3) && he_exp_ext)
903                     sta_add_req->ampdu_size_max_he =
904                         (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + ht_exp + he_exp_ext)) - 1;
905                 else
906                     sta_add_req->ampdu_size_max_he = sta_add_req->ampdu_size_max_ht;
907             }
908         }
909 #endif
910     }
911 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
912     if (sta->mfp)
913         sta_add_req->capa_flags |= STA_MFP_CAPA;
914 #endif
915
916     ecrnx_sta = (struct ecrnx_sta *)sta->drv_priv;
917     /* TODO Set the interface index from the vif structure */
918     sta_add_req->inst_nbr = inst_nbr;
919     sta_add_req->tdls_sta = sta->tdls;
920     sta_add_req->tdls_sta_initiator = STA_TDLS_INITIATOR(sta);
921     sta_add_req->bssid_index = 0;
922     sta_add_req->max_bssid_ind = 0;
923     phy = (union ecrnx_thd_phy_ctrl_info *)&sta_add_req->paid_gid;
924     phy->partialAIDTx = ecrnx_sta->paid;
925     phy->groupIDTx = ecrnx_sta->gid;
926
927     /* Send the MM_STA_ADD_REQ message to LMAC FW */
928     error = ecrnx_send_msg(ecrnx_hw, sta_add_req, 1, MM_STA_ADD_CFM, cfm);
929
930     return (error);
931 }
932
933 int ecrnx_send_sta_del(struct ecrnx_hw *ecrnx_hw, u8 sta_idx)
934 {
935     struct mm_sta_del_req *sta_del_req;
936
937     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
938
939     /* Build the MM_STA_DEL_REQ message */
940     sta_del_req = ecrnx_msg_zalloc(MM_STA_DEL_REQ, TASK_MM, DRV_TASK_ID,
941                                   sizeof(struct mm_sta_del_req));
942     if (!sta_del_req)
943         return -ENOMEM;
944
945     /* Set parameters for the MM_STA_DEL_REQ message */
946     sta_del_req->sta_idx = sta_idx;
947
948     /* Send the MM_STA_DEL_REQ message to LMAC FW */
949     return ecrnx_send_msg(ecrnx_hw, sta_del_req, 1, MM_STA_DEL_CFM, NULL);
950 }
951
952 int ecrnx_send_set_filter(struct ecrnx_hw *ecrnx_hw, uint32_t filter)
953 {
954     struct mm_set_filter_req *set_filter_req_param;
955     uint32_t rx_filter = 0;
956
957     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
958
959     /* Build the MM_SET_FILTER_REQ message */
960     set_filter_req_param =
961         ecrnx_msg_zalloc(MM_SET_FILTER_REQ, TASK_MM, DRV_TASK_ID,
962                         sizeof(struct mm_set_filter_req));
963     if (!set_filter_req_param)
964         return -ENOMEM;
965
966     /* Set parameters for the MM_SET_FILTER_REQ message */
967 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
968     if (filter & FIF_PROMISC_IN_BSS)
969         rx_filter |= NXMAC_ACCEPT_UNICAST_BIT;
970 #endif
971     if (filter & FIF_ALLMULTI)
972         rx_filter |= NXMAC_ACCEPT_MULTICAST_BIT;
973
974     if (filter & (FIF_FCSFAIL | FIF_PLCPFAIL))
975         rx_filter |= NXMAC_ACCEPT_ERROR_FRAMES_BIT;
976
977     if (filter & FIF_BCN_PRBRESP_PROMISC)
978         rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT;
979
980     if (filter & FIF_CONTROL)
981         rx_filter |= NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT |
982                      NXMAC_ACCEPT_CF_END_BIT |
983                      NXMAC_ACCEPT_ACK_BIT |
984                      NXMAC_ACCEPT_CTS_BIT |
985                      NXMAC_ACCEPT_RTS_BIT |
986                      NXMAC_ACCEPT_BA_BIT | NXMAC_ACCEPT_BAR_BIT;
987
988     if (filter & FIF_OTHER_BSS)
989         rx_filter |= NXMAC_ACCEPT_OTHER_BSSID_BIT;
990
991     if (filter & FIF_PSPOLL) {
992         /* TODO: check if the MAC filters apply to our BSSID or is general */
993         rx_filter |= NXMAC_ACCEPT_PS_POLL_BIT;
994     }
995
996     if (filter & FIF_PROBE_REQ) {
997         rx_filter |= NXMAC_ACCEPT_PROBE_REQ_BIT;
998         rx_filter |= NXMAC_ACCEPT_ALL_BEACON_BIT;
999     }
1000
1001     /* Add the filter flags that are set by default and cannot be changed here */
1002     rx_filter |= ECRNX_MAC80211_NOT_CHANGEABLE;
1003
1004     /* XXX */
1005     if (ieee80211_hw_check(ecrnx_hw->hw, AMPDU_AGGREGATION))
1006         rx_filter |= NXMAC_ACCEPT_BA_BIT;
1007
1008     /* Now copy all the flags into the message parameter */
1009     set_filter_req_param->filter = rx_filter;
1010
1011     ECRNX_DBG("new total_flags = 0x%08x\nrx filter set to  0x%08x\n",
1012              filter, rx_filter);
1013
1014     /* Send the MM_SET_FILTER_REQ message to LMAC FW */
1015     return ecrnx_send_msg(ecrnx_hw, set_filter_req_param, 1, MM_SET_FILTER_CFM, NULL);
1016 }
1017
1018
1019 int ecrnx_send_add_chanctx(struct ecrnx_hw *ecrnx_hw,
1020                           struct ieee80211_chanctx_conf *ctx,
1021                           struct mm_chan_ctxt_add_cfm *cfm)
1022 {
1023     struct mm_chan_ctxt_add_req *req;
1024
1025     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1026
1027     /* Build the MM_CHAN_CTXT_ADD_REQ message */
1028     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_ADD_REQ, TASK_MM, DRV_TASK_ID,
1029                           sizeof(struct mm_chan_ctxt_add_req));
1030     if (!req)
1031         return -ENOMEM;
1032
1033     /* Set parameters for the CHAN_CTXT_ADD_REQ message */
1034     cfg80211_to_ecrnx_chan(&ctx->def, &req->chan);
1035
1036     if (ecrnx_hw->phy.limit_bw)
1037         limit_chan_bw(&req->chan.type, req->chan.prim20_freq,
1038                       &req->chan.center1_freq);
1039
1040     ECRNX_DBG("mac80211:   freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n"
1041              "          prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n",
1042              ctx->def.chan->center_freq, ctx->def.center_freq1,
1043              ctx->def.center_freq2, ctx->def.width, ctx->def.chan->band,
1044              req->chan.prim20_freq, req->chan.center1_freq,
1045              req->chan.center2_freq, req->chan.type, req->chan.band);
1046     /* Send the CHAN_CTXT_ADD_REQ message to LMAC FW */
1047     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_ADD_CFM, cfm);
1048 }
1049
1050 int ecrnx_send_del_chanctx(struct ecrnx_hw *ecrnx_hw, u8 index)
1051 {
1052     struct mm_chan_ctxt_del_req *req;
1053
1054     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1055
1056     /* Build the MM_CHAN_CTXT_DEL_REQ message */
1057     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_DEL_REQ, TASK_MM, DRV_TASK_ID,
1058                                     sizeof(struct mm_chan_ctxt_del_req));
1059     if (!req)
1060         return -ENOMEM;
1061
1062     /* Set parameters for the MM_REMOVE_IF_REQ message */
1063     req->index = index;
1064
1065     /* Send the MM_CHAN_CTXT_DEL_REQ message to LMAC FW */
1066     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_DEL_CFM, NULL);
1067 }
1068
1069 int ecrnx_send_link_chanctx(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, u8 chan_idx,
1070                            u8 chan_switch)
1071 {
1072     struct mm_chan_ctxt_link_req *req;
1073
1074     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1075
1076     /* Build the MM_CHAN_CTXT_LINK_REQ message */
1077     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_LINK_REQ, TASK_MM, DRV_TASK_ID,
1078                           sizeof(struct mm_chan_ctxt_link_req));
1079     if (!req)
1080         return -ENOMEM;
1081
1082     /* Set parameters for the MM_CHAN_CTXT_LINK_REQ message */
1083     req->vif_index = vif_idx;
1084     req->chan_index = chan_idx;
1085     req->chan_switch = chan_switch;
1086
1087     /* Send the MM_CHAN_CTXT_LINK_REQ message to LMAC FW */
1088     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_LINK_CFM, NULL);
1089 }
1090
1091 int ecrnx_send_unlink_chanctx(struct ecrnx_hw *ecrnx_hw, u8 vif_idx)
1092 {
1093     struct mm_chan_ctxt_unlink_req *req;
1094
1095     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1096
1097     /* Build the MM_CHAN_CTXT_UNLINK_REQ message */
1098     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_UNLINK_REQ, TASK_MM, DRV_TASK_ID,
1099                           sizeof(struct mm_chan_ctxt_unlink_req));
1100     if (!req)
1101         return -ENOMEM;
1102
1103     /* Set parameters for the MM_CHAN_CTXT_UNLINK_REQ message */
1104     req->vif_index = vif_idx;
1105
1106     /* Send the MM_CHAN_CTXT_UNLINK_REQ message to LMAC FW */
1107     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_UNLINK_CFM, NULL);
1108 }
1109
1110 int ecrnx_send_update_chanctx(struct ecrnx_hw *ecrnx_hw,
1111                              struct ieee80211_chanctx_conf *ctx)
1112 {
1113     struct mm_chan_ctxt_update_req *req;
1114     struct ecrnx_chanctx *ecrnx_chanctx;
1115
1116     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1117
1118     /* Build the MM_CHAN_CTXT_UPDATE_REQ message */
1119     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_UPDATE_REQ, TASK_MM, DRV_TASK_ID,
1120                                        sizeof(struct mm_chan_ctxt_update_req));
1121     if (!req)
1122         return -ENOMEM;
1123
1124     /* Set parameters for the MM_CHAN_CTXT_UPDATE_REQ message */
1125     ecrnx_chanctx = (struct ecrnx_chanctx *)ctx->drv_priv;
1126     req->chan_index = ecrnx_chanctx->index;
1127     cfg80211_to_ecrnx_chan(&ctx->def, &req->chan);
1128
1129     if (ecrnx_hw->phy.limit_bw)
1130         limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq);
1131
1132     ECRNX_DBG("mac80211:   freq=%d(c1:%d - c2:%d)/width=%d - band=%d\n"
1133              "          prim20=%d(c1:%d - c2:%d)/ type=%d - band=%d\n",
1134              ctx->def.chan->center_freq, ctx->def.center_freq1,
1135              ctx->def.center_freq2, ctx->def.width, ctx->def.chan->band,
1136              req->chan.prim20_freq, req->chan.center1_freq,
1137              req->chan.center2_freq, req->chan.type, req->chan.band);
1138     /* Send the MM_CHAN_CTXT_UPDATE_REQ message to LMAC FW */
1139     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_UPDATE_CFM, NULL);
1140 }
1141
1142 int ecrnx_send_sched_chanctx(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, u8 chan_idx, u8 type)
1143 {
1144     struct mm_chan_ctxt_sched_req *req;
1145
1146     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1147
1148     /* Build the MM_CHAN_CTXT_SCHED_REQ message */
1149     req = ecrnx_msg_zalloc(MM_CHAN_CTXT_SCHED_REQ, TASK_MM, DRV_TASK_ID,
1150                                     sizeof(struct mm_chan_ctxt_sched_req));
1151     if (!req)
1152         return -ENOMEM;
1153
1154     /* Set parameters for the MM_CHAN_CTXT_SCHED_REQ message */
1155     req->vif_index = vif_idx;
1156     req->chan_index = chan_idx;
1157     req->type = type;
1158
1159     /* Send the MM_CHAN_CTXT_SCHED_REQ message to LMAC FW */
1160     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_CHAN_CTXT_SCHED_CFM, NULL);
1161 }
1162
1163 int ecrnx_send_dtim_req(struct ecrnx_hw *ecrnx_hw, u8 dtim_period)
1164 {
1165     struct mm_set_dtim_req *set_dtim_req;
1166
1167     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1168
1169     /* Build the MM_SET_DTIM_REQ message */
1170     set_dtim_req = ecrnx_msg_zalloc(MM_SET_DTIM_REQ, TASK_MM, DRV_TASK_ID,
1171                                    sizeof(struct mm_set_dtim_req));
1172     if (!set_dtim_req)
1173         return -ENOMEM;
1174
1175     /* Set parameters for the MM_SET_DTIM_REQ message */
1176     set_dtim_req->dtim_period = dtim_period;
1177
1178     /* Send the MM_SET_DTIM_REQ message to LMAC FW */
1179     return ecrnx_send_msg(ecrnx_hw, set_dtim_req, 1, MM_SET_DTIM_CFM, NULL);
1180 }
1181
1182 int ecrnx_send_set_br(struct ecrnx_hw *ecrnx_hw, u32 basic_rates, u8 vif_idx, u8 band)
1183 {
1184     struct mm_set_basic_rates_req *set_basic_rates_req_param;
1185
1186     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1187
1188     /* Build the MM_SET_BASIC_RATES_REQ message */
1189     set_basic_rates_req_param =
1190         ecrnx_msg_zalloc(MM_SET_BASIC_RATES_REQ, TASK_MM, DRV_TASK_ID,
1191                         sizeof(struct mm_set_basic_rates_req));
1192     if (!set_basic_rates_req_param)
1193         return -ENOMEM;
1194
1195     /* Set parameters for the MM_SET_BASIC_RATES_REQ message */
1196     set_basic_rates_req_param->rates = basic_rates;
1197     set_basic_rates_req_param->inst_nbr = vif_idx;
1198     set_basic_rates_req_param->band = band;
1199
1200     /* Send the MM_SET_BASIC_RATES_REQ message to LMAC FW */
1201     return ecrnx_send_msg(ecrnx_hw, set_basic_rates_req_param, 1, MM_SET_BASIC_RATES_CFM, NULL);
1202 }
1203
1204 int ecrnx_send_set_beacon_int(struct ecrnx_hw *ecrnx_hw, u16 beacon_int, u8 vif_idx)
1205 {
1206     struct mm_set_beacon_int_req *set_beacon_int_req_param;
1207
1208     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1209
1210     /* Build the MM_SET_BEACON_INT_REQ message */
1211     set_beacon_int_req_param =
1212         ecrnx_msg_zalloc(MM_SET_BEACON_INT_REQ, TASK_MM, DRV_TASK_ID,
1213                         sizeof(struct mm_set_beacon_int_req));
1214     if (!set_beacon_int_req_param)
1215         return -ENOMEM;
1216
1217     /* Set parameters for the MM_SET_BEACON_INT_REQ message */
1218     set_beacon_int_req_param->beacon_int = beacon_int;
1219     set_beacon_int_req_param->inst_nbr = vif_idx;
1220
1221     /* Send the MM_SET_BEACON_INT_REQ message to LMAC FW */
1222     return ecrnx_send_msg(ecrnx_hw, set_beacon_int_req_param, 1,
1223                          MM_SET_BEACON_INT_CFM, NULL);
1224 }
1225
1226 int ecrnx_send_set_bssid(struct ecrnx_hw *ecrnx_hw, const u8 *bssid, u8 vif_idx)
1227 {
1228     struct mm_set_bssid_req *set_bssid_req_param;
1229
1230     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1231
1232     /* Build the MM_SET_BSSID_REQ message */
1233     set_bssid_req_param = ecrnx_msg_zalloc(MM_SET_BSSID_REQ, TASK_MM, DRV_TASK_ID,
1234                                           sizeof(struct mm_set_bssid_req));
1235     if (!set_bssid_req_param)
1236         return -ENOMEM;
1237
1238     /* Set parameters for the MM_SET_BSSID_REQ message */
1239     memcpy(&(set_bssid_req_param->bssid.array[0]), bssid, ETH_ALEN);
1240     set_bssid_req_param->inst_nbr = vif_idx;
1241
1242     /* Send the MM_SET_BSSID_REQ message to LMAC FW */
1243     return ecrnx_send_msg(ecrnx_hw, set_bssid_req_param, 1, MM_SET_BSSID_CFM, NULL);
1244 }
1245
1246 int ecrnx_send_set_vif_state(struct ecrnx_hw *ecrnx_hw, bool active,
1247                             u16 aid, u8 vif_idx)
1248 {
1249     struct mm_set_vif_state_req *req;
1250
1251     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1252
1253     /* Build the MM_SET_VIF_STATE_REQ message */
1254     req = ecrnx_msg_zalloc(MM_SET_VIF_STATE_REQ, TASK_MM, DRV_TASK_ID,
1255                           sizeof(struct mm_set_vif_state_req));
1256     if (!req)
1257         return -ENOMEM;
1258
1259     /* Set parameters for the MM_SET_VIF_STATE_REQ message */
1260     req->active = active;
1261     req->aid = aid;
1262     req->inst_nbr = vif_idx;
1263
1264     /* Send the MM_SET_VIF_STATE_REQ message to LMAC FW */
1265     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_SET_VIF_STATE_CFM, NULL);
1266 }
1267
1268 int ecrnx_send_set_mode(struct ecrnx_hw *ecrnx_hw, u8 abgnmode)
1269 {
1270     struct mm_set_mode_req *set_mode_req_param;
1271
1272     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1273
1274     /* Build the MM_SET_MODE_REQ message */
1275     set_mode_req_param = ecrnx_msg_zalloc(MM_SET_MODE_REQ, TASK_MM, DRV_TASK_ID,
1276                                          sizeof(struct mm_set_mode_req));
1277     if (!set_mode_req_param)
1278         return -ENOMEM;
1279
1280     set_mode_req_param->abgnmode = abgnmode;
1281
1282     /* Send the MM_SET_MODE_REQ message to LMAC FW */
1283     return ecrnx_send_msg(ecrnx_hw, set_mode_req_param, 1, MM_SET_MODE_CFM, NULL);
1284 }
1285
1286 int ecrnx_send_set_idle(struct ecrnx_hw *ecrnx_hw, int idle)
1287 {
1288     struct mm_set_idle_req *set_idle_req_param;
1289
1290     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1291
1292     set_idle_req_param = ecrnx_msg_zalloc(MM_SET_IDLE_REQ, TASK_MM, DRV_TASK_ID,
1293                                          sizeof(struct mm_set_idle_req));
1294     if (!set_idle_req_param)
1295         return -ENOMEM;
1296
1297     set_idle_req_param->hw_idle = idle;
1298
1299     return ecrnx_send_msg(ecrnx_hw, set_idle_req_param, 1, MM_SET_IDLE_CFM, NULL);
1300 }
1301
1302 int ecrnx_send_set_ps_mode(struct ecrnx_hw *ecrnx_hw, u8 ps_mode)
1303 {
1304     struct mm_set_ps_mode_req *set_ps_mode_req_param;
1305
1306     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1307
1308     set_ps_mode_req_param =
1309         ecrnx_msg_zalloc(MM_SET_PS_MODE_REQ, TASK_MM, DRV_TASK_ID,
1310                         sizeof(struct mm_set_ps_mode_req));
1311     if (!set_ps_mode_req_param)
1312         return -ENOMEM;
1313
1314     set_ps_mode_req_param->new_state = ps_mode;
1315
1316     return ecrnx_send_msg(ecrnx_hw, set_ps_mode_req_param, 1, MM_SET_PS_MODE_CFM, NULL);
1317 }
1318
1319 int ecrnx_send_set_ps_options(struct ecrnx_hw *ecrnx_hw, bool listen_bcmc,
1320                              u16 listen_interval, u8 vif_idx)
1321 {
1322     struct mm_set_ps_options_req *req;
1323
1324     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1325
1326     /* Build the MM_SET_PS_OPTIONS_REQ message */
1327     req = ecrnx_msg_zalloc(MM_SET_PS_OPTIONS_REQ, TASK_MM, DRV_TASK_ID,
1328                           sizeof(struct mm_set_ps_options_req));
1329     if (!req)
1330         return -ENOMEM;
1331
1332     /* Set parameters for the MM_SET_VIF_STATE_REQ message */
1333     req->listen_interval = listen_interval;
1334     req->dont_listen_bc_mc = !listen_bcmc;
1335     req->vif_index = vif_idx;
1336
1337     /* Send the MM_SET_PS_OPTIONS_REQ message to LMAC FW */
1338     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_SET_PS_OPTIONS_CFM, NULL);
1339 }
1340
1341 int ecrnx_send_set_slottime(struct ecrnx_hw *ecrnx_hw, int use_short_slot)
1342 {
1343     struct mm_set_slottime_req *set_slottime_req_param;
1344
1345     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1346
1347     /* Build the MM_SET_SLOTTIME_REQ message */
1348     set_slottime_req_param =
1349         ecrnx_msg_zalloc(MM_SET_SLOTTIME_REQ, TASK_MM, DRV_TASK_ID,
1350                         sizeof(struct mm_set_slottime_req));
1351     if (!set_slottime_req_param)
1352         return -ENOMEM;
1353
1354     /* Set parameters for the MM_SET_SLOTTIME_REQ message */
1355     set_slottime_req_param->slottime = use_short_slot ? 9 : 20;
1356
1357     /* Send the MM_SET_SLOTTIME_REQ message to LMAC FW */
1358     return ecrnx_send_msg(ecrnx_hw, set_slottime_req_param, 1, MM_SET_SLOTTIME_CFM, NULL);
1359 }
1360
1361 int ecrnx_send_ba_add(struct ecrnx_hw *ecrnx_hw, uint8_t type, uint8_t sta_idx,
1362                      u16 tid, uint8_t bufsz, uint16_t ssn,
1363                      struct mm_ba_add_cfm *cfm)
1364 {
1365     struct mm_ba_add_req *req;
1366
1367     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1368
1369     /* Build the MM_BA_ADD_REQ message */
1370     req = ecrnx_msg_zalloc(MM_BA_ADD_REQ, TASK_MM, DRV_TASK_ID,
1371                           sizeof(struct mm_ba_add_req));
1372     if (!req)
1373         return -ENOMEM;
1374
1375     /* Set parameters for the MM_BA_ADD_REQ message */
1376     req->type = type;
1377     req->sta_idx = sta_idx;
1378     req->tid = (u8_l)tid;
1379     req->bufsz = bufsz;
1380     req->ssn = ssn;
1381
1382     /* Send the MM_BA_ADD_REQ message to LMAC FW */
1383     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_BA_ADD_CFM, cfm);
1384 }
1385
1386 int ecrnx_send_ba_del(struct ecrnx_hw *ecrnx_hw, uint8_t sta_idx, u16 tid,
1387                      struct mm_ba_del_cfm *cfm)
1388 {
1389     struct mm_ba_del_req *req;
1390
1391     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1392
1393     /* Build the MM_BA_DEL_REQ message */
1394     req = ecrnx_msg_zalloc(MM_BA_DEL_REQ, TASK_MM, DRV_TASK_ID,
1395                           sizeof(struct mm_ba_del_req));
1396     if (!req)
1397         return -ENOMEM;
1398
1399     /* Set parameters */
1400     req->type = 0;
1401     req->sta_idx = sta_idx;
1402     req->tid = (u8_l)tid;
1403
1404     /* Send the MM_BA_DEL_REQ message to LMAC FW */
1405     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_BA_DEL_CFM, cfm);
1406 }
1407
1408 int ecrnx_send_scan_req(struct ecrnx_hw *ecrnx_hw, struct ieee80211_vif *vif,
1409                        struct cfg80211_scan_request *param,
1410                        struct scan_start_cfm *cfm)
1411 {
1412     struct scan_start_req *req;
1413     int i;
1414     struct ecrnx_vif *ecrnx_vif;
1415     uint8_t chan_flags = 0;
1416
1417     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1418
1419     ecrnx_vif = (struct ecrnx_vif *)vif->drv_priv;
1420
1421     /* Build the SCAN_START_REQ message */
1422     req = ecrnx_msg_zalloc(SCAN_START_REQ, TASK_SCAN, DRV_TASK_ID,
1423                           sizeof(struct scan_start_req));
1424     if (!req)
1425         return -ENOMEM;
1426
1427     /* Set parameters */
1428     req->vif_idx = ecrnx_vif->vif_index;
1429     req->chan_cnt = (u8)min_t(int, SCAN_CHANNEL_MAX, param->n_channels);
1430     req->ssid_cnt = (u8)min_t(int, SCAN_SSID_MAX, param->n_ssids);
1431     req->bssid = mac_addr_bcst;
1432     req->no_cck = param->no_cck;
1433 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
1434     if (param->duration_mandatory)
1435         req->duration = ieee80211_tu_to_usec(param->duration);
1436 #endif
1437
1438     if (req->ssid_cnt == 0)
1439         chan_flags |= CHAN_NO_IR;
1440     for (i = 0; i < req->ssid_cnt; i++) {
1441         int j;
1442         for (j = 0; j < param->ssids[i].ssid_len; j++)
1443             req->ssid[i].array[j] = param->ssids[i].ssid[j];
1444         req->ssid[i].length = param->ssids[i].ssid_len;
1445     }
1446
1447     if (param->ie) {
1448         if (ecrnx_ipc_elem_var_allocs(ecrnx_hw, &ecrnx_hw->scan_ie,
1449                                      param->ie_len, DMA_TO_DEVICE,
1450                                      NULL, param->ie, NULL))
1451             goto error;
1452
1453         req->add_ie_len = param->ie_len;
1454         req->add_ies = ecrnx_hw->scan_ie.dma_addr;
1455     } else {
1456         req->add_ie_len = 0;
1457         req->add_ies = 0;
1458     }
1459
1460     for (i = 0; i < req->chan_cnt; i++) {
1461         struct ieee80211_channel *chan = param->channels[i];
1462
1463         req->chan[i].band = chan->band;
1464         req->chan[i].freq = chan->center_freq;
1465         req->chan[i].flags = chan_flags | get_chan_flags(chan->flags);
1466         req->chan[i].tx_power = chan_to_fw_pwr(chan->max_reg_power);
1467     }
1468
1469     /* Send the SCAN_START_REQ message to LMAC FW */
1470     return ecrnx_send_msg(ecrnx_hw, req, 1, SCAN_START_CFM, cfm);
1471 error:
1472     if (req != NULL)
1473         ecrnx_msg_free(ecrnx_hw, req);
1474     return -ENOMEM;
1475 }
1476
1477 int ecrnx_send_scan_cancel_req(struct ecrnx_hw *ecrnx_hw,
1478                               struct scan_cancel_cfm *cfm)
1479 {
1480     struct scan_cancel_req *req;
1481
1482     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1483
1484     /* Build the SCAN_CANCEL_REQ message */
1485     req = ecrnx_msg_zalloc(SCAN_CANCEL_REQ, TASK_SCAN, DRV_TASK_ID,
1486                           sizeof(struct scan_cancel_req));
1487     if (!req)
1488         return -ENOMEM;
1489
1490     /* Send the SCAN_CANCEL_REQ message to LMAC FW */
1491     return ecrnx_send_msg(ecrnx_hw, req, 1, SCAN_CANCEL_CFM, cfm);
1492 }
1493
1494 void ecrnx_send_tdls_ps(struct ecrnx_hw *ecrnx_hw, bool ps_mode)
1495 {
1496     if (!ecrnx_hw->mod_params->ps_on)
1497         return;
1498
1499     ecrnx_send_set_ps_mode(ecrnx_hw, ps_mode);
1500 }
1501
1502 int ecrnx_send_tim_update(struct ecrnx_hw *ecrnx_hw, u8 vif_idx, u16 aid,
1503                          u8 tx_status)
1504 {
1505     struct mm_tim_update_req *req;
1506
1507     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1508
1509     /* Build the MM_TIM_UPDATE_REQ message */
1510     req = ecrnx_msg_zalloc(MM_TIM_UPDATE_REQ, TASK_MM, DRV_TASK_ID,
1511                           sizeof(struct mm_tim_update_req));
1512     if (!req)
1513         return -ENOMEM;
1514
1515     /* Set parameters for the MM_TIM_UPDATE_REQ message */
1516     req->aid = aid;
1517     req->tx_avail = tx_status;
1518     req->inst_nbr = vif_idx;
1519
1520     /* Send the MM_TIM_UPDATE_REQ message to LMAC FW */
1521     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_TIM_UPDATE_CFM, NULL);
1522 }
1523 #endif /* CONFIG_ECRNX_SOFTMAC */
1524
1525 /******************************************************************************
1526  *    Control messages handling functions (FULLMAC only)
1527  *****************************************************************************/
1528 #ifdef CONFIG_ECRNX_FULLMAC
1529
1530 int ecrnx_send_me_config_req(struct ecrnx_hw *ecrnx_hw)
1531 {
1532     struct me_config_req *req;
1533     struct wiphy *wiphy = ecrnx_hw->wiphy;
1534 #ifdef CONFIG_ECRNX_5G
1535     struct ieee80211_sta_ht_cap *ht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap;
1536     struct ieee80211_sta_vht_cap *vht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->vht_cap;
1537 #else
1538         struct ieee80211_sta_ht_cap *ht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap;
1539         struct ieee80211_sta_vht_cap *vht_cap = &wiphy->bands[NL80211_BAND_2GHZ]->vht_cap;
1540 #endif
1541 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)  && defined(CONFIG_ECRNX_HE)
1542     struct ieee80211_sta_he_cap const *he_cap;
1543 #endif
1544     uint8_t *ht_mcs = (uint8_t *)&ht_cap->mcs;
1545     int i;
1546
1547     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1548
1549     /* Build the ME_CONFIG_REQ message */
1550     req = ecrnx_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
1551                                    sizeof(struct me_config_req));
1552     if (!req)
1553         return -ENOMEM;
1554
1555     /* Set parameters for the ME_CONFIG_REQ message */
1556     req->ht_supp = ht_cap->ht_supported;
1557     req->vht_supp = vht_cap->vht_supported;
1558     req->ht_cap.ht_capa_info = cpu_to_le16(ht_cap->cap);
1559     req->ht_cap.a_mpdu_param = ht_cap->ampdu_factor |
1560                                      (ht_cap->ampdu_density <<
1561                                          IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
1562     for (i = 0; i < sizeof(ht_cap->mcs); i++)
1563         req->ht_cap.mcs_rate[i] = ht_mcs[i];
1564     req->ht_cap.ht_extended_capa = 0;
1565     req->ht_cap.tx_beamforming_capa = 0;
1566     req->ht_cap.asel_capa = 0;
1567
1568     req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap);
1569     req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest);
1570     req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map);
1571     req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest);
1572     req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map);
1573
1574 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) && defined(CONFIG_ECRNX_HE)
1575 #ifdef CONFIG_ECRNX_5G
1576     if (wiphy->bands[NL80211_BAND_5GHZ]->iftype_data != NULL) {
1577         he_cap = &wiphy->bands[NL80211_BAND_5GHZ]->iftype_data->he_cap;
1578 #else
1579         if (wiphy->bands[NL80211_BAND_2GHZ]->iftype_data != NULL) {
1580                 he_cap = &wiphy->bands[NL80211_BAND_2GHZ]->iftype_data->he_cap;
1581 #endif
1582
1583         req->he_supp = he_cap->has_he;
1584         for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.mac_cap_info); i++) {
1585             req->he_cap.mac_cap_info[i] = he_cap->he_cap_elem.mac_cap_info[i];
1586         }
1587         for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.phy_cap_info); i++) {
1588             req->he_cap.phy_cap_info[i] = he_cap->he_cap_elem.phy_cap_info[i];
1589         }
1590         req->he_cap.mcs_supp.rx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80);
1591         req->he_cap.mcs_supp.tx_mcs_80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80);
1592         req->he_cap.mcs_supp.rx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_160);
1593         req->he_cap.mcs_supp.tx_mcs_160 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_160);
1594         req->he_cap.mcs_supp.rx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.rx_mcs_80p80);
1595         req->he_cap.mcs_supp.tx_mcs_80p80 = cpu_to_le16(he_cap->he_mcs_nss_supp.tx_mcs_80p80);
1596         for (i = 0; i < MAC_HE_PPE_THRES_MAX_LEN; i++) {
1597             req->he_cap.ppe_thres[i] = he_cap->ppe_thres[i];
1598         }
1599         req->he_ul_on = ecrnx_hw->mod_params->he_ul_on;
1600     }
1601 #else
1602     req->he_ul_on = false;
1603
1604     req->he_supp = ecrnx_he_cap.has_he;
1605     for (i = 0; i < ARRAY_SIZE(ecrnx_he_cap.he_cap_elem.mac_cap_info); i++) {
1606         req->he_cap.mac_cap_info[i] = ecrnx_he_cap.he_cap_elem.mac_cap_info[i];
1607     }
1608     for (i = 0; i < ARRAY_SIZE(ecrnx_he_cap.he_cap_elem.phy_cap_info); i++) {
1609         req->he_cap.phy_cap_info[i] = ecrnx_he_cap.he_cap_elem.phy_cap_info[i];
1610     }
1611     req->he_cap.mcs_supp.rx_mcs_80 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_80);
1612     req->he_cap.mcs_supp.tx_mcs_80 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_80);
1613     req->he_cap.mcs_supp.rx_mcs_160 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_160);
1614     req->he_cap.mcs_supp.tx_mcs_160 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_160);
1615     req->he_cap.mcs_supp.rx_mcs_80p80 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.rx_mcs_80p80);
1616     req->he_cap.mcs_supp.tx_mcs_80p80 = cpu_to_le16(ecrnx_he_cap.he_mcs_nss_supp.tx_mcs_80p80);
1617     for (i = 0; i < MAC_HE_PPE_THRES_MAX_LEN; i++) {
1618         req->he_cap.ppe_thres[i] = ecrnx_he_cap.ppe_thres[i];
1619     }
1620 #endif
1621
1622     req->ps_on = ecrnx_hw->mod_params->ps_on;
1623     req->dpsm = ecrnx_hw->mod_params->dpsm;
1624     /**
1625      * set sleep_flag for sdio slave.
1626      * bit0: MODEM_SLEEP
1627      * bit1: WFI_SLEEP
1628      * bit2: LIGHT_SLEEP
1629      * bit3: DEEP_SLEEP
1630      */
1631     req->sleep_flag = 0x5;
1632     req->tx_lft = ecrnx_hw->mod_params->tx_lft;
1633     req->ant_div_on = ecrnx_hw->mod_params->ant_div;
1634     if (ecrnx_hw->mod_params->use_80)
1635         req->phy_bw_max = PHY_CHNL_BW_80;
1636     else if (ecrnx_hw->mod_params->use_2040)
1637         req->phy_bw_max = PHY_CHNL_BW_40;
1638     else
1639         req->phy_bw_max = PHY_CHNL_BW_20;
1640
1641     wiphy_info(wiphy, "HT supp %d, VHT supp %d, HE supp %d\n", req->ht_supp,
1642                                                                req->vht_supp,
1643                                                                req->he_supp);
1644
1645     /* Send the ME_CONFIG_REQ message to LMAC FW */
1646     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_CONFIG_CFM, NULL);
1647 }
1648
1649 int ecrnx_send_me_chan_config_req(struct ecrnx_hw *ecrnx_hw)
1650 {
1651     struct me_chan_config_req *req;
1652     struct wiphy *wiphy = ecrnx_hw->wiphy;
1653     int i;
1654
1655     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1656
1657     /* Build the ME_CHAN_CONFIG_REQ message */
1658     req = ecrnx_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
1659                                             sizeof(struct me_chan_config_req));
1660     if (!req)
1661         return -ENOMEM;
1662
1663     req->chan2G4_cnt=  0;
1664     if (wiphy->bands[NL80211_BAND_2GHZ] != NULL) {
1665         struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_2GHZ];
1666         for (i = 0; i < b->n_channels; i++) {
1667             req->chan2G4[req->chan2G4_cnt].flags = 0;
1668             if (b->channels[i].flags & IEEE80211_CHAN_DISABLED)
1669                 req->chan2G4[req->chan2G4_cnt].flags |= CHAN_DISABLED;
1670             req->chan2G4[req->chan2G4_cnt].flags |= get_chan_flags(b->channels[i].flags);
1671             req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ;
1672             req->chan2G4[req->chan2G4_cnt].freq = b->channels[i].center_freq;
1673             req->chan2G4[req->chan2G4_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power);
1674             req->chan2G4_cnt++;
1675             if (req->chan2G4_cnt == MAC_DOMAINCHANNEL_24G_MAX)
1676                 break;
1677         }
1678     }
1679
1680     req->chan5G_cnt = 0;
1681 #ifdef CONFIG_ECRNX_5G
1682     if (wiphy->bands[NL80211_BAND_5GHZ] != NULL) {
1683         struct ieee80211_supported_band *b = wiphy->bands[NL80211_BAND_5GHZ];
1684         for (i = 0; i < b->n_channels; i++) {
1685             req->chan5G[req->chan5G_cnt].flags = 0;
1686             if (b->channels[i].flags & IEEE80211_CHAN_DISABLED)
1687                 req->chan5G[req->chan5G_cnt].flags |= CHAN_DISABLED;
1688             req->chan5G[req->chan5G_cnt].flags |= get_chan_flags(b->channels[i].flags);
1689             req->chan5G[req->chan5G_cnt].band = NL80211_BAND_5GHZ;
1690             req->chan5G[req->chan5G_cnt].freq = b->channels[i].center_freq;
1691             req->chan5G[req->chan5G_cnt].tx_power = chan_to_fw_pwr(b->channels[i].max_power);
1692             req->chan5G_cnt++;
1693             if (req->chan5G_cnt == MAC_DOMAINCHANNEL_5G_MAX)
1694                 break;
1695         }
1696     }
1697 #endif
1698     /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */
1699     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL);
1700 }
1701
1702 int ecrnx_send_me_set_control_port_req(struct ecrnx_hw *ecrnx_hw, bool opened, u8 sta_idx)
1703 {
1704     struct me_set_control_port_req *req;
1705
1706     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1707
1708     /* Build the ME_SET_CONTROL_PORT_REQ message */
1709     req = ecrnx_msg_zalloc(ME_SET_CONTROL_PORT_REQ, TASK_ME, DRV_TASK_ID,
1710                                    sizeof(struct me_set_control_port_req));
1711     if (!req)
1712         return -ENOMEM;
1713
1714     /* Set parameters for the ME_SET_CONTROL_PORT_REQ message */
1715     req->sta_idx = sta_idx;
1716     req->control_port_open = opened;
1717
1718     /* Send the ME_SET_CONTROL_PORT_REQ message to LMAC FW */
1719     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_SET_CONTROL_PORT_CFM, NULL);
1720 }
1721
1722 int ecrnx_send_me_sta_add(struct ecrnx_hw *ecrnx_hw, struct station_parameters *params,
1723                          const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm)
1724 {
1725     struct me_sta_add_req *req;
1726     u8 *ht_mcs = (u8 *)&params->ht_capa->mcs;
1727     int i;
1728
1729     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1730
1731     /* Build the MM_STA_ADD_REQ message */
1732     req = ecrnx_msg_zalloc(ME_STA_ADD_REQ, TASK_ME, DRV_TASK_ID,
1733                                   sizeof(struct me_sta_add_req));
1734     if (!req)
1735         return -ENOMEM;
1736
1737     /* Set parameters for the MM_STA_ADD_REQ message */
1738     memcpy(&(req->mac_addr.array[0]), mac, ETH_ALEN);
1739
1740     req->rate_set.length = params->supported_rates_len;
1741     for (i = 0; i < params->supported_rates_len; i++)
1742         req->rate_set.array[i] = params->supported_rates[i];
1743
1744     req->flags = 0;
1745
1746 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1747     if (params->capability & WLAN_CAPABILITY_SHORT_PREAMBLE){
1748         req->flags |= STA_SHORT_PREAMBLE_CAPA;
1749     }
1750 #endif
1751
1752     if (params->ht_capa) {
1753         const struct ieee80211_ht_cap *ht_capa = params->ht_capa;
1754
1755         req->flags |= STA_HT_CAPA;
1756         req->ht_cap.ht_capa_info = cpu_to_le16(ht_capa->cap_info);
1757         req->ht_cap.a_mpdu_param = ht_capa->ampdu_params_info;
1758         for (i = 0; i < sizeof(ht_capa->mcs); i++)
1759             req->ht_cap.mcs_rate[i] = ht_mcs[i];
1760         req->ht_cap.ht_extended_capa = cpu_to_le16(ht_capa->extended_ht_cap_info);
1761         req->ht_cap.tx_beamforming_capa = cpu_to_le32(ht_capa->tx_BF_cap_info);
1762         req->ht_cap.asel_capa = ht_capa->antenna_selection_info;
1763     }
1764
1765     if (params->vht_capa) {
1766         const struct ieee80211_vht_cap *vht_capa = params->vht_capa;
1767
1768         req->flags |= STA_VHT_CAPA;
1769         req->vht_cap.vht_capa_info = cpu_to_le32(vht_capa->vht_cap_info);
1770         req->vht_cap.rx_highest = cpu_to_le16(vht_capa->supp_mcs.rx_highest);
1771         req->vht_cap.rx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.rx_mcs_map);
1772         req->vht_cap.tx_highest = cpu_to_le16(vht_capa->supp_mcs.tx_highest);
1773         req->vht_cap.tx_mcs_map = cpu_to_le16(vht_capa->supp_mcs.tx_mcs_map);
1774     }
1775
1776 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)) && defined(CONFIG_ECRNX_HE)
1777     if (params->he_capa) {
1778         const struct ieee80211_he_cap_elem *he_capa = params->he_capa;
1779         struct ieee80211_he_mcs_nss_supp *mcs_nss_supp =
1780                                 (struct ieee80211_he_mcs_nss_supp *)(he_capa + 1);
1781
1782         req->flags |= STA_HE_CAPA;
1783         for (i = 0; i < ARRAY_SIZE(he_capa->mac_cap_info); i++) {
1784             req->he_cap.mac_cap_info[i] = he_capa->mac_cap_info[i];
1785         }
1786         for (i = 0; i < ARRAY_SIZE(he_capa->phy_cap_info); i++) {
1787             req->he_cap.phy_cap_info[i] = he_capa->phy_cap_info[i];
1788         }
1789         req->he_cap.mcs_supp.rx_mcs_80 = mcs_nss_supp->rx_mcs_80;
1790         req->he_cap.mcs_supp.tx_mcs_80 = mcs_nss_supp->tx_mcs_80;
1791         req->he_cap.mcs_supp.rx_mcs_160 = mcs_nss_supp->rx_mcs_160;
1792         req->he_cap.mcs_supp.tx_mcs_160 = mcs_nss_supp->tx_mcs_160;
1793         req->he_cap.mcs_supp.rx_mcs_80p80 = mcs_nss_supp->rx_mcs_80p80;
1794         req->he_cap.mcs_supp.tx_mcs_80p80 = mcs_nss_supp->tx_mcs_80p80;
1795     }
1796
1797 #endif
1798
1799     if (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))
1800         req->flags |= STA_QOS_CAPA;
1801
1802     if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) //  if (sme->mfp == NL80211_MFP_REQUIRED || sme->mfp ==NL80211_MFP_OPTIONAL) //wfa must used  NL80211_MFP_REQUIRED and NL80211_MFP_OPTIONAL
1803         req->flags |= STA_MFP_CAPA;
1804
1805 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
1806     if (params->opmode_notif_used) {
1807         req->flags |= STA_OPMOD_NOTIF;
1808         req->opmode = params->opmode_notif;
1809     }
1810 #endif
1811
1812     req->aid = cpu_to_le16(params->aid);
1813     req->uapsd_queues = params->uapsd_queues;
1814     req->max_sp_len = params->max_sp * 2;
1815     req->vif_idx = inst_nbr;
1816
1817     if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
1818         struct ecrnx_vif *ecrnx_vif = ecrnx_hw->vif_table[inst_nbr];
1819         req->tdls_sta = true;
1820 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1821         if ((params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) &&
1822             !ecrnx_vif->tdls_chsw_prohibited)
1823             req->tdls_chsw_allowed = true;
1824 #endif
1825         if (ecrnx_vif->tdls_status == TDLS_SETUP_RSP_TX)
1826             req->tdls_sta_initiator = true;
1827     }
1828
1829     /* Send the ME_STA_ADD_REQ message to LMAC FW */
1830     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_STA_ADD_CFM, cfm);
1831 }
1832
1833 int ecrnx_send_me_sta_del(struct ecrnx_hw *ecrnx_hw, u8 sta_idx, bool tdls_sta)
1834 {
1835     struct me_sta_del_req *req;
1836
1837     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1838
1839     /* Build the MM_STA_DEL_REQ message */
1840     req = ecrnx_msg_zalloc(ME_STA_DEL_REQ, TASK_ME, DRV_TASK_ID,
1841                           sizeof(struct me_sta_del_req));
1842     if (!req)
1843         return -ENOMEM;
1844
1845     /* Set parameters for the MM_STA_DEL_REQ message */
1846     req->sta_idx = sta_idx;
1847     req->tdls_sta = tdls_sta;
1848
1849     /* Send the ME_STA_DEL_REQ message to LMAC FW */
1850     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_STA_DEL_CFM, NULL);
1851 }
1852
1853 int ecrnx_send_me_traffic_ind(struct ecrnx_hw *ecrnx_hw, u8 sta_idx, bool uapsd, u8 tx_status)
1854 {
1855     struct me_traffic_ind_req *req;
1856
1857     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1858
1859     /* Build the ME_UTRAFFIC_IND_REQ message */
1860     req = ecrnx_msg_zalloc(ME_TRAFFIC_IND_REQ, TASK_ME, DRV_TASK_ID,
1861                           sizeof(struct me_traffic_ind_req));
1862     if (!req)
1863         return -ENOMEM;
1864
1865     /* Set parameters for the ME_TRAFFIC_IND_REQ message */
1866     req->sta_idx = sta_idx;
1867     req->tx_avail = tx_status;
1868     req->uapsd = uapsd;
1869
1870     /* Send the ME_TRAFFIC_IND_REQ to UMAC FW */
1871     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_TRAFFIC_IND_CFM, NULL);
1872 }
1873
1874 int ecrnx_send_twt_request(struct ecrnx_hw *ecrnx_hw,
1875                           u8 setup_type, u8 vif_idx,
1876                           struct twt_conf_tag *conf,
1877                           struct twt_setup_cfm *cfm)
1878 {
1879     struct twt_setup_req *req;
1880
1881     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1882
1883     /* Build the TWT_SETUP_REQ message */
1884     req = ecrnx_msg_zalloc(TWT_SETUP_REQ, TASK_TWT, DRV_TASK_ID,
1885                           sizeof(struct twt_setup_req));
1886     if (!req)
1887         return -ENOMEM;
1888
1889     memcpy(&req->conf, conf, sizeof(req->conf));
1890     req->setup_type = setup_type;
1891     req->vif_idx = vif_idx;
1892
1893     /* Send the TWT_SETUP_REQ message to LMAC FW */
1894     return ecrnx_send_msg(ecrnx_hw, req, 1, TWT_SETUP_CFM, cfm);
1895 }
1896
1897 int ecrnx_send_twt_teardown(struct ecrnx_hw *ecrnx_hw,
1898                            struct twt_teardown_req *twt_teardown,
1899                            struct twt_teardown_cfm *cfm)
1900 {
1901     struct twt_teardown_req *req;
1902
1903     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1904
1905     /* Build the TWT_TEARDOWN_REQ message */
1906     req = ecrnx_msg_zalloc(TWT_TEARDOWN_REQ, TASK_TWT, DRV_TASK_ID,
1907                           sizeof(struct twt_teardown_req));
1908     if (!req)
1909         return -ENOMEM;
1910
1911     memcpy(req, twt_teardown, sizeof(struct twt_teardown_req));
1912
1913     /* Send the TWT_TEARDOWN_REQ message to LMAC FW */
1914     return ecrnx_send_msg(ecrnx_hw, req, 1, TWT_TEARDOWN_CFM, cfm);
1915 }
1916 int ecrnx_send_me_rc_stats(struct ecrnx_hw *ecrnx_hw,
1917                           u8 sta_idx,
1918                           struct me_rc_stats_cfm *cfm)
1919 {
1920     struct me_rc_stats_req *req;
1921
1922     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1923
1924     /* Build the ME_RC_STATS_REQ message */
1925     req = ecrnx_msg_zalloc(ME_RC_STATS_REQ, TASK_ME, DRV_TASK_ID,
1926                                   sizeof(struct me_rc_stats_req));
1927     if (!req)
1928         return -ENOMEM;
1929
1930     /* Set parameters for the ME_RC_STATS_REQ message */
1931     req->sta_idx = sta_idx;
1932
1933     /* Send the ME_RC_STATS_REQ message to LMAC FW */
1934     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_RC_STATS_CFM, cfm);
1935 }
1936
1937 int ecrnx_send_me_rc_set_rate(struct ecrnx_hw *ecrnx_hw,
1938                              u8 sta_idx,
1939                              u16 rate_cfg)
1940 {
1941     struct me_rc_set_rate_req *req;
1942
1943     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1944
1945     /* Build the ME_RC_SET_RATE_REQ message */
1946     req = ecrnx_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID,
1947                           sizeof(struct me_rc_set_rate_req));
1948     if (!req)
1949         return -ENOMEM;
1950
1951     /* Set parameters for the ME_RC_SET_RATE_REQ message */
1952     req->sta_idx = sta_idx;
1953     req->fixed_rate_cfg = rate_cfg;
1954
1955     /* Send the ME_RC_SET_RATE_REQ message to FW */
1956     return ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
1957 }
1958
1959 int ecrnx_send_me_set_ps_mode(struct ecrnx_hw *ecrnx_hw, u8 ps_mode)
1960 {
1961     struct me_set_ps_mode_req *req;
1962
1963     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1964
1965     /* Build the ME_SET_PS_MODE_REQ message */
1966     req = ecrnx_msg_zalloc(ME_SET_PS_MODE_REQ, TASK_ME, DRV_TASK_ID,
1967                           sizeof(struct me_set_ps_mode_req));
1968     if (!req)
1969         return -ENOMEM;
1970
1971     /* Set parameters for the ME_SET_PS_MODE_REQ message */
1972     req->ps_state = ps_mode;
1973
1974     /* Send the ME_SET_PS_MODE_REQ message to FW */
1975     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_SET_PS_MODE_CFM, NULL);
1976 }
1977
1978 int ecrnx_send_sm_connect_req(struct ecrnx_hw *ecrnx_hw,
1979                              struct ecrnx_vif *ecrnx_vif,
1980                              struct cfg80211_connect_params *sme,
1981                              struct sm_connect_cfm *cfm)
1982 {
1983     struct sm_connect_req *req;
1984     int i, ie_len;
1985
1986     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1987
1988     ie_len = update_connect_req(ecrnx_vif, sme);
1989     /* Build the SM_CONNECT_REQ message */
1990     req = ecrnx_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID,
1991                      (sizeof(struct sm_connect_req) + ie_len));
1992     if (!req)
1993         return -ENOMEM;
1994
1995     /* Set parameters for the SM_CONNECT_REQ message */
1996     if (sme->crypto.n_ciphers_pairwise &&
1997         ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) ||
1998          (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) ||
1999          (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)))
2000         req->flags |= DISABLE_HT;
2001
2002     if (sme->crypto.control_port)
2003         req->flags |= CONTROL_PORT_HOST;
2004
2005     if (sme->crypto.control_port_no_encrypt)
2006         req->flags |= CONTROL_PORT_NO_ENC;
2007
2008     if (use_pairwise_key(&sme->crypto))
2009         req->flags |= WPA_WPA2_IN_USE;
2010
2011 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2012     if (sme->mfp == NL80211_MFP_REQUIRED)
2013         req->flags |= MFP_IN_USE;
2014 #endif
2015
2016     req->ctrl_port_ethertype = sme->crypto.control_port_ethertype;
2017
2018     if (sme->bssid)
2019         memcpy(&req->bssid, sme->bssid, ETH_ALEN);
2020     else
2021         req->bssid = mac_addr_bcst;
2022 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
2023     if (sme->prev_bssid)
2024         req->flags |= REASSOCIATION;
2025 #else
2026     if (ecrnx_vif->sta.ap)
2027         req->flags |= REASSOCIATION;
2028 #endif
2029     if ((sme->auth_type == NL80211_AUTHTYPE_FT) && (ecrnx_vif->sta.flags & ECRNX_STA_FT_OVER_DS))
2030         req->flags |= (REASSOCIATION | FT_OVER_DS);
2031     req->vif_idx = ecrnx_vif->vif_index;
2032     if (sme->channel) {
2033         req->chan.band = sme->channel->band;
2034         req->chan.freq = sme->channel->center_freq;
2035         req->chan.flags = get_chan_flags(sme->channel->flags);
2036     } else {
2037         req->chan.freq = (u16_l)-1;
2038     }
2039     for (i = 0; i < sme->ssid_len; i++)
2040         req->ssid.array[i] = sme->ssid[i];
2041     req->ssid.length = sme->ssid_len;
2042
2043     req->listen_interval = ecrnx_mod_params.listen_itv;
2044     req->dont_wait_bcmc = !ecrnx_mod_params.listen_bcmc;
2045
2046     /* Set auth_type */
2047     if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC)
2048         req->auth_type = WLAN_AUTH_OPEN;
2049     else if (sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
2050         req->auth_type = WLAN_AUTH_OPEN;
2051     else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
2052         req->auth_type = WLAN_AUTH_SHARED_KEY;
2053     else if (sme->auth_type == NL80211_AUTHTYPE_FT)
2054         req->auth_type = WLAN_AUTH_FT;
2055     else if (sme->auth_type == NL80211_AUTHTYPE_SAE)
2056         req->auth_type = WLAN_AUTH_SAE;
2057     else
2058         goto invalid_param;
2059     copy_connect_ies(ecrnx_vif, req, sme);
2060
2061     /* Set UAPSD queues */
2062     req->uapsd_queues = ecrnx_mod_params.uapsd_queues;
2063
2064     /* Send the SM_CONNECT_REQ message to LMAC FW */
2065     return ecrnx_send_msg(ecrnx_hw, req, 1, SM_CONNECT_CFM, cfm);
2066
2067 invalid_param:
2068     ecrnx_msg_free(ecrnx_hw, req);
2069     return -EINVAL;
2070 }
2071
2072 int ecrnx_send_sm_disconnect_req(struct ecrnx_hw *ecrnx_hw,
2073                                 struct ecrnx_vif *ecrnx_vif,
2074                                 u16 reason)
2075 {
2076     struct sm_disconnect_req *req;
2077
2078     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2079
2080     /* Build the SM_DISCONNECT_REQ message */
2081     req = ecrnx_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID,
2082                                    sizeof(struct sm_disconnect_req));
2083     if (!req)
2084         return -ENOMEM;
2085
2086     /* Set parameters for the SM_DISCONNECT_REQ message */
2087     req->reason_code = reason;
2088     req->vif_idx = ecrnx_vif->vif_index;
2089
2090     /* Send the SM_DISCONNECT_REQ message to LMAC FW */
2091     return ecrnx_send_msg(ecrnx_hw, req, 1, SM_DISCONNECT_CFM, NULL);
2092 }
2093
2094 int ecrnx_send_sm_external_auth_required_rsp(struct ecrnx_hw *ecrnx_hw,
2095                                             struct ecrnx_vif *ecrnx_vif,
2096                                             u16 status)
2097 {
2098     struct sm_external_auth_required_rsp *rsp;
2099
2100     /* Build the SM_EXTERNAL_AUTH_CFM message */
2101     rsp = ecrnx_msg_zalloc(SM_EXTERNAL_AUTH_REQUIRED_RSP, TASK_SM, DRV_TASK_ID,
2102                           sizeof(struct sm_external_auth_required_rsp));
2103     if (!rsp)
2104         return -ENOMEM;
2105
2106     rsp->status = status;
2107     rsp->vif_idx = ecrnx_vif->vif_index;
2108
2109     /* send the SM_EXTERNAL_AUTH_REQUIRED_RSP message UMAC FW */
2110     return ecrnx_send_msg(ecrnx_hw, rsp, 0, 0, NULL);
2111 }
2112 int ecrnx_send_sm_ft_auth_rsp(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
2113                              uint8_t *ie, int ie_len)
2114 {
2115     struct sm_connect_req *rsp;
2116     rsp = ecrnx_msg_zalloc(SM_FT_AUTH_RSP, TASK_SM, DRV_TASK_ID,
2117                          (sizeof(struct sm_connect_req) + ie_len));
2118     if (!rsp)
2119         return -ENOMEM;
2120     rsp->vif_idx = ecrnx_vif->vif_index;
2121     rsp->ie_len = ie_len;
2122     memcpy(rsp->ie_buf, ie, rsp->ie_len);
2123     return ecrnx_send_msg(ecrnx_hw, rsp, 0, 0, NULL);
2124 }
2125
2126 int ecrnx_send_apm_start_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2127                             struct cfg80211_ap_settings *settings,
2128                             struct apm_start_cfm *cfm,
2129                             struct ecrnx_ipc_elem_var *elem)
2130 {
2131     struct apm_start_req *req;
2132     struct ecrnx_bcn *bcn = &vif->ap.bcn;
2133     u8 *buf;
2134     u32 flags = 0;
2135     const u8 *rate_ie;
2136     u8 rate_len = 0;
2137     int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
2138     const u8 *var_pos;
2139     int len, i, error;
2140
2141     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2142
2143     /* Build the APM_START_REQ message */
2144     req = ecrnx_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID,
2145                                    sizeof(struct apm_start_req));
2146     if (!req)
2147         return -ENOMEM;
2148
2149     // Build the beacon
2150     bcn->dtim = (u8)settings->dtim_period;
2151     buf = ecrnx_build_bcn(bcn, &settings->beacon);
2152     if (!buf) {
2153         ecrnx_msg_free(ecrnx_hw, req);
2154         return -ENOMEM;
2155     }
2156
2157     // Retrieve the basic rate set from the beacon buffer
2158     len = bcn->len - var_offset;
2159     var_pos = buf + var_offset;
2160
2161 // Assume that rate higher that 54 Mbps are BSS membership
2162 #define IS_BASIC_RATE(r) (r & 0x80) && ((r & ~0x80) <= (54 * 2))
2163
2164     rate_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
2165     if (rate_ie) {
2166         const u8 *rates = rate_ie + 2;
2167         for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) {
2168             if (IS_BASIC_RATE(rates[i]))
2169                 req->basic_rates.array[rate_len++] = rates[i];
2170         }
2171     }
2172     rate_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, var_pos, len);
2173     if (rate_ie) {
2174         const u8 *rates = rate_ie + 2;
2175         for (i = 0; (i < rate_ie[1]) && (rate_len < MAC_RATESET_LEN); i++) {
2176             if (IS_BASIC_RATE(rates[i]))
2177                 req->basic_rates.array[rate_len++] = rates[i];
2178         }
2179     }
2180     req->basic_rates.length = rate_len;
2181 #undef IS_BASIC_RATE
2182
2183     // Sync buffer for FW
2184     if ((error = ecrnx_ipc_elem_var_allocs(ecrnx_hw, elem, bcn->len,
2185                                           DMA_TO_DEVICE, buf, NULL, NULL))) {
2186         return error;
2187     }
2188
2189     /* Set parameters for the APM_START_REQ message */
2190     req->vif_idx = vif->vif_index;
2191     req->bcn_addr = elem->dma_addr;
2192     req->bcn_len = bcn->len;
2193     req->tim_oft = bcn->head_len;
2194     req->tim_len = bcn->tim_len;
2195     cfg80211_to_ecrnx_chan(&settings->chandef, &req->chan);
2196     req->bcn_int = settings->beacon_interval;
2197     if (settings->crypto.control_port)
2198         flags |= CONTROL_PORT_HOST;
2199
2200     if (settings->crypto.control_port_no_encrypt)
2201         flags |= CONTROL_PORT_NO_ENC;
2202
2203     if (use_pairwise_key(&settings->crypto))
2204         flags |= WPA_WPA2_IN_USE;
2205
2206     if (settings->crypto.control_port_ethertype)
2207         req->ctrl_port_ethertype = settings->crypto.control_port_ethertype;
2208     else
2209         req->ctrl_port_ethertype = ETH_P_PAE;
2210     req->flags = flags;
2211
2212     /* Send the APM_START_REQ message to LMAC FW */
2213     return ecrnx_send_msg(ecrnx_hw, req, 1, APM_START_CFM, cfm);
2214 }
2215
2216 int ecrnx_send_apm_stop_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif)
2217 {
2218     struct apm_stop_req *req;
2219
2220     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2221
2222     /* Build the APM_STOP_REQ message */
2223     req = ecrnx_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID,
2224                                    sizeof(struct apm_stop_req));
2225     if (!req)
2226         return -ENOMEM;
2227
2228     /* Set parameters for the APM_STOP_REQ message */
2229     req->vif_idx = vif->vif_index;
2230
2231     /* Send the APM_STOP_REQ message to LMAC FW */
2232     return ecrnx_send_msg(ecrnx_hw, req, 1, APM_STOP_CFM, NULL);
2233 }
2234
2235 int ecrnx_send_apm_probe_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2236                             struct ecrnx_sta *sta, struct apm_probe_client_cfm *cfm)
2237 {
2238     struct apm_probe_client_req *req;
2239
2240     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2241
2242     req = ecrnx_msg_zalloc(APM_PROBE_CLIENT_REQ, TASK_APM, DRV_TASK_ID,
2243                           sizeof(struct apm_probe_client_req));
2244     if (!req)
2245         return -ENOMEM;
2246
2247     req->vif_idx = vif->vif_index;
2248     req->sta_idx = sta->sta_idx;
2249
2250     /* Send the APM_PROBE_CLIENT_REQ message to UMAC FW */
2251     return ecrnx_send_msg(ecrnx_hw, req, 1, APM_PROBE_CLIENT_CFM, cfm);
2252 }
2253 int ecrnx_send_scanu_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
2254                         struct cfg80211_scan_request *param)
2255 {
2256     struct scanu_start_req *req;
2257     int i, chan_num = 0;
2258     uint8_t chan_flags = 0;
2259
2260     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2261
2262     /* Build the SCANU_START_REQ message */
2263     req = ecrnx_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID,
2264                           sizeof(struct scanu_start_req));
2265     if (!req)
2266         return -ENOMEM;
2267
2268     /* Set parameters */
2269     req->vif_idx = ecrnx_vif->vif_index;
2270     req->chan_cnt = (u8)min_t(int, SCAN_CHANNEL_MAX, param->n_channels);
2271     req->ssid_cnt = (u8)min_t(int, SCAN_SSID_MAX, param->n_ssids);
2272     req->bssid = mac_addr_bcst;
2273     req->no_cck = param->no_cck;
2274 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
2275     if (param->duration_mandatory)
2276         req->duration = ieee80211_tu_to_usec(param->duration);
2277 #endif
2278
2279     if(param->n_ssids > SCAN_SSID_MAX){
2280         ECRNX_PRINT("%s:n_ssids: %d \n", __func__, param->n_ssids);
2281         for (i = 0; i < param->n_ssids; i++){
2282             print_hex_dump_bytes("[ecrnx]scan_req: ", DUMP_PREFIX_NONE, &param->ssids[i], param->ssids[i].ssid_len);
2283             ECRNX_PRINT("i:%d, ssid_len:%d \n", i, param->ssids[i].ssid_len);
2284         }
2285     }
2286
2287     if (req->ssid_cnt == 0)
2288         chan_flags |= CHAN_NO_IR;
2289     for (i = 0; i < req->ssid_cnt; i++) {
2290         int j;
2291         for (j = 0; j < param->ssids[i].ssid_len; j++)
2292             req->ssid[i].array[j] = param->ssids[i].ssid[j];
2293         req->ssid[i].length = param->ssids[i].ssid_len;
2294     }
2295
2296     if(req->ssid_cnt == 1 && param->ssids[0].ssid_len > 0)
2297     {
2298         if (strcmp(req->ssid[0].array, "DIRECT-"))
2299         {
2300             req->ssid_cnt = 2;
2301             req->ssid[1].length = 0;
2302         }
2303     }
2304
2305     if (param->ie) {
2306
2307         if (ecrnx_ipc_elem_var_allocs(ecrnx_hw, &ecrnx_hw->scan_ie,
2308                                      param->ie_len, DMA_TO_DEVICE,
2309                                      NULL, param->ie, NULL))
2310             goto error;
2311         req->add_ie_len = param->ie_len;
2312         req->add_ies = ecrnx_hw->scan_ie.dma_addr;
2313     } else {
2314         req->add_ie_len = 0;
2315         req->add_ies = 0;
2316     }
2317
2318     for (i = 0; i < req->chan_cnt; i++) {
2319         struct ieee80211_channel *chan = param->channels[i];
2320
2321                 if(chan->band){
2322                         continue;
2323                 }
2324         req->chan[chan_num].band = chan->band;
2325         req->chan[chan_num].freq = chan->center_freq;
2326         req->chan[chan_num].flags = chan_flags | get_chan_flags(chan->flags);
2327         req->chan[chan_num].tx_power = chan_to_fw_pwr(chan->max_reg_power);
2328                 chan_num++;
2329                 //printk("--%d set ch, %d,%d,%d,%d\n", i, req->chan[i].band, req->chan[i].freq, req->chan[i].flags, req->chan[i].tx_power);
2330     }
2331         req->chan_cnt = chan_num;
2332     /* Send the SCANU_START_REQ message to LMAC FW */
2333     return ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2334 error:
2335     if (req != NULL)
2336         ecrnx_msg_free(ecrnx_hw, req);
2337     return -ENOMEM;
2338 }
2339
2340 int ecrnx_send_scanu_cancel_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif)
2341 {
2342     struct scanu_cancel_req *req = NULL;
2343
2344     /* Build the SCANU_START_REQ message */
2345     req = ecrnx_msg_zalloc(SCANU_CANCEL_REQ, TASK_SCANU, DRV_TASK_ID,
2346                           sizeof(struct scanu_cancel_req));
2347     if (!req){
2348         return -ENOMEM;
2349     }
2350
2351     req->vif_idx = ecrnx_vif->vif_index;
2352     ECRNX_PRINT("%s: vif_idx:%d; \n", __func__, req->vif_idx);
2353     return ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2354 }
2355
2356 int ecrnx_send_apm_start_cac_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2357                                 struct cfg80211_chan_def *chandef,
2358                                 struct apm_start_cac_cfm *cfm)
2359 {
2360     struct apm_start_cac_req *req;
2361
2362     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2363
2364     /* Build the APM_START_CAC_REQ message */
2365     req = ecrnx_msg_zalloc(APM_START_CAC_REQ, TASK_APM, DRV_TASK_ID,
2366                           sizeof(struct apm_start_cac_req));
2367     if (!req)
2368         return -ENOMEM;
2369
2370     /* Set parameters for the APM_START_CAC_REQ message */
2371     req->vif_idx = vif->vif_index;
2372     cfg80211_to_ecrnx_chan(chandef, &req->chan);
2373
2374     /* Send the APM_START_CAC_REQ message to LMAC FW */
2375     return ecrnx_send_msg(ecrnx_hw, req, 1, APM_START_CAC_CFM, cfm);
2376 }
2377
2378 int ecrnx_send_apm_stop_cac_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif)
2379 {
2380     struct apm_stop_cac_req *req;
2381
2382     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2383
2384     /* Build the APM_STOP_CAC_REQ message */
2385     req = ecrnx_msg_zalloc(APM_STOP_CAC_REQ, TASK_APM, DRV_TASK_ID,
2386                           sizeof(struct apm_stop_cac_req));
2387     if (!req)
2388         return -ENOMEM;
2389
2390     /* Set parameters for the APM_STOP_CAC_REQ message */
2391     req->vif_idx = vif->vif_index;
2392
2393     /* Send the APM_STOP_CAC_REQ message to LMAC FW */
2394     return ecrnx_send_msg(ecrnx_hw, req, 1, APM_STOP_CAC_CFM, NULL);
2395 }
2396
2397 int ecrnx_send_mesh_start_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2398                              const struct mesh_config *conf, const struct mesh_setup *setup,
2399                              struct mesh_start_cfm *cfm)
2400 {
2401     // Message to send
2402     struct mesh_start_req *req;
2403     // Supported basic rates
2404     struct ieee80211_supported_band *band = ecrnx_hw->wiphy->bands[setup->chandef.chan->band];
2405     /* Counter */
2406     int i;
2407     /* Return status */
2408     int status;
2409     /* DMA Address to be unmapped after confirmation reception */
2410     u32 dma_addr = 0;
2411
2412     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2413
2414     /* Build the MESH_START_REQ message */
2415     req = ecrnx_msg_zalloc(MESH_START_REQ, TASK_MESH, DRV_TASK_ID,
2416                           sizeof(struct mesh_start_req));
2417     if (!req) {
2418         return -ENOMEM;
2419     }
2420
2421     req->vif_index = vif->vif_index;
2422 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2423     req->bcn_int = setup->beacon_interval;
2424     req->dtim_period = setup->dtim_period;
2425 #endif
2426     req->mesh_id_len = setup->mesh_id_len;
2427
2428     for (i = 0; i < setup->mesh_id_len; i++) {
2429         req->mesh_id[i] = *(setup->mesh_id + i);
2430     }
2431
2432 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2433     req->user_mpm = setup->user_mpm;
2434 #endif
2435     req->is_auth = setup->is_authenticated;
2436 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
2437     req->auth_id = setup->auth_id;
2438 #endif
2439     req->ie_len = setup->ie_len;
2440
2441     if (setup->ie_len) {
2442         /*
2443          * Need to provide a Virtual Address to the MAC so that it can download the
2444          * additional information elements.
2445          */
2446         req->ie_addr = dma_map_single(ecrnx_hw->dev, (void *)setup->ie,
2447                                       setup->ie_len, DMA_FROM_DEVICE);
2448
2449         /* Check DMA mapping result */
2450         if (dma_mapping_error(ecrnx_hw->dev, req->ie_addr)) {
2451             ECRNX_ERR(KERN_CRIT "%s - DMA Mapping error on additional IEs\n", __func__);
2452
2453             /* Consider there is no Additional IEs */
2454             req->ie_len = 0;
2455         } else {
2456             /* Store DMA Address so that we can unmap the memory section once MESH_START_CFM is received */
2457             dma_addr = req->ie_addr;
2458         }
2459     }
2460
2461     /* Provide rate information */
2462     req->basic_rates.length = 0;
2463     for (i = 0; i < band->n_bitrates; i++) {
2464         u16 rate = band->bitrates[i].bitrate;
2465
2466         /* Read value is in in units of 100 Kbps, provided value is in units
2467          * of 1Mbps, and multiplied by 2 so that 5.5 becomes 11 */
2468         rate = (rate << 1) / 10;
2469
2470 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
2471         if (setup->basic_rates & CO_BIT(i)) {
2472             rate |= 0x80;
2473         }
2474 #endif
2475
2476         req->basic_rates.array[i] = (u8)rate;
2477         req->basic_rates.length++;
2478     }
2479
2480     /* Provide channel information */
2481     cfg80211_to_ecrnx_chan(&setup->chandef, &req->chan);
2482
2483     /* Send the MESH_START_REQ message to UMAC FW */
2484     status = ecrnx_send_msg(ecrnx_hw, req, 1, MESH_START_CFM, cfm);
2485
2486     /* Unmap DMA area */
2487     if (setup->ie_len) {
2488         dma_unmap_single(ecrnx_hw->dev, dma_addr, setup->ie_len, DMA_TO_DEVICE);
2489     }
2490
2491     /* Return the status */
2492     return (status);
2493 }
2494
2495 int ecrnx_send_mesh_stop_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2496                             struct mesh_stop_cfm *cfm)
2497 {
2498     // Message to send
2499     struct mesh_stop_req *req;
2500
2501     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2502
2503     /* Build the MESH_STOP_REQ message */
2504     req = ecrnx_msg_zalloc(MESH_STOP_REQ, TASK_MESH, DRV_TASK_ID,
2505                           sizeof(struct mesh_stop_req));
2506     if (!req) {
2507         return -ENOMEM;
2508     }
2509
2510     req->vif_idx = vif->vif_index;
2511
2512     /* Send the MESH_STOP_REQ message to UMAC FW */
2513     return ecrnx_send_msg(ecrnx_hw, req, 1, MESH_STOP_CFM, cfm);
2514 }
2515
2516 int ecrnx_send_mesh_update_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2517                               u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm)
2518 {
2519     // Message to send
2520     struct mesh_update_req *req;
2521     // Keep only bit for fields which can be updated
2522     u32 supp_mask = (mask << 1) & (CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS)
2523                                    | CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE)
2524                                    | CO_BIT(NL80211_MESHCONF_FORWARDING)
2525 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2526                                    | CO_BIT(NL80211_MESHCONF_POWER_MODE)
2527 #endif
2528                                    );
2529
2530
2531     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2532
2533     if (!supp_mask) {
2534         return -ENOENT;
2535     }
2536
2537     /* Build the MESH_UPDATE_REQ message */
2538     req = ecrnx_msg_zalloc(MESH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID,
2539                           sizeof(struct mesh_update_req));
2540
2541     if (!req) {
2542         return -ENOMEM;
2543     }
2544
2545     req->vif_idx = vif->vif_index;
2546
2547     if (supp_mask & CO_BIT(NL80211_MESHCONF_GATE_ANNOUNCEMENTS))
2548     {
2549         req->flags |= CO_BIT(MESH_UPDATE_FLAGS_GATE_MODE_BIT);
2550         req->gate_announ = p_mconf->dot11MeshGateAnnouncementProtocol;
2551     }
2552
2553     if (supp_mask & CO_BIT(NL80211_MESHCONF_HWMP_ROOTMODE))
2554     {
2555         req->flags |= CO_BIT(MESH_UPDATE_FLAGS_ROOT_MODE_BIT);
2556         req->root_mode = p_mconf->dot11MeshHWMPRootMode;
2557     }
2558
2559     if (supp_mask & CO_BIT(NL80211_MESHCONF_FORWARDING))
2560     {
2561         req->flags |= CO_BIT(MESH_UPDATE_FLAGS_MESH_FWD_BIT);
2562         req->mesh_forward = p_mconf->dot11MeshForwarding;
2563     }
2564 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2565     if (supp_mask & CO_BIT(NL80211_MESHCONF_POWER_MODE))
2566     {
2567         req->flags |= CO_BIT(MESH_UPDATE_FLAGS_LOCAL_PSM_BIT);
2568         req->local_ps_mode = p_mconf->power_mode;
2569     }
2570 #endif
2571     /* Send the MESH_UPDATE_REQ message to UMAC FW */
2572     return ecrnx_send_msg(ecrnx_hw, req, 1, MESH_UPDATE_CFM, cfm);
2573 }
2574
2575 int ecrnx_send_mesh_peer_info_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2576                                  u8 sta_idx, struct mesh_peer_info_cfm *cfm)
2577 {
2578     // Message to send
2579     struct mesh_peer_info_req *req;
2580
2581     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2582
2583     /* Build the MESH_PEER_INFO_REQ message */
2584     req = ecrnx_msg_zalloc(MESH_PEER_INFO_REQ, TASK_MESH, DRV_TASK_ID,
2585                           sizeof(struct mesh_peer_info_req));
2586     if (!req) {
2587         return -ENOMEM;
2588     }
2589
2590     req->sta_idx = sta_idx;
2591
2592     /* Send the MESH_PEER_INFO_REQ message to UMAC FW */
2593     return ecrnx_send_msg(ecrnx_hw, req, 1, MESH_PEER_INFO_CFM, cfm);
2594 }
2595
2596 void ecrnx_send_mesh_peer_update_ntf(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif,
2597                                     u8 sta_idx, u8 mlink_state)
2598 {
2599     // Message to send
2600     struct mesh_peer_update_ntf *ntf;
2601
2602     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2603
2604     /* Build the MESH_PEER_UPDATE_NTF message */
2605     ntf = ecrnx_msg_zalloc(MESH_PEER_UPDATE_NTF, TASK_MESH, DRV_TASK_ID,
2606                           sizeof(struct mesh_peer_update_ntf));
2607
2608     if (ntf) {
2609         ntf->vif_idx = vif->vif_index;
2610         ntf->sta_idx = sta_idx;
2611         ntf->state = mlink_state;
2612
2613         /* Send the MESH_PEER_INFO_REQ message to UMAC FW */
2614         ecrnx_send_msg(ecrnx_hw, ntf, 0, 0, NULL);
2615     }
2616 }
2617
2618 void ecrnx_send_mesh_path_create_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif, u8 *tgt_addr)
2619 {
2620     struct mesh_path_create_req *req;
2621     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2622
2623     /* Check if we are already waiting for a confirmation */
2624     if (vif->ap.flags & ECRNX_AP_CREATE_MESH_PATH)
2625         return;
2626
2627         /* Build the MESH_PATH_CREATE_REQ message */
2628     req = ecrnx_msg_zalloc(MESH_PATH_CREATE_REQ, TASK_MESH, DRV_TASK_ID,
2629                               sizeof(struct mesh_path_create_req));
2630     if (!req)
2631         return;
2632
2633     req->vif_idx = vif->vif_index;
2634     memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN);
2635
2636     vif->ap.flags |= ECRNX_AP_CREATE_MESH_PATH;
2637
2638     /* Send the MESH_PATH_CREATE_REQ message to UMAC FW */
2639     ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2640 }
2641
2642 int ecrnx_send_mesh_path_update_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif, const u8 *tgt_addr,
2643                                    const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm)
2644 {
2645     // Message to send
2646     struct mesh_path_update_req *req;
2647
2648     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2649
2650     /* Build the MESH_PATH_UPDATE_REQ message */
2651     req = ecrnx_msg_zalloc(MESH_PATH_UPDATE_REQ, TASK_MESH, DRV_TASK_ID,
2652                           sizeof(struct mesh_path_update_req));
2653     if (!req) {
2654         return -ENOMEM;
2655     }
2656
2657     req->delete = (p_nhop_addr == NULL);
2658     req->vif_idx = vif->vif_index;
2659     memcpy(&req->tgt_mac_addr, tgt_addr, ETH_ALEN);
2660
2661     if (p_nhop_addr) {
2662         memcpy(&req->nhop_mac_addr, p_nhop_addr, ETH_ALEN);
2663     }
2664
2665     /* Send the MESH_PATH_UPDATE_REQ message to UMAC FW */
2666     return ecrnx_send_msg(ecrnx_hw, req, 1, MESH_PATH_UPDATE_CFM, cfm);
2667 }
2668
2669 void ecrnx_send_mesh_proxy_add_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *vif, u8 *ext_addr)
2670 {
2671     // Message to send
2672     struct mesh_proxy_add_req *req;
2673
2674     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2675
2676     /* Build the MESH_PROXY_ADD_REQ message */
2677     req = ecrnx_msg_zalloc(MESH_PROXY_ADD_REQ, TASK_MESH, DRV_TASK_ID,
2678                           sizeof(struct mesh_proxy_add_req));
2679
2680     if (req) {
2681         req->vif_idx = vif->vif_index;
2682         memcpy(&req->ext_sta_addr, ext_addr, ETH_ALEN);
2683
2684         /* Send the MESH_PROXY_ADD_REQ message to UMAC FW */
2685         ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2686     }
2687 }
2688
2689 int ecrnx_send_tdls_peer_traffic_ind_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif)
2690 {
2691     struct tdls_peer_traffic_ind_req *tdls_peer_traffic_ind_req;
2692
2693     if (!ecrnx_vif->sta.tdls_sta)
2694         return -ENOLINK;
2695
2696     /* Build the TDLS_PEER_TRAFFIC_IND_REQ message */
2697     tdls_peer_traffic_ind_req = ecrnx_msg_zalloc(TDLS_PEER_TRAFFIC_IND_REQ, TASK_TDLS, DRV_TASK_ID,
2698                                            sizeof(struct tdls_peer_traffic_ind_req));
2699
2700     if (!tdls_peer_traffic_ind_req)
2701         return -ENOMEM;
2702
2703     /* Set parameters for the TDLS_PEER_TRAFFIC_IND_REQ message */
2704     tdls_peer_traffic_ind_req->vif_index = ecrnx_vif->vif_index;
2705     tdls_peer_traffic_ind_req->sta_idx = ecrnx_vif->sta.tdls_sta->sta_idx;
2706     memcpy(&(tdls_peer_traffic_ind_req->peer_mac_addr.array[0]),
2707            ecrnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN);
2708     tdls_peer_traffic_ind_req->dialog_token = 0; // check dialog token value
2709     tdls_peer_traffic_ind_req->last_tid = ecrnx_vif->sta.tdls_sta->tdls.last_tid;
2710     tdls_peer_traffic_ind_req->last_sn = ecrnx_vif->sta.tdls_sta->tdls.last_sn;
2711
2712     /* Send the TDLS_PEER_TRAFFIC_IND_REQ message to LMAC FW */
2713     return ecrnx_send_msg(ecrnx_hw, tdls_peer_traffic_ind_req, 0, 0, NULL);
2714 }
2715
2716 int ecrnx_send_config_monitor_req(struct ecrnx_hw *ecrnx_hw,
2717                                  struct cfg80211_chan_def *chandef,
2718                                  struct me_config_monitor_cfm *cfm)
2719 {
2720     struct me_config_monitor_req *req;
2721
2722     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2723
2724     /* Build the ME_CONFIG_MONITOR_REQ message */
2725     req = ecrnx_msg_zalloc(ME_CONFIG_MONITOR_REQ, TASK_ME, DRV_TASK_ID,
2726                                    sizeof(struct me_config_monitor_req));
2727     if (!req)
2728         return -ENOMEM;
2729
2730     if (chandef) {
2731         req->chan_set = true;
2732         cfg80211_to_ecrnx_chan(chandef, &req->chan);
2733
2734         if (ecrnx_hw->phy.limit_bw)
2735             limit_chan_bw(&req->chan.type, req->chan.prim20_freq, &req->chan.center1_freq);
2736     } else {
2737          req->chan_set = false;
2738     }
2739
2740     req->uf = ecrnx_hw->mod_params->uf;
2741
2742     /* Send the ME_CONFIG_MONITOR_REQ message to FW */
2743     return ecrnx_send_msg(ecrnx_hw, req, 1, ME_CONFIG_MONITOR_CFM, cfm);
2744 }
2745 #endif /* CONFIG_ECRNX_FULLMAC */
2746
2747 #ifdef CONFIG_ECRNX_P2P
2748 int ecrnx_send_p2p_start_listen_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif, unsigned int duration)
2749 {
2750         struct p2p_listen_start_req *req;
2751         struct ecrnx_p2p_listen *p2p_listen = &ecrnx_hw->p2p_listen;
2752         int rc;
2753         
2754         ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2755
2756         if(p2p_listen->listen_started)
2757         {
2758                 ECRNX_ERR("P2P listen already ongoing\n");
2759                 return -EBUSY;
2760         }
2761
2762         p2p_listen->ecrnx_vif = ecrnx_vif;
2763         p2p_listen->listen_duration = duration;
2764         
2765         if(ecrnx_hw->scan_request)
2766         {
2767                 ECRNX_ERR("Delaying p2p listen until scan done\n");
2768                 return 0;
2769         }
2770         
2771         /* Build the P2P_LISTEN_START_REQ message */
2772     req = ecrnx_msg_zalloc(P2P_LISTEN_START_REQ, TASK_P2P_LISTEN, DRV_TASK_ID,
2773                                                         sizeof(struct p2p_listen_start_req));
2774     if (!req)
2775         return -ENOMEM;
2776
2777     req->vif_idx = ecrnx_vif->vif_index;
2778
2779     rc = ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2780     if(rc)
2781         return rc;
2782
2783     p2p_listen->listen_started = 1;
2784
2785     return rc;
2786 }
2787
2788 int ecrnx_send_p2p_cancel_listen_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif)
2789 {
2790     struct p2p_cancel_listen_req *req;
2791     struct ecrnx_p2p_listen *p2p_listen = &ecrnx_hw->p2p_listen;
2792         
2793     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2794
2795         /* Build the P2P_CANCEL_LISTEN_REQ message */
2796     req = ecrnx_msg_zalloc(P2P_CANCEL_LISTEN_REQ, TASK_P2P_LISTEN, DRV_TASK_ID,
2797                                                         sizeof(struct p2p_cancel_listen_req));
2798     if (!req)
2799         return -ENOMEM;
2800
2801     req->vif_idx = ecrnx_vif->vif_index;
2802     p2p_listen->listen_started = 0;
2803     //return rwnx_send_msg(rwnx_hw, req, 1, P2P_CANCEL_LISTEN_CFM, NULL);
2804     ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
2805
2806     return 0;
2807
2808 }
2809 #endif
2810
2811 int ecrnx_send_tdls_chan_switch_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_vif *ecrnx_vif,
2812                                    struct ecrnx_sta *ecrnx_sta, bool sta_initiator,
2813                                    u8 oper_class, struct cfg80211_chan_def *chandef,
2814                                    struct tdls_chan_switch_cfm *cfm)
2815 {
2816     struct tdls_chan_switch_req *tdls_chan_switch_req;
2817
2818 #ifdef CONFIG_ECRNX_SOFTMAC
2819     /* Check if channel switch already enabled on a TDLS peer */
2820     if (ecrnx_hw->tdls_info.chsw_en) {
2821         ECRNX_ERR("TDLS channel switch already enabled for another TDLS station\n");
2822         return -ENOTSUPP;
2823     }
2824 #endif
2825
2826     /* Build the TDLS_CHAN_SWITCH_REQ message */
2827     tdls_chan_switch_req = ecrnx_msg_zalloc(TDLS_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID,
2828                                            sizeof(struct tdls_chan_switch_req));
2829
2830     if (!tdls_chan_switch_req)
2831         return -ENOMEM;
2832
2833     /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */
2834     tdls_chan_switch_req->vif_index = ecrnx_vif->vif_index;
2835     tdls_chan_switch_req->sta_idx = ecrnx_sta->sta_idx;
2836     memcpy(&(tdls_chan_switch_req->peer_mac_addr.array[0]),
2837            ecrnx_sta_addr(ecrnx_sta), ETH_ALEN);
2838     tdls_chan_switch_req->initiator = sta_initiator;
2839     cfg80211_to_ecrnx_chan(chandef, &tdls_chan_switch_req->chan);
2840     tdls_chan_switch_req->op_class = oper_class;
2841
2842     /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */
2843     return ecrnx_send_msg(ecrnx_hw, tdls_chan_switch_req, 1, TDLS_CHAN_SWITCH_CFM, cfm);
2844 }
2845
2846 int ecrnx_send_tdls_cancel_chan_switch_req(struct ecrnx_hw *ecrnx_hw,
2847                                           struct ecrnx_vif *ecrnx_vif,
2848                                           struct ecrnx_sta *ecrnx_sta,
2849                                           struct tdls_cancel_chan_switch_cfm *cfm)
2850 {
2851     struct tdls_cancel_chan_switch_req *tdls_cancel_chan_switch_req;
2852
2853     /* Build the TDLS_CHAN_SWITCH_REQ message */
2854     tdls_cancel_chan_switch_req = ecrnx_msg_zalloc(TDLS_CANCEL_CHAN_SWITCH_REQ, TASK_TDLS, DRV_TASK_ID,
2855                                            sizeof(struct tdls_cancel_chan_switch_req));
2856     if (!tdls_cancel_chan_switch_req)
2857         return -ENOMEM;
2858
2859     /* Set parameters for the TDLS_CHAN_SWITCH_REQ message */
2860     tdls_cancel_chan_switch_req->vif_index = ecrnx_vif->vif_index;
2861     tdls_cancel_chan_switch_req->sta_idx = ecrnx_sta->sta_idx;
2862     memcpy(&(tdls_cancel_chan_switch_req->peer_mac_addr.array[0]),
2863            ecrnx_sta_addr(ecrnx_sta), ETH_ALEN);
2864
2865     /* Send the TDLS_CHAN_SWITCH_REQ message to LMAC FW */
2866     return ecrnx_send_msg(ecrnx_hw, tdls_cancel_chan_switch_req, 1, TDLS_CANCEL_CHAN_SWITCH_CFM, cfm);
2867 }
2868
2869 #ifdef CONFIG_ECRNX_BFMER
2870 #ifdef CONFIG_ECRNX_SOFTMAC
2871 void ecrnx_send_bfmer_enable(struct ecrnx_hw *ecrnx_hw, struct ieee80211_sta *sta)
2872 #else
2873 void ecrnx_send_bfmer_enable(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *ecrnx_sta,
2874                             const struct ieee80211_vht_cap *vht_cap)
2875 #endif /* CONFIG_ECRNX_SOFTMAC*/
2876 {
2877     struct mm_bfmer_enable_req *bfmer_en_req;
2878 #ifdef CONFIG_ECRNX_SOFTMAC
2879     struct ecrnx_sta *ecrnx_sta = (struct ecrnx_sta *)&sta->drv_priv;
2880     u32 vht_capability;
2881 #else
2882     __le32 vht_capability;
2883     u8 rx_nss = 0;
2884 #endif /* CONFIG_ECRNX_SOFTMAC */
2885
2886     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2887
2888 #ifdef CONFIG_ECRNX_SOFTMAC
2889     if (!sta->vht_cap.vht_supported) {
2890 #else
2891     if (!vht_cap) {
2892 #endif /* CONFIG_ECRNX_SOFTMAC */
2893         goto end;
2894     }
2895
2896 #ifdef CONFIG_ECRNX_SOFTMAC
2897     vht_capability = sta->vht_cap.cap;
2898 #else
2899     vht_capability = vht_cap->vht_cap_info;
2900 #endif /* CONFIG_ECRNX_SOFTMAC */
2901
2902     if (!(vht_capability & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) {
2903         goto end;
2904     }
2905
2906 #ifdef CONFIG_ECRNX_FULLMAC
2907     rx_nss = ecrnx_bfmer_get_rx_nss(vht_cap);
2908 #endif /* CONFIG_ECRNX_FULLMAC */
2909
2910     /* Allocate a structure that will contain the beamforming report */
2911     if (ecrnx_bfmer_report_add(ecrnx_hw, ecrnx_sta, ECRNX_BFMER_REPORT_SPACE_SIZE))
2912     {
2913         goto end;
2914     }
2915
2916     /* Build the MM_BFMER_ENABLE_REQ message */
2917     bfmer_en_req = ecrnx_msg_zalloc(MM_BFMER_ENABLE_REQ, TASK_MM, DRV_TASK_ID,
2918                                    sizeof(struct mm_bfmer_enable_req));
2919
2920     /* Check message allocation */
2921     if (!bfmer_en_req) {
2922         /* Free memory allocated for the report */
2923         ecrnx_bfmer_report_del(ecrnx_hw, ecrnx_sta);
2924
2925         /* Do not use beamforming */
2926         goto end;
2927     }
2928
2929     /* Provide DMA address to the MAC */
2930     bfmer_en_req->host_bfr_addr = ecrnx_sta->bfm_report->dma_addr;
2931     bfmer_en_req->host_bfr_size = ECRNX_BFMER_REPORT_SPACE_SIZE;
2932     bfmer_en_req->sta_idx = ecrnx_sta->sta_idx;
2933 #ifdef CONFIG_ECRNX_SOFTMAC
2934     bfmer_en_req->aid = sta->aid;
2935     bfmer_en_req->rx_nss = sta->rx_nss;
2936 #else
2937     bfmer_en_req->aid = ecrnx_sta->aid;
2938     bfmer_en_req->rx_nss = rx_nss;
2939 #endif /* CONFIG_ECRNX_SOFTMAC */
2940
2941     if (vht_capability & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) {
2942         bfmer_en_req->vht_mu_bfmee = true;
2943     } else {
2944         bfmer_en_req->vht_mu_bfmee = false;
2945     }
2946
2947     /* Send the MM_BFMER_EN_REQ message to LMAC FW */
2948     ecrnx_send_msg(ecrnx_hw, bfmer_en_req, 0, 0, NULL);
2949
2950 end:
2951     return;
2952 }
2953
2954 #ifdef CONFIG_ECRNX_MUMIMO_TX
2955 int ecrnx_send_mu_group_update_req(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *ecrnx_sta)
2956 {
2957     struct mm_mu_group_update_req *req;
2958     int group_id, i = 0;
2959     u64 map;
2960
2961     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
2962
2963     /* Build the MM_MU_GROUP_UPDATE_REQ message */
2964     req = ecrnx_msg_zalloc(MM_MU_GROUP_UPDATE_REQ, TASK_MM, DRV_TASK_ID,
2965                           sizeof(struct mm_mu_group_update_req) +
2966                           ecrnx_sta->group_info.cnt * sizeof(req->groups[0]));
2967
2968     /* Check message allocation */
2969     if (!req)
2970         return -ENOMEM;
2971
2972     /* Go through the groups the STA belongs to */
2973     group_sta_for_each(ecrnx_sta, group_id, map) {
2974         int user_pos = ecrnx_mu_group_sta_get_pos(ecrnx_hw, ecrnx_sta, group_id);
2975
2976         if (WARN((i >= ecrnx_sta->group_info.cnt),
2977                  "STA%d: Too much group (%d)\n",
2978                  ecrnx_sta->sta_idx, i + 1))
2979             break;
2980
2981         req->groups[i].group_id = group_id;
2982         req->groups[i].user_pos = user_pos;
2983
2984         i++;
2985     }
2986
2987     req->group_cnt = ecrnx_sta->group_info.cnt;
2988     req->sta_idx = ecrnx_sta->sta_idx;
2989
2990     /* Send the MM_MU_GROUP_UPDATE_REQ message to LMAC FW */
2991     return ecrnx_send_msg(ecrnx_hw, req, 1, MM_MU_GROUP_UPDATE_CFM, NULL);
2992 }
2993 #endif /* CONFIG_ECRNX_MUMIMO_TX */
2994 #endif /* CONFIG_ECRNX_BFMER */
2995
2996 /**********************************************************************
2997  *    Debug Messages
2998  *********************************************************************/
2999 int ecrnx_send_dbg_trigger_req(struct ecrnx_hw *ecrnx_hw, char *msg)
3000 {
3001     struct mm_dbg_trigger_req *req;
3002
3003     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3004
3005     /* Build the MM_DBG_TRIGGER_REQ message */
3006     req = ecrnx_msg_zalloc(MM_DBG_TRIGGER_REQ, TASK_MM, DRV_TASK_ID,
3007                           sizeof(struct mm_dbg_trigger_req));
3008     if (!req)
3009         return -ENOMEM;
3010
3011     /* Set parameters for the MM_DBG_TRIGGER_REQ message */
3012     strncpy(req->error, msg, sizeof(req->error));
3013
3014     /* Send the MM_DBG_TRIGGER_REQ message to LMAC FW */
3015     return ecrnx_send_msg(ecrnx_hw, req, 0, -1, NULL);
3016 }
3017
3018 int ecrnx_send_dbg_mem_read_req(struct ecrnx_hw *ecrnx_hw, u32 mem_addr,
3019                                struct dbg_mem_read_cfm *cfm)
3020 {
3021     struct dbg_mem_read_req *mem_read_req;
3022
3023     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3024
3025     /* Build the DBG_MEM_READ_REQ message */
3026     mem_read_req = ecrnx_msg_zalloc(DBG_MEM_READ_REQ, TASK_DBG, DRV_TASK_ID,
3027                                    sizeof(struct dbg_mem_read_req));
3028     if (!mem_read_req)
3029         return -ENOMEM;
3030
3031     /* Set parameters for the DBG_MEM_READ_REQ message */
3032     mem_read_req->memaddr = mem_addr;
3033
3034     /* Send the DBG_MEM_READ_REQ message to LMAC FW */
3035     return ecrnx_send_msg(ecrnx_hw, mem_read_req, 1, DBG_MEM_READ_CFM, cfm);
3036 }
3037
3038 int ecrnx_send_dbg_mem_write_req(struct ecrnx_hw *ecrnx_hw, u32 mem_addr,
3039                                 u32 mem_data)
3040 {
3041     struct dbg_mem_write_req *mem_write_req;
3042
3043     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3044
3045     /* Build the DBG_MEM_WRITE_REQ message */
3046     mem_write_req = ecrnx_msg_zalloc(DBG_MEM_WRITE_REQ, TASK_DBG, DRV_TASK_ID,
3047                                     sizeof(struct dbg_mem_write_req));
3048     if (!mem_write_req)
3049         return -ENOMEM;
3050
3051     /* Set parameters for the DBG_MEM_WRITE_REQ message */
3052     mem_write_req->memaddr = mem_addr;
3053     mem_write_req->memdata = mem_data;
3054
3055     /* Send the DBG_MEM_WRITE_REQ message to LMAC FW */
3056     return ecrnx_send_msg(ecrnx_hw, mem_write_req, 1, DBG_MEM_WRITE_CFM, NULL);
3057 }
3058
3059 int ecrnx_send_dbg_set_mod_filter_req(struct ecrnx_hw *ecrnx_hw, u32 filter)
3060 {
3061     struct dbg_set_mod_filter_req *set_mod_filter_req;
3062
3063     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3064
3065     /* Build the DBG_SET_MOD_FILTER_REQ message */
3066     set_mod_filter_req =
3067         ecrnx_msg_zalloc(DBG_SET_MOD_FILTER_REQ, TASK_DBG, DRV_TASK_ID,
3068                         sizeof(struct dbg_set_mod_filter_req));
3069     if (!set_mod_filter_req)
3070         return -ENOMEM;
3071
3072     /* Set parameters for the DBG_SET_MOD_FILTER_REQ message */
3073     set_mod_filter_req->mod_filter = filter;
3074
3075     /* Send the DBG_SET_MOD_FILTER_REQ message to LMAC FW */
3076     return ecrnx_send_msg(ecrnx_hw, set_mod_filter_req, 1, DBG_SET_MOD_FILTER_CFM, NULL);
3077 }
3078
3079 int ecrnx_send_dbg_set_sev_filter_req(struct ecrnx_hw *ecrnx_hw, u32 filter)
3080 {
3081     struct dbg_set_sev_filter_req *set_sev_filter_req;
3082
3083     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3084
3085     /* Build the DBG_SET_SEV_FILTER_REQ message */
3086     set_sev_filter_req =
3087         ecrnx_msg_zalloc(DBG_SET_SEV_FILTER_REQ, TASK_DBG, DRV_TASK_ID,
3088                         sizeof(struct dbg_set_sev_filter_req));
3089     if (!set_sev_filter_req)
3090         return -ENOMEM;
3091
3092     /* Set parameters for the DBG_SET_SEV_FILTER_REQ message */
3093     set_sev_filter_req->sev_filter = filter;
3094
3095     /* Send the DBG_SET_SEV_FILTER_REQ message to LMAC FW */
3096     return ecrnx_send_msg(ecrnx_hw, set_sev_filter_req, 1, DBG_SET_SEV_FILTER_CFM, NULL);
3097 }
3098
3099 int ecrnx_send_dbg_get_sys_stat_req(struct ecrnx_hw *ecrnx_hw,
3100                                    struct dbg_get_sys_stat_cfm *cfm)
3101 {
3102     void *req;
3103
3104     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3105
3106     /* Allocate the message */
3107     req = ecrnx_msg_zalloc(DBG_GET_SYS_STAT_REQ, TASK_DBG, DRV_TASK_ID, 0);
3108     if (!req)
3109         return -ENOMEM;
3110
3111     /* Send the DBG_MEM_READ_REQ message to LMAC FW */
3112     return ecrnx_send_msg(ecrnx_hw, req, 1, DBG_GET_SYS_STAT_CFM, cfm);
3113 }
3114
3115 int ecrnx_send_cfg_rssi_req(struct ecrnx_hw *ecrnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst)
3116 {
3117     struct mm_cfg_rssi_req *req;
3118
3119     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3120
3121     /* Build the MM_CFG_RSSI_REQ message */
3122     req = ecrnx_msg_zalloc(MM_CFG_RSSI_REQ, TASK_MM, DRV_TASK_ID,
3123                           sizeof(struct mm_cfg_rssi_req));
3124     if (!req)
3125         return -ENOMEM;
3126
3127     /* Set parameters for the MM_CFG_RSSI_REQ message */
3128     req->vif_index = vif_index;
3129     req->rssi_thold = (s8)rssi_thold;
3130     req->rssi_hyst = (u8)rssi_hyst;
3131
3132     /* Send the MM_CFG_RSSI_REQ message to LMAC FW */
3133     return ecrnx_send_msg(ecrnx_hw, req, 0, 0, NULL);
3134 }
3135
3136 extern bool set_gain;
3137 int ecrnx_send_set_gain_delta_req(struct ecrnx_hw *ecrnx_hw)
3138 {
3139         s8_l *delta;
3140
3141     if (set_gain != true)
3142         return -ENOMEM;
3143
3144     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3145
3146     /* Build the MM_SET_GAIN_DELTA_REQ message */
3147     delta = ecrnx_msg_zalloc(MM_SET_GAIN_DELTA_REQ, TASK_MM, DRV_TASK_ID,
3148                           GAIN_DELTA_CFG_BUF_SIZE);
3149     if (!delta)
3150         return -ENOMEM;
3151
3152     /* Set parameters for the MM_SET_GAIN_DELTA_REQ message */
3153     memset(delta, 0, GAIN_DELTA_CFG_BUF_SIZE);
3154     memcpy(delta, gain_delta, GAIN_DELTA_CFG_BUF_SIZE);
3155
3156     /* Send the MM_SET_GAIN_DELTA_REQ message to LMAC FW */
3157     return ecrnx_send_msg(ecrnx_hw, delta, 0, MM_SET_GAIN_DELTA_CFM, NULL);
3158 }
3159
3160 int ecrnx_send_cal_result_get_req(struct ecrnx_hw *ecrnx_hw, void *cfm)
3161 {
3162     void *void_param;
3163
3164         ECRNX_DBG(ECRNX_FN_ENTRY_STR);
3165     /* calibration result get REQ has no parameter */
3166     void_param = ecrnx_msg_zalloc(MM_GET_CAL_RESULT_REQ, TASK_MM, DRV_TASK_ID, 0);
3167     if (!void_param)
3168         return -ENOMEM;
3169
3170     return ecrnx_send_msg(ecrnx_hw, void_param, 1, MM_GET_CAL_RESULT_CFM, cfm);
3171 }
3172
3173