net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_mod_params.c
1 /**
2 ******************************************************************************
3 *
4 * @file ecrnx_mod_params.c
5 *
6 * @brief Set configuration according to modules parameters
7 *
8 * Copyright (C) ESWIN 2015-2020
9 *
10 ******************************************************************************
11 */
12 #include <linux/module.h>
13 #include <linux/rtnetlink.h>
14
15 #include "ecrnx_defs.h"
16 #include "ecrnx_tx.h"
17 #include "hal_desc.h"
18 #include "ecrnx_cfgfile.h"
19 #include "reg_access.h"
20 #include "ecrnx_compat.h"
21
22 #ifdef CONFIG_ECRNX_SOFTMAC
23 #define COMMON_PARAM(name, default_softmac, default_fullmac)    \
24     .name = default_softmac,
25 #define SOFTMAC_PARAM(name, default) .name = default,
26 #define FULLMAC_PARAM(name, default)
27 #else
28 #define COMMON_PARAM(name, default_softmac, default_fullmac)    \
29     .name = default_fullmac,
30 #define SOFTMAC_PARAM(name, default)
31 #define FULLMAC_PARAM(name, default) .name = default,
32 #endif /* CONFIG_ECRNX_SOFTMAC */
33
34 struct ecrnx_mod_params ecrnx_mod_params = {
35     /* common parameters */
36     COMMON_PARAM(ht_on, true, true)
37     COMMON_PARAM(vht_on, false, false)
38     COMMON_PARAM(he_on, true, true)
39 #ifdef CONFIG_6600_HAL
40     COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_7, IEEE80211_HE_MCS_SUPPORT_0_7)
41 #else
42     COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9, IEEE80211_HE_MCS_SUPPORT_0_9)
43 #endif
44     COMMON_PARAM(he_ul_on, false, false)
45     COMMON_PARAM(ldpc_on, false, false)
46     COMMON_PARAM(stbc_on, false, false)
47     COMMON_PARAM(gf_rx_on, true, true)
48     COMMON_PARAM(phy_cfg, 0, 0)
49     COMMON_PARAM(uapsd_timeout, 300, 300)
50     COMMON_PARAM(ap_uapsd_on, true, true)
51     COMMON_PARAM(sgi, true, true)
52     COMMON_PARAM(sgi80, true, true)
53     COMMON_PARAM(use_2040, 1, 1)
54     COMMON_PARAM(nss, 1, 1)
55     COMMON_PARAM(amsdu_rx_max, 2, 2)
56     COMMON_PARAM(bfmee, true, true)
57     COMMON_PARAM(bfmer, true, true)
58     COMMON_PARAM(mesh, true, true)
59     COMMON_PARAM(murx, true, true)
60     COMMON_PARAM(mutx, true, true)
61     COMMON_PARAM(mutx_on, true, true)
62     COMMON_PARAM(use_80, false, false)
63     COMMON_PARAM(custregd, false, false)
64     COMMON_PARAM(custchan, false, false)
65     COMMON_PARAM(roc_dur_max, 500, 500)
66     COMMON_PARAM(listen_itv, 0, 0)
67     COMMON_PARAM(listen_bcmc, true, true)
68     COMMON_PARAM(lp_clk_ppm, 20, 20)
69     COMMON_PARAM(ps_on, true, true)
70     COMMON_PARAM(tx_lft, ECRNX_TX_LIFETIME_MS, ECRNX_TX_LIFETIME_MS)
71     COMMON_PARAM(amsdu_maxnb, NX_TX_PAYLOAD_MAX, NX_TX_PAYLOAD_MAX)
72     // By default, only enable UAPSD for Voice queue (see IEEE80211_DEFAULT_UAPSD_QUEUE comment)
73     COMMON_PARAM(uapsd_queues, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO, IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
74     COMMON_PARAM(tdls, true, true)
75     COMMON_PARAM(uf, true, true)
76     COMMON_PARAM(ftl, "", "")
77     COMMON_PARAM(dpsm, true, true)
78     COMMON_PARAM(tx_to_bk, 0, 0)
79     COMMON_PARAM(tx_to_be, 0, 0)
80     COMMON_PARAM(tx_to_vi, 0, 0)
81     COMMON_PARAM(tx_to_vo, 0, 0)
82
83     /* SOFTMAC only parameters */
84     SOFTMAC_PARAM(mfp_on, false)
85     SOFTMAC_PARAM(gf_on, false)
86     SOFTMAC_PARAM(bwsig_on, true)
87     SOFTMAC_PARAM(dynbw_on, true)
88     SOFTMAC_PARAM(agg_tx, true)
89     SOFTMAC_PARAM(amsdu_force, 0)
90     SOFTMAC_PARAM(rc_probes_on, false)
91     SOFTMAC_PARAM(cmon, true)
92     SOFTMAC_PARAM(hwscan, true)
93     SOFTMAC_PARAM(autobcn, true)
94
95     /* FULLMAC only parameters */
96     FULLMAC_PARAM(ant_div, false)
97 };
98
99 #ifdef CONFIG_ECRNX_SOFTMAC
100 /* SOFTMAC specific parameters */
101 module_param_named(mfp_on, ecrnx_mod_params.mfp_on, bool, S_IRUGO);
102 MODULE_PARM_DESC(mfp_on, "Enable MFP (11w) (Default: 0)");
103
104 module_param_named(gf_on, ecrnx_mod_params.gf_on, bool, S_IRUGO | S_IWUSR);
105 MODULE_PARM_DESC(gf_on, "Try TXing Green Field if peer supports it (Default: 0)");
106
107 module_param_named(bwsig_on, ecrnx_mod_params.bwsig_on, bool, S_IRUGO | S_IWUSR);
108 MODULE_PARM_DESC(bwsig_on, "Enable bandwidth signaling (VHT tx) (Default: 1)");
109
110 module_param_named(dynbw_on, ecrnx_mod_params.dynbw_on, bool, S_IRUGO | S_IWUSR);
111 MODULE_PARM_DESC(dynbw_on, "Enable dynamic bandwidth (VHT tx) (Default: 1)");
112
113 module_param_named(agg_tx, ecrnx_mod_params.agg_tx, bool, S_IRUGO);
114 MODULE_PARM_DESC(agg_tx, "Use A-MPDU in TX (Default: 1)");
115
116 module_param_named(amsdu_force, ecrnx_mod_params.amsdu_force, int, S_IRUGO | S_IWUSR);
117 MODULE_PARM_DESC(amsdu_force, "Use A-MSDU in TX: 0-if advertised, 1-yes, 2-no (Default: 0)");
118
119 module_param_named(rc_probes_on, ecrnx_mod_params.rc_probes_on, bool, S_IRUGO | S_IWUSR);
120 MODULE_PARM_DESC(rc_probes_on, "IEEE80211_TX_CTL_RATE_CTRL_PROBE is 1st in AMPDU (Default: 0)");
121
122 module_param_named(cmon, ecrnx_mod_params.cmon, bool, S_IRUGO);
123 MODULE_PARM_DESC(cmon, "Connection monitoring work handled by the FW (Default: 1)");
124
125 module_param_named(hwscan, ecrnx_mod_params.hwscan, bool, S_IRUGO);
126 MODULE_PARM_DESC(hwscan, "Scan work handled by the FW (Default: 1)");
127
128 module_param_named(autobcn, ecrnx_mod_params.autobcn, bool, S_IRUGO);
129 MODULE_PARM_DESC(autobcn, "Beacon transmission done autonomously by the FW (Default: 1)");
130
131 #else
132 /* FULLMAC specific parameters*/
133 module_param_named(ant_div, ecrnx_mod_params.ant_div, bool, S_IRUGO);
134 MODULE_PARM_DESC(ant_div, "Enable Antenna Diversity (Default: 0)");
135 #endif /* CONFIG_ECRNX_SOFTMAC */
136
137 module_param_named(ht_on, ecrnx_mod_params.ht_on, bool, S_IRUGO);
138 MODULE_PARM_DESC(ht_on, "Enable HT (Default: 1)");
139
140 module_param_named(vht_on, ecrnx_mod_params.vht_on, bool, S_IRUGO);
141 MODULE_PARM_DESC(vht_on, "Enable VHT (Default: 1)");
142
143 module_param_named(he_on, ecrnx_mod_params.he_on, bool, S_IRUGO);
144 MODULE_PARM_DESC(he_on, "Enable HE (Default: 1)");
145
146 module_param_named(mcs_map, ecrnx_mod_params.mcs_map, int, S_IRUGO);
147 MODULE_PARM_DESC(mcs_map,  "VHT MCS map value  0: MCS0_7, 1: MCS0_8, 2: MCS0_9"
148                  " (Default: 2)");
149
150 module_param_named(he_mcs_map, ecrnx_mod_params.he_mcs_map, int, S_IRUGO);
151 MODULE_PARM_DESC(he_mcs_map,  "HE MCS map value  0: MCS0_7, 1: MCS0_9, 2: MCS0_11"
152                  " (Default: 2)");
153
154 module_param_named(he_ul_on, ecrnx_mod_params.he_ul_on, bool, S_IRUGO);
155 MODULE_PARM_DESC(he_ul_on, "Enable HE OFDMA UL (Default: 0)");
156
157 module_param_named(amsdu_maxnb, ecrnx_mod_params.amsdu_maxnb, int, S_IRUGO | S_IWUSR);
158 MODULE_PARM_DESC(amsdu_maxnb, "Maximum number of MSDUs inside an A-MSDU in TX: (Default: NX_TX_PAYLOAD_MAX)");
159
160 module_param_named(ps_on, ecrnx_mod_params.ps_on, bool, S_IRUGO);
161 MODULE_PARM_DESC(ps_on, "Enable PowerSaving (Default: 1-Enabled)");
162
163 module_param_named(tx_lft, ecrnx_mod_params.tx_lft, int, 0644);
164 MODULE_PARM_DESC(tx_lft, "Tx lifetime (ms) - setting it to 0 disables retries "
165                  "(Default: "__stringify(ECRNX_TX_LIFETIME_MS)")");
166
167 module_param_named(ldpc_on, ecrnx_mod_params.ldpc_on, bool, S_IRUGO);
168 MODULE_PARM_DESC(ldpc_on, "Enable LDPC (Default: 1)");
169
170 module_param_named(stbc_on, ecrnx_mod_params.stbc_on, bool, S_IRUGO);
171 MODULE_PARM_DESC(stbc_on, "Enable STBC in RX (Default: 1)");
172
173 module_param_named(gf_rx_on, ecrnx_mod_params.gf_rx_on, bool, S_IRUGO);
174 MODULE_PARM_DESC(gf_rx_on, "Enable HT greenfield in reception (Default: 1)");
175
176 module_param_named(phycfg, ecrnx_mod_params.phy_cfg, int, S_IRUGO);
177 MODULE_PARM_DESC(phycfg, "Main RF Path (Default: 0)");
178
179 module_param_named(uapsd_timeout, ecrnx_mod_params.uapsd_timeout, int, S_IRUGO | S_IWUSR);
180 MODULE_PARM_DESC(uapsd_timeout,
181                  "UAPSD Timer timeout, in ms (Default: 300). If 0, UAPSD is disabled");
182
183 module_param_named(uapsd_queues, ecrnx_mod_params.uapsd_queues, int, S_IRUGO | S_IWUSR);
184 MODULE_PARM_DESC(uapsd_queues, "UAPSD Queues, integer value, must be seen as a bitfield\n"
185                  "        Bit 0 = VO\n"
186                  "        Bit 1 = VI\n"
187                  "        Bit 2 = BK\n"
188                  "        Bit 3 = BE\n"
189                  "     -> uapsd_queues=7 will enable uapsd for VO, VI and BK queues");
190
191 module_param_named(ap_uapsd_on, ecrnx_mod_params.ap_uapsd_on, bool, S_IRUGO);
192 MODULE_PARM_DESC(ap_uapsd_on, "Enable UAPSD in AP mode (Default: 1)");
193
194 module_param_named(sgi, ecrnx_mod_params.sgi, bool, S_IRUGO);
195 MODULE_PARM_DESC(sgi, "Advertise Short Guard Interval support (Default: 1)");
196
197 module_param_named(sgi80, ecrnx_mod_params.sgi80, bool, S_IRUGO);
198 MODULE_PARM_DESC(sgi80, "Advertise Short Guard Interval support for 80MHz (Default: 1)");
199
200 module_param_named(use_2040, ecrnx_mod_params.use_2040, bool, S_IRUGO);
201 MODULE_PARM_DESC(use_2040, "Enable 40MHz (Default: 1)");
202
203 module_param_named(use_80, ecrnx_mod_params.use_80, bool, S_IRUGO);
204 MODULE_PARM_DESC(use_80, "Enable 80MHz (Default: 1)");
205
206 module_param_named(custregd, ecrnx_mod_params.custregd, bool, S_IRUGO);
207 MODULE_PARM_DESC(custregd,
208                  "Use permissive custom regulatory rules (for testing ONLY) (Default: 0)");
209
210 module_param_named(custchan, ecrnx_mod_params.custchan, bool, S_IRUGO);
211 MODULE_PARM_DESC(custchan,
212                  "Extend channel set to non-standard channels (for testing ONLY) (Default: 0)");
213
214 module_param_named(nss, ecrnx_mod_params.nss, int, S_IRUGO);
215 MODULE_PARM_DESC(nss, "1 <= nss <= 2 : Supported number of Spatial Streams (Default: 2)");
216
217 module_param_named(amsdu_rx_max, ecrnx_mod_params.amsdu_rx_max, int, S_IRUGO);
218 MODULE_PARM_DESC(amsdu_rx_max, "0 <= amsdu_rx_max <= 2 : Maximum A-MSDU size supported in RX\n"
219                  "        0: 3895 bytes\n"
220                  "        1: 7991 bytes\n"
221                  "        2: 11454 bytes\n"
222                  "        This value might be reduced according to the FW capabilities.\n"
223                  "        Default: 2");
224
225 module_param_named(bfmee, ecrnx_mod_params.bfmee, bool, S_IRUGO);
226 MODULE_PARM_DESC(bfmee, "Enable Beamformee Capability (Default: 1-Enabled)");
227
228 module_param_named(bfmer, ecrnx_mod_params.bfmer, bool, S_IRUGO);
229 MODULE_PARM_DESC(bfmer, "Enable Beamformer Capability (Default: 1-Enabled)");
230
231 module_param_named(mesh, ecrnx_mod_params.mesh, bool, S_IRUGO);
232 MODULE_PARM_DESC(mesh, "Enable Meshing Capability (Default: 1-Enabled)");
233
234 module_param_named(murx, ecrnx_mod_params.murx, bool, S_IRUGO);
235 MODULE_PARM_DESC(murx, "Enable MU-MIMO RX Capability (Default: 1-Enabled)");
236
237 module_param_named(mutx, ecrnx_mod_params.mutx, bool, S_IRUGO);
238 MODULE_PARM_DESC(mutx, "Enable MU-MIMO TX Capability (Default: 1-Enabled)");
239
240 module_param_named(mutx_on, ecrnx_mod_params.mutx_on, bool, S_IRUGO | S_IWUSR);
241 MODULE_PARM_DESC(mutx_on, "Enable MU-MIMO transmissions (Default: 1-Enabled)");
242
243 module_param_named(roc_dur_max, ecrnx_mod_params.roc_dur_max, int, S_IRUGO);
244 MODULE_PARM_DESC(roc_dur_max, "Maximum Remain on Channel duration");
245
246 module_param_named(listen_itv, ecrnx_mod_params.listen_itv, int, S_IRUGO);
247 MODULE_PARM_DESC(listen_itv, "Maximum listen interval");
248
249 module_param_named(listen_bcmc, ecrnx_mod_params.listen_bcmc, bool, S_IRUGO);
250 MODULE_PARM_DESC(listen_bcmc, "Wait for BC/MC traffic following DTIM beacon");
251
252 module_param_named(lp_clk_ppm, ecrnx_mod_params.lp_clk_ppm, int, S_IRUGO);
253 MODULE_PARM_DESC(lp_clk_ppm, "Low Power Clock accuracy of the local device");
254
255 module_param_named(tdls, ecrnx_mod_params.tdls, bool, S_IRUGO);
256 MODULE_PARM_DESC(tdls, "Enable TDLS (Default: 1-Enabled)");
257
258 module_param_named(uf, ecrnx_mod_params.uf, bool, S_IRUGO | S_IWUSR);
259 MODULE_PARM_DESC(uf, "Enable Unsupported HT Frame Logging (Default: 1-Enabled)");
260
261 module_param_named(ftl, ecrnx_mod_params.ftl, charp, S_IRUGO);
262 MODULE_PARM_DESC(ftl, "Firmware trace level  (Default: \"\")");
263
264 module_param_named(dpsm, ecrnx_mod_params.dpsm, bool, S_IRUGO);
265 MODULE_PARM_DESC(dpsm, "Enable Dynamic PowerSaving (Default: 1-Enabled)");
266 module_param_named(tx_to_bk, ecrnx_mod_params.tx_to_bk, int, S_IRUGO);
267 MODULE_PARM_DESC(tx_to_bk,
268      "TX timeout for BK, in ms (Default: 0, Max: 65535). If 0, default value is applied");
269 module_param_named(tx_to_be, ecrnx_mod_params.tx_to_be, int, S_IRUGO);
270 MODULE_PARM_DESC(tx_to_be,
271      "TX timeout for BE, in ms (Default: 0, Max: 65535). If 0, default value is applied");
272 module_param_named(tx_to_vi, ecrnx_mod_params.tx_to_vi, int, S_IRUGO);
273 MODULE_PARM_DESC(tx_to_vi,
274      "TX timeout for VI, in ms (Default: 0, Max: 65535). If 0, default value is applied");
275 module_param_named(tx_to_vo, ecrnx_mod_params.tx_to_vo, int, S_IRUGO);
276 MODULE_PARM_DESC(tx_to_vo,
277      "TX timeout for VO, in ms (Default: 0, Max: 65535). If 0, default value is applied");
278
279 /* Regulatory rules */
280 static struct ieee80211_regdomain ecrnx_regdom = {
281     .n_reg_rules = 2,
282     .alpha2 = "99",
283     .reg_rules = {
284         REG_RULE(2390 - 10, 2510 + 10, 40, 0, 1000, 0),
285         REG_RULE(5150 - 10, 5970 + 10, 80, 0, 1000, 0),
286     }
287 };
288
289 static const int mcs_map_to_rate[4][3] = {
290     [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_7] = 65,
291     [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_8] = 78,
292     [PHY_CHNL_BW_20][IEEE80211_VHT_MCS_SUPPORT_0_9] = 78,
293     [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_7] = 135,
294     [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_8] = 162,
295     [PHY_CHNL_BW_40][IEEE80211_VHT_MCS_SUPPORT_0_9] = 180,
296     [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_7] = 292,
297     [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_8] = 351,
298     [PHY_CHNL_BW_80][IEEE80211_VHT_MCS_SUPPORT_0_9] = 390,
299     [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_7] = 585,
300     [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_8] = 702,
301     [PHY_CHNL_BW_160][IEEE80211_VHT_MCS_SUPPORT_0_9] = 780,
302 };
303
304 #define MAX_VHT_RATE(map, nss, bw) (mcs_map_to_rate[bw][map] * (nss))
305
306 #if defined(CONFIG_ECRNX_HE)
307 struct ieee80211_sta_he_cap ecrnx_he_cap;
308 #endif
309
310 /**
311  * Do some sanity check
312  *
313  */
314 static int ecrnx_check_fw_hw_feature(struct ecrnx_hw *ecrnx_hw,
315                                     struct wiphy *wiphy)
316 {
317     u32_l sys_feat = ecrnx_hw->version_cfm.features;
318     u32_l mac_feat = ecrnx_hw->version_cfm.version_machw_1;
319     u32_l phy_feat = ecrnx_hw->version_cfm.version_phy_1;
320     u32_l phy_vers = ecrnx_hw->version_cfm.version_phy_2;
321     u16_l max_sta_nb = ecrnx_hw->version_cfm.max_sta_nb;
322     u8_l max_vif_nb = ecrnx_hw->version_cfm.max_vif_nb;
323     int bw, res = 0;
324     int amsdu_rx;
325
326     if (!ecrnx_hw->mod_params->custregd)
327         ecrnx_hw->mod_params->custchan = false;
328
329     if (ecrnx_hw->mod_params->custchan) {
330 #ifdef CONFIG_ECRNX_SOFTMAC
331         ecrnx_hw->mod_params->autobcn = false;
332         ecrnx_hw->mod_params->hwscan = false;
333         sys_feat &= ~BIT(MM_FEAT_CMON_BIT);
334 #endif
335         ecrnx_hw->mod_params->mesh = false;
336         ecrnx_hw->mod_params->tdls = false;
337     }
338
339 #ifdef CONFIG_ECRNX_SOFTMAC
340     if (sys_feat & BIT(MM_FEAT_UMAC_BIT)) {
341         wiphy_err(wiphy, "Loading fullmac firmware with softmac driver\n");
342         res = -1;
343     }
344
345     if (sys_feat & BIT(MM_FEAT_AUTOBCN_BIT) &&
346         !ecrnx_hw->mod_params->autobcn) {
347         wiphy_err(wiphy,
348                   "Auto beacon enabled in firmware but disabled in driver\n");
349         res = -1;
350     }
351
352     if (!!(sys_feat & BIT(MM_FEAT_HWSCAN_BIT)) !=
353         !!ecrnx_hw->mod_params->hwscan) {
354         wiphy_err(wiphy,
355                   "hwscan %sabled in firmware but %sabled in driver\n",
356                   (sys_feat & BIT(MM_FEAT_HWSCAN_BIT)) ? "en" : "dis",
357                    ecrnx_hw->mod_params->hwscan ? "en" : "dis");
358         res = -1;
359     }
360
361     if (sys_feat & BIT(MM_FEAT_CMON_BIT)) {
362         ieee80211_hw_set(ecrnx_hw->hw, CONNECTION_MONITOR);
363     }
364
365     /* AMPDU (non)support implies different shared structure definition
366        so insure that fw and drv have consistent compilation option */
367     if (sys_feat & BIT(MM_FEAT_AMPDU_BIT)) {
368 #ifndef CONFIG_ECRNX_AGG_TX
369         wiphy_err(wiphy,
370                   "AMPDU enabled in firmware but support not compiled in driver\n");
371         res = -1;
372 #endif /* CONFIG_ECRNX_AGG_TX */
373     } else {
374 #ifdef CONFIG_ECRNX_AGG_TX
375         wiphy_err(wiphy,
376                   "AMPDU disabled in firmware but support compiled in driver\n");
377         res = -1;
378 #else
379         ecrnx_hw->mod_params->agg_tx = false;
380 #endif /* CONFIG_ECRNX_AGG_TX */
381     }
382
383     if (!(sys_feat & BIT(MM_FEAT_DPSM_BIT))) {
384         ecrnx_hw->mod_params->dpsm = false;
385     }
386
387 #else /* check for FULLMAC */
388
389     if (!(sys_feat & BIT(MM_FEAT_UMAC_BIT))) {
390         wiphy_err(wiphy,
391                   "Loading softmac firmware with fullmac driver\n");
392         res = -1;
393     }
394
395     if (!(sys_feat & BIT(MM_FEAT_ANT_DIV_BIT))) {
396         ecrnx_hw->mod_params->ant_div = false;
397     }
398
399 #endif /* CONFIG_ECRNX_SOFTMAC */
400
401     if (!(sys_feat & BIT(MM_FEAT_VHT_BIT))) {
402         ecrnx_hw->mod_params->vht_on = false;
403     }
404
405     // Check if HE is supported
406     if (!(sys_feat & BIT(MM_FEAT_HE_BIT))) {
407         ecrnx_hw->mod_params->he_on = false;
408         ecrnx_hw->mod_params->he_ul_on = false;
409     }
410
411     if (!(sys_feat & BIT(MM_FEAT_PS_BIT))) {
412         ecrnx_hw->mod_params->ps_on = false;
413     }
414
415     /* AMSDU (non)support implies different shared structure definition
416        so insure that fw and drv have consistent compilation option */
417     if (sys_feat & BIT(MM_FEAT_AMSDU_BIT)) {
418 #ifndef CONFIG_ECRNX_SPLIT_TX_BUF
419         wiphy_err(wiphy,
420                   "AMSDU enabled in firmware but support not compiled in driver\n");
421         res = -1;
422 #else
423         /* Adjust amsdu_maxnb so that it stays in allowed bounds */
424         ecrnx_adjust_amsdu_maxnb(ecrnx_hw);
425 #endif /* CONFIG_ECRNX_SPLIT_TX_BUF */
426     } else {
427 #ifdef CONFIG_ECRNX_SPLIT_TX_BUF
428         wiphy_err(wiphy,
429                   "AMSDU disabled in firmware but support compiled in driver\n");
430         res = -1;
431 #endif /* CONFIG_ECRNX_SPLIT_TX_BUF */
432     }
433
434     if (!(sys_feat & BIT(MM_FEAT_UAPSD_BIT))) {
435         ecrnx_hw->mod_params->uapsd_timeout = 0;
436     }
437
438     if (!(sys_feat & BIT(MM_FEAT_BFMEE_BIT))) {
439         ecrnx_hw->mod_params->bfmee = false;
440     }
441
442     if ((sys_feat & BIT(MM_FEAT_BFMER_BIT))) {
443 #ifndef CONFIG_ECRNX_BFMER
444         wiphy_err(wiphy,
445                   "BFMER enabled in firmware but support not compiled in driver\n");
446         res = -1;
447 #endif /* CONFIG_ECRNX_BFMER */
448         // Check PHY and MAC HW BFMER support and update parameter accordingly
449         if (!(phy_feat & MDM_BFMER_BIT) || !(mac_feat & NXMAC_BFMER_BIT)) {
450             ecrnx_hw->mod_params->bfmer = false;
451             // Disable the feature in the bitfield so that it won't be displayed
452             sys_feat &= ~BIT(MM_FEAT_BFMER_BIT);
453         }
454     } else {
455 #ifdef CONFIG_ECRNX_BFMER
456         wiphy_err(wiphy,
457                   "BFMER disabled in firmware but support compiled in driver\n");
458         res = -1;
459 #else
460         ecrnx_hw->mod_params->bfmer = false;
461 #endif /* CONFIG_ECRNX_BFMER */
462     }
463
464     if (!(sys_feat & BIT(MM_FEAT_MESH_BIT))) {
465         ecrnx_hw->mod_params->mesh = false;
466     }
467
468     if (!(sys_feat & BIT(MM_FEAT_TDLS_BIT))) {
469         ecrnx_hw->mod_params->tdls = false;
470     }
471
472     if (!(sys_feat & BIT(MM_FEAT_UF_BIT))) {
473         ecrnx_hw->mod_params->uf = false;
474     }
475
476 #ifdef CONFIG_ECRNX_FULLMAC
477     if ((sys_feat & BIT(MM_FEAT_MON_DATA_BIT))) {
478 #ifndef CONFIG_ECRNX_MON_DATA
479         wiphy_err(wiphy,
480                   "Monitor+Data interface support (MON_DATA) is enabled in firmware but support not compiled in driver\n");
481         res = -1;
482 #endif /* CONFIG_ECRNX_MON_DATA */
483     } else {
484 #ifdef CONFIG_ECRNX_MON_DATA
485         wiphy_err(wiphy,
486                   "Monitor+Data interface support (MON_DATA) disabled in firmware but support compiled in driver\n");
487         res = -1;
488 #endif /* CONFIG_ECRNX_MON_DATA */
489     }
490 #endif
491
492     // Check supported AMSDU RX size
493     amsdu_rx = (sys_feat >> MM_AMSDU_MAX_SIZE_BIT0) & 0x03;
494     if (amsdu_rx < ecrnx_hw->mod_params->amsdu_rx_max) {
495         ecrnx_hw->mod_params->amsdu_rx_max = amsdu_rx;
496     }
497
498     // Check supported BW
499     bw = (phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB;
500     // Check if 80MHz BW is supported
501     if (bw < 2) {
502         ecrnx_hw->mod_params->use_80 = false;
503     }
504     // Check if 40MHz BW is supported
505     if (bw < 1)
506         ecrnx_hw->mod_params->use_2040 = false;
507
508     // 80MHz BW shall be disabled if 40MHz is not enabled
509     if (!ecrnx_hw->mod_params->use_2040)
510         ecrnx_hw->mod_params->use_80 = false;
511
512     // Check if HT is supposed to be supported. If not, disable VHT/HE too
513     if (!ecrnx_hw->mod_params->ht_on)
514     {
515         ecrnx_hw->mod_params->vht_on = false;
516         ecrnx_hw->mod_params->he_on = false;
517         ecrnx_hw->mod_params->he_ul_on = false;
518         ecrnx_hw->mod_params->use_80 = false;
519         ecrnx_hw->mod_params->use_2040 = false;
520     }
521
522     // LDPC is mandatory for HE40 and above, so if LDPC is not supported, then disable
523     // HE to use HT/VHT only
524     if (ecrnx_hw->mod_params->he_on && !ecrnx_hw->mod_params->ldpc_on)
525     {
526         ecrnx_hw->mod_params->use_80 = false;
527         /* ESWIN turns off 40M automotically when it is HE mode  */
528         //ecrnx_hw->mod_params->use_2040 = false;
529
530     }
531
532     // HT greenfield is not supported in modem >= 3.0
533     if (__MDM_MAJOR_VERSION(phy_vers) > 0) {
534 #ifdef CONFIG_ECRNX_SOFTMAC
535         ecrnx_hw->mod_params->gf_on = false;
536 #endif
537         ecrnx_hw->mod_params->gf_rx_on = false;
538     }
539
540     if (!(sys_feat & BIT(MM_FEAT_MU_MIMO_RX_BIT)) ||
541         !ecrnx_hw->mod_params->bfmee) {
542         ecrnx_hw->mod_params->murx = false;
543     }
544
545     if ((sys_feat & BIT(MM_FEAT_MU_MIMO_TX_BIT))) {
546 #ifndef CONFIG_ECRNX_MUMIMO_TX
547         wiphy_err(wiphy,
548                   "MU-MIMO TX enabled in firmware but support not compiled in driver\n");
549         res = -1;
550 #endif /* CONFIG_ECRNX_MUMIMO_TX */
551         if (!ecrnx_hw->mod_params->bfmer)
552             ecrnx_hw->mod_params->mutx = false;
553         // Check PHY and MAC HW MU-MIMO TX support and update parameter accordingly
554         else if (!(phy_feat & MDM_MUMIMOTX_BIT) || !(mac_feat & NXMAC_MU_MIMO_TX_BIT)) {
555                 ecrnx_hw->mod_params->mutx = false;
556                 // Disable the feature in the bitfield so that it won't be displayed
557                 sys_feat &= ~BIT(MM_FEAT_MU_MIMO_TX_BIT);
558         }
559     } else {
560 #ifdef CONFIG_ECRNX_MUMIMO_TX
561         wiphy_err(wiphy,
562                   "MU-MIMO TX disabled in firmware but support compiled in driver\n");
563         res = -1;
564 #else
565         ecrnx_hw->mod_params->mutx = false;
566 #endif /* CONFIG_ECRNX_MUMIMO_TX */
567     }
568
569     if (sys_feat & BIT(MM_FEAT_WAPI_BIT)) {
570         ecrnx_enable_wapi(ecrnx_hw);
571     }
572
573 #ifdef CONFIG_ECRNX_FULLMAC
574     if (sys_feat & BIT(MM_FEAT_MFP_BIT)) {
575         ecrnx_enable_mfp(ecrnx_hw);
576     }
577     if (mac_feat & NXMAC_GCMP_BIT) {
578         ecrnx_enable_gcmp(ecrnx_hw);
579     }
580 #endif
581
582 #ifdef CONFIG_ECRNX_SOFTMAC
583 #define QUEUE_NAME "BEACON queue "
584 #else
585 #define QUEUE_NAME "Broadcast/Multicast queue "
586 #endif /* CONFIG_ECRNX_SOFTMAC */
587
588     if (sys_feat & BIT(MM_FEAT_BCN_BIT)) {
589 #if NX_TXQ_CNT == 4
590         wiphy_err(wiphy, QUEUE_NAME
591                   "enabled in firmware but support not compiled in driver\n");
592         res = -1;
593 #endif /* NX_TXQ_CNT == 4 */
594     } else {
595 #if NX_TXQ_CNT == 5
596         wiphy_err(wiphy, QUEUE_NAME
597                   "disabled in firmware but support compiled in driver\n");
598         res = -1;
599 #endif /* NX_TXQ_CNT == 5 */
600     }
601 #undef QUEUE_NAME
602
603 #ifdef CONFIG_ECRNX_RADAR
604     if (sys_feat & BIT(MM_FEAT_RADAR_BIT)) {
605         /* Enable combination with radar detection */
606         wiphy->n_iface_combinations++;
607     }
608 #endif /* CONFIG_ECRNX_RADAR */
609
610 #ifndef CONFIG_ECRNX_SDM
611     switch (__MDM_PHYCFG_FROM_VERS(phy_feat)) {
612         case MDM_PHY_CONFIG_TRIDENT:
613             ecrnx_hw->mod_params->nss = 1;
614             if ((ecrnx_hw->mod_params->phy_cfg < 0) || (ecrnx_hw->mod_params->phy_cfg > 2))
615                 ecrnx_hw->mod_params->phy_cfg = 2;
616             break;
617         case MDM_PHY_CONFIG_KARST:
618         case MDM_PHY_CONFIG_CATAXIA:
619             {
620                 int nss_supp = (phy_feat & MDM_NSS_MASK) >> MDM_NSS_LSB;
621                 if (ecrnx_hw->mod_params->nss > nss_supp)
622                     ecrnx_hw->mod_params->nss = nss_supp;
623                 if ((ecrnx_hw->mod_params->phy_cfg < 0) || (ecrnx_hw->mod_params->phy_cfg > 1))
624                     ecrnx_hw->mod_params->phy_cfg = 0;
625             }
626             break;
627         default:
628             WARN_ON(1);
629             break;
630     }
631 #endif /* CONFIG_ECRNX_SDM */
632
633     if ((ecrnx_hw->mod_params->nss < 1) || (ecrnx_hw->mod_params->nss > 2))
634         ecrnx_hw->mod_params->nss = 1;
635
636
637     if ((ecrnx_hw->mod_params->mcs_map < 0) || (ecrnx_hw->mod_params->mcs_map > 2))
638         ecrnx_hw->mod_params->mcs_map = 0;
639
640 #define PRINT_ECRNX_PHY_FEAT(feat)                                   \
641     (phy_feat & MDM_##feat##_BIT ? "["#feat"]" : "")
642     wiphy_info(wiphy, "PHY features: [NSS=%d][CHBW=%d]%s%s%s%s%s%s%s\n",
643                (phy_feat & MDM_NSS_MASK) >> MDM_NSS_LSB,
644                20 * (1 << ((phy_feat & MDM_CHBW_MASK) >> MDM_CHBW_LSB)),
645                (phy_feat & (MDM_LDPCDEC_BIT | MDM_LDPCENC_BIT)) ==
646                        (MDM_LDPCDEC_BIT | MDM_LDPCENC_BIT) ? "[LDPC]" : "",
647                PRINT_ECRNX_PHY_FEAT(VHT),
648                PRINT_ECRNX_PHY_FEAT(HE),
649                PRINT_ECRNX_PHY_FEAT(BFMER),
650                PRINT_ECRNX_PHY_FEAT(BFMEE),
651                PRINT_ECRNX_PHY_FEAT(MUMIMOTX),
652                PRINT_ECRNX_PHY_FEAT(MUMIMORX)
653                );
654
655 #define PRINT_ECRNX_FEAT(feat)                                   \
656     (sys_feat & BIT(MM_FEAT_##feat##_BIT) ? "["#feat"]" : "")
657
658     wiphy_info(wiphy, "FW features: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
659                PRINT_ECRNX_FEAT(BCN),
660                PRINT_ECRNX_FEAT(AUTOBCN),
661                PRINT_ECRNX_FEAT(HWSCAN),
662                PRINT_ECRNX_FEAT(CMON),
663                PRINT_ECRNX_FEAT(MROLE),
664                PRINT_ECRNX_FEAT(RADAR),
665                PRINT_ECRNX_FEAT(PS),
666                PRINT_ECRNX_FEAT(UAPSD),
667                PRINT_ECRNX_FEAT(DPSM),
668                PRINT_ECRNX_FEAT(AMPDU),
669                PRINT_ECRNX_FEAT(AMSDU),
670                PRINT_ECRNX_FEAT(CHNL_CTXT),
671                PRINT_ECRNX_FEAT(REORD),
672                PRINT_ECRNX_FEAT(P2P),
673                PRINT_ECRNX_FEAT(P2P_GO),
674                PRINT_ECRNX_FEAT(UMAC),
675                PRINT_ECRNX_FEAT(VHT),
676                PRINT_ECRNX_FEAT(HE),
677                PRINT_ECRNX_FEAT(BFMEE),
678                PRINT_ECRNX_FEAT(BFMER),
679                PRINT_ECRNX_FEAT(WAPI),
680                PRINT_ECRNX_FEAT(MFP),
681                PRINT_ECRNX_FEAT(MU_MIMO_RX),
682                PRINT_ECRNX_FEAT(MU_MIMO_TX),
683                PRINT_ECRNX_FEAT(MESH),
684                PRINT_ECRNX_FEAT(TDLS),
685                PRINT_ECRNX_FEAT(ANT_DIV),
686                PRINT_ECRNX_FEAT(UF),
687                PRINT_ECRNX_FEAT(TWT));
688 #undef PRINT_ECRNX_FEAT
689
690     if(max_sta_nb != NX_REMOTE_STA_MAX)
691     {
692         wiphy_err(wiphy, "Different number of supported stations between driver and FW (%d != %d)\n",
693                   NX_REMOTE_STA_MAX, max_sta_nb);
694         res = -1;
695     }
696
697     if(max_vif_nb != NX_VIRT_DEV_MAX)
698     {
699         wiphy_err(wiphy, "Different number of supported virtual interfaces between driver and FW (%d != %d)\n",
700                   NX_VIRT_DEV_MAX, max_vif_nb);
701         res = -1;
702     }
703
704     return res;
705 }
706
707 static void ecrnx_set_ppe_threshold(struct ecrnx_hw *ecrnx_hw,
708                                    struct ieee80211_sta_he_cap *he_cap)
709 {
710     const u8_l PPE_THRES_INFO_OFT = 7;
711     const u8_l PPE_THRES_INFO_BIT_LEN = 6;
712     struct ppe_thres_info_tag
713     {
714         u8_l ppet16 : 3;
715         u8_l ppet8 : 3;
716     }__packed;
717     struct ppe_thres_field_tag
718     {
719         u8_l nsts : 3;
720         u8_l ru_idx_bmp : 4;
721     };
722     int nss = ecrnx_hw->mod_params->nss;
723     struct ppe_thres_field_tag* ppe_thres_field = (struct ppe_thres_field_tag*) he_cap->ppe_thres;
724     struct ppe_thres_info_tag ppe_thres_info = {.ppet16 = 0, //BSPK
725                                                 .ppet8 = 7 //None
726                                                };
727     u8_l* ppe_thres_info_ptr = (u8_l*) &ppe_thres_info;
728     u16_l* ppe_thres_ptr = (u16_l*) he_cap->ppe_thres;
729     u8_l i, j, cnt, offset;
730     if (ecrnx_hw->mod_params->use_80)
731     {
732         ppe_thres_field->ru_idx_bmp = 7;
733         cnt = 3;
734     }
735     else
736     {
737         ppe_thres_field->ru_idx_bmp = 1;
738         cnt = 1;
739     }
740     ppe_thres_field->nsts = nss - 1;
741     for (i = 0; i < nss ; i++)
742     {
743         for (j = 0; j < cnt; j++){
744             offset = (i * cnt + j) * PPE_THRES_INFO_BIT_LEN + PPE_THRES_INFO_OFT;
745             ppe_thres_ptr = (u16_l*)&he_cap->ppe_thres[offset / 8];
746             *ppe_thres_ptr |= *ppe_thres_info_ptr << (offset % 8);
747         }
748     }
749 }
750
751
752 #ifdef CONFIG_ECRNX_SOFTMAC
753 static void ecrnx_set_softmac_flags(struct ecrnx_hw *ecrnx_hw)
754 {
755     struct ieee80211_hw *hw = ecrnx_hw->hw;
756     int nss;
757 #ifdef CONFIG_MAC80211_AMSDUS_TX
758     ieee80211_hw_set(hw, TX_AMSDU);
759     ieee80211_hw_set(hw, TX_FRAG_LIST);
760     hw->max_tx_fragments = ecrnx_hw->mod_params->amsdu_maxnb;
761 #endif
762
763     if (!ecrnx_hw->mod_params->autobcn)
764         ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
765
766     if (ecrnx_hw->mod_params->agg_tx)
767         ieee80211_hw_set(hw, AMPDU_AGGREGATION);
768
769     if (ecrnx_hw->mod_params->cmon)
770         ieee80211_hw_set(hw, CONNECTION_MONITOR);
771
772     if (ecrnx_hw->mod_params->hwscan)
773         ieee80211_hw_set(hw, CHANCTX_STA_CSA);
774
775     if (ecrnx_hw->mod_params->ps_on) {
776         ieee80211_hw_set(hw, SUPPORTS_PS);
777     }
778     /* To disable the dynamic PS we say to the stack that we support it in
779      * HW. This will force mac80211 rely on us to handle this. */
780     ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
781
782     if (ecrnx_hw->mod_params->mfp_on)
783         ieee80211_hw_set(hw, MFP_CAPABLE);
784
785     nss = ecrnx_hw->mod_params->nss;
786     ecrnx_hw->phy.ctrlinfo_1.value = 0;
787     ecrnx_hw->phy.ctrlinfo_2.value = 0;
788     if (nss == 1) {
789         ecrnx_hw->phy.ctrlinfo_2.antennaSet = 1;
790     } else {
791         ecrnx_hw->phy.ctrlinfo_1.fecCoding = 0;
792         ecrnx_hw->phy.ctrlinfo_1.nTx = 1;
793         ecrnx_hw->phy.ctrlinfo_2.antennaSet = 3;
794         ecrnx_hw->phy.ctrlinfo_2.smmIndex = 1;
795     }
796     ecrnx_hw->phy.stbc_nss = nss >> 1;
797 }
798 #endif
799
800 #ifdef CONFIG_ECRNX_5G
801 static void ecrnx_set_vht_capa(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
802 {
803     struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ];
804     int i;
805     int nss = ecrnx_hw->mod_params->nss;
806     int mcs_map;
807     int mcs_map_max;
808     int mcs_map_max_2ss_rx = IEEE80211_VHT_MCS_SUPPORT_0_9;
809     int mcs_map_max_2ss_tx = IEEE80211_VHT_MCS_SUPPORT_0_9;
810     int bw_max;
811
812     if (!ecrnx_hw->mod_params->vht_on)
813         return;
814
815     band_5GHz->vht_cap.vht_supported = true;
816     if (ecrnx_hw->mod_params->sgi80)
817         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
818     if (ecrnx_hw->mod_params->stbc_on)
819         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
820     if (ecrnx_hw->mod_params->ldpc_on)
821         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
822     if (ecrnx_hw->mod_params->bfmee) {
823         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
824         band_5GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
825     }
826     if (nss > 1)
827         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
828
829     // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
830     band_5GHz->vht_cap.cap |= ecrnx_hw->mod_params->amsdu_rx_max;
831
832     if (ecrnx_hw->mod_params->bfmer) {
833         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
834         /* Set number of sounding dimensions */
835         band_5GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
836     }
837     if (ecrnx_hw->mod_params->murx)
838         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
839     if (ecrnx_hw->mod_params->mutx)
840         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
841
842     /*
843      * MCS map:
844      * This capabilities are filled according to the mcs_map module parameter.
845      * However currently we have some limitations due to FPGA clock constraints
846      * that prevent always using the range of MCS that is defined by the
847      * parameter:
848      *   - in RX, 2SS, we support up to MCS7
849      *   - in TX, 2SS, we support up to MCS8
850      */
851     // Get max supported BW
852     if (ecrnx_hw->mod_params->use_80) {
853         bw_max = PHY_CHNL_BW_80;
854         mcs_map_max_2ss_rx = IEEE80211_VHT_MCS_SUPPORT_0_7;
855         mcs_map_max_2ss_tx = IEEE80211_VHT_MCS_SUPPORT_0_8;
856     } else if (ecrnx_hw->mod_params->use_2040)
857         bw_max = PHY_CHNL_BW_40;
858     else
859         bw_max = PHY_CHNL_BW_20;
860
861     // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20,
862     // MCS9 is not supported in 1 and 2 SS
863     if (ecrnx_hw->mod_params->use_2040)
864         mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9;
865     else
866         mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8;
867
868     mcs_map = min_t(int, ecrnx_hw->mod_params->mcs_map, mcs_map_max);
869     band_5GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0);
870     for (i = 0; i < nss; i++) {
871         band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
872         band_5GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
873         mcs_map = min_t(int, mcs_map, mcs_map_max_2ss_rx);
874     }
875     for (; i < 8; i++) {
876         band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(
877             IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2));
878     }
879
880     mcs_map = min_t(int, ecrnx_hw->mod_params->mcs_map, mcs_map_max);
881     band_5GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0);
882     for (i = 0; i < nss; i++) {
883         band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
884         band_5GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
885         mcs_map = min_t(int, mcs_map, mcs_map_max_2ss_tx);
886     }
887     for (; i < 8; i++) {
888         band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(
889             IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2));
890     }
891
892     if (!ecrnx_hw->mod_params->use_80) {
893 #ifdef CONFIG_VENDOR_ECRNX_VHT_NO80
894         band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80;
895 #endif
896         band_5GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80;
897     }
898 }
899 #else
900 static void ecrnx_set_vht_capa(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
901 {
902     struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ];
903     int i;
904     int nss = ecrnx_hw->mod_params->nss;
905     int mcs_map;
906     int mcs_map_max;
907     int mcs_map_max_2ss_rx = IEEE80211_VHT_MCS_SUPPORT_0_9;
908     int mcs_map_max_2ss_tx = IEEE80211_VHT_MCS_SUPPORT_0_9;
909     int bw_max;
910
911     if (!ecrnx_hw->mod_params->vht_on)
912         return;
913
914     band_2GHz->vht_cap.vht_supported = true;
915     if (ecrnx_hw->mod_params->sgi80)
916         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
917     if (ecrnx_hw->mod_params->stbc_on)
918         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
919     if (ecrnx_hw->mod_params->ldpc_on)
920         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
921     if (ecrnx_hw->mod_params->bfmee) {
922         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
923 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
924         band_2GHz->vht_cap.cap |= 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
925 #endif
926     }
927     if (nss > 1)
928         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
929
930     // Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
931     band_2GHz->vht_cap.cap |= ecrnx_hw->mod_params->amsdu_rx_max;
932
933     if (ecrnx_hw->mod_params->bfmer) {
934         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
935         /* Set number of sounding dimensions */
936 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
937         band_2GHz->vht_cap.cap |= (nss - 1) << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
938 #endif
939     }
940     if (ecrnx_hw->mod_params->murx)
941         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
942     if (ecrnx_hw->mod_params->mutx)
943         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
944
945     /*
946      * MCS map:
947      * This capabilities are filled according to the mcs_map module parameter.
948      * However currently we have some limitations due to FPGA clock constraints
949      * that prevent always using the range of MCS that is defined by the
950      * parameter:
951      *   - in RX, 2SS, we support up to MCS7
952      *   - in TX, 2SS, we support up to MCS8
953      */
954     // Get max supported BW
955     if (ecrnx_hw->mod_params->use_80) {
956         bw_max = PHY_CHNL_BW_80;
957         mcs_map_max_2ss_rx = IEEE80211_VHT_MCS_SUPPORT_0_7;
958         mcs_map_max_2ss_tx = IEEE80211_VHT_MCS_SUPPORT_0_8;
959     } else if (ecrnx_hw->mod_params->use_2040)
960         bw_max = PHY_CHNL_BW_40;
961     else
962         bw_max = PHY_CHNL_BW_20;
963
964     // Check if MCS map should be limited to MCS0_8 due to the standard. Indeed in BW20,
965     // MCS9 is not supported in 1 and 2 SS
966     if (ecrnx_hw->mod_params->use_2040)
967         mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_9;
968     else
969         mcs_map_max = IEEE80211_VHT_MCS_SUPPORT_0_8;
970
971     mcs_map = min_t(int, ecrnx_hw->mod_params->mcs_map, mcs_map_max);
972     band_2GHz->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0);
973     for (i = 0; i < nss; i++) {
974         band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
975         band_2GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
976         mcs_map = min_t(int, mcs_map, mcs_map_max_2ss_rx);
977     }
978     for (; i < 8; i++) {
979         band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(
980             IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2));
981     }
982
983     mcs_map = min_t(int, ecrnx_hw->mod_params->mcs_map, mcs_map_max);
984     band_2GHz->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0);
985     for (i = 0; i < nss; i++) {
986         band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
987         band_2GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
988         mcs_map = min_t(int, mcs_map, mcs_map_max_2ss_tx);
989     }
990     for (; i < 8; i++) {
991         band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(
992             IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2));
993     }
994
995     if (!ecrnx_hw->mod_params->use_80) {
996 #ifdef CONFIG_VENDOR_ECRNX_VHT_NO80
997         band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80;
998 #endif
999         band_2GHz->vht_cap.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80;
1000     }
1001 }
1002 #endif
1003
1004
1005 static void ecrnx_set_ht_capa(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1006 {
1007 #ifdef CONFIG_ECRNX_5G
1008     struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ];
1009 #endif
1010     struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ];
1011     int i;
1012     int nss = ecrnx_hw->mod_params->nss;
1013
1014     if (!ecrnx_hw->mod_params->ht_on) {
1015         band_2GHz->ht_cap.ht_supported = false;
1016 #ifdef CONFIG_ECRNX_5G
1017         band_5GHz->ht_cap.ht_supported = false;
1018 #endif
1019         return;
1020     }
1021         //JIRA438 begin by E0000550
1022     //if (ecrnx_hw->mod_params->stbc_on)
1023     //JIRA438 end
1024         band_2GHz->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
1025     if (ecrnx_hw->mod_params->ldpc_on)
1026         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
1027     if (ecrnx_hw->mod_params->use_2040) {
1028         band_2GHz->ht_cap.mcs.rx_mask[4] = 0x1; /* MCS32 */
1029         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1030         band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(135 * nss);
1031     } else {
1032         band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss);
1033     }
1034     if (nss > 1)
1035         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
1036
1037     // Update the AMSDU max RX size
1038     if (ecrnx_hw->mod_params->amsdu_rx_max)
1039         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
1040
1041     if (ecrnx_hw->mod_params->sgi) {
1042         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
1043         if (ecrnx_hw->mod_params->use_2040) {
1044             band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
1045             band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(150 * nss);
1046         } else
1047             band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(72 * nss);
1048     }
1049     if (ecrnx_hw->mod_params->gf_rx_on)
1050         band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD;
1051
1052     for (i = 0; i < nss; i++) {
1053         band_2GHz->ht_cap.mcs.rx_mask[i] = 0xFF;
1054     }
1055         
1056 #ifdef CONFIG_ECRNX_5G
1057     band_5GHz->ht_cap = band_2GHz->ht_cap;
1058 #endif
1059 }
1060
1061 static void ecrnx_set_he_capa(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1062 {
1063 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
1064 #ifdef CONFIG_ECRNX_5G
1065     struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ];
1066 #endif
1067     struct ieee80211_supported_band *band_2GHz = wiphy->bands[NL80211_BAND_2GHZ];
1068 #endif
1069
1070     int i;
1071     int nss = ecrnx_hw->mod_params->nss;
1072     struct ieee80211_sta_he_cap *he_cap;
1073     int mcs_map, mcs_map_max_2ss = IEEE80211_HE_MCS_SUPPORT_0_11;
1074     u8 dcm_max_ru = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_242;
1075     u32_l phy_vers = ecrnx_hw->version_cfm.version_phy_2;
1076
1077     if (!ecrnx_hw->mod_params->he_on) {
1078 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
1079         band_2GHz->iftype_data = NULL;
1080         band_2GHz->n_iftype_data = 0;
1081         #ifdef CONFIG_ECRNX_5G
1082         band_5GHz->iftype_data = NULL;
1083         band_5GHz->n_iftype_data = 0;
1084         #endif
1085 #endif
1086         return;
1087     }
1088 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
1089     he_cap = (struct ieee80211_sta_he_cap *) &band_2GHz->iftype_data->he_cap;
1090 #else
1091     he_cap = &ecrnx_he_cap;
1092 #endif
1093     he_cap->has_he = true;
1094     #ifdef CONFIG_ECRNX_FULLMAC
1095     if (ecrnx_hw->version_cfm.features & BIT(MM_FEAT_TWT_BIT))
1096     {
1097         ecrnx_hw->ext_capa[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT;
1098         he_cap->he_cap_elem.mac_cap_info[0] |= IEEE80211_HE_MAC_CAP0_TWT_REQ;
1099     }
1100     #endif
1101     he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK;
1102     ecrnx_set_ppe_threshold(ecrnx_hw, he_cap);
1103 #if 0
1104     /* ESWIN turns off 40M automotically when it is HE mode  */
1105     if (ecrnx_hw->mod_params->use_2040) {
1106         he_cap->he_cap_elem.phy_cap_info[0] |=
1107                         IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G;
1108         dcm_max_ru = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_484;
1109     }
1110 #endif
1111     if (ecrnx_hw->mod_params->use_80) {
1112         he_cap->he_cap_elem.phy_cap_info[0] |=
1113                         IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
1114         mcs_map_max_2ss = IEEE80211_HE_MCS_SUPPORT_0_7;
1115         dcm_max_ru = IEEE80211_HE_PHY_CAP8_DCM_MAX_RU_996;
1116     }
1117     if (ecrnx_hw->mod_params->ldpc_on) {
1118         he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD;
1119     } else {
1120         // If no LDPC is supported, we have to limit to MCS0_9, as LDPC is mandatory
1121         // for MCS 10 and 11
1122         ecrnx_hw->mod_params->he_mcs_map = min_t(int, ecrnx_hw->mod_params->he_mcs_map,
1123                                                 IEEE80211_HE_MCS_SUPPORT_0_9);
1124     }
1125 #if 0
1126     /* ESWIN: sync the he capa with 6600 standalone */
1127     he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US |
1128                                            IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS;
1129     he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS |
1130                                            IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
1131                                            IEEE80211_HE_PHY_CAP2_DOPPLER_RX;
1132 #else
1133     he_cap->he_cap_elem.phy_cap_info[1] |= IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US;
1134     he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
1135                                            IEEE80211_HE_PHY_CAP2_DOPPLER_RX;
1136 #endif
1137     if (ecrnx_hw->mod_params->stbc_on)
1138         he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
1139     he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM |
1140                                            IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA;
1141
1142     /* ESWIN: sync the he capa with 6600 standalone */
1143     if (nss > 1) {
1144         he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_2;
1145     } else {
1146         he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1;
1147     }
1148     if (ecrnx_hw->mod_params->bfmee) {
1149         he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
1150         he_cap->he_cap_elem.phy_cap_info[4] |=
1151                      IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
1152     }
1153     he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
1154                                            IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
1155     he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU |
1156                                            IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU |
1157 #if 0
1158     /* ESWIN: sync the he capa with 6600 standalone */
1159
1160                                            IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB |
1161                                            IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB |
1162 #endif
1163                                            IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT |
1164                                            IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
1165     he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
1166     he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G |
1167                                            dcm_max_ru;
1168     he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
1169                                            IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB |
1170                                            IEEE80211_HE_PHY_CAP9_NOMIMAL_PKT_PADDING_16US;
1171 #if 0
1172     if (__MDM_VERSION(phy_vers) > 30) {
1173         he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE;
1174         he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI |
1175                                                IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI;
1176     }
1177 #endif
1178     mcs_map = ecrnx_hw->mod_params->he_mcs_map;
1179     memset(&he_cap->he_mcs_nss_supp, 0, sizeof(he_cap->he_mcs_nss_supp));
1180     for (i = 0; i < nss; i++) {
1181         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
1182         he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
1183         he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss;
1184         he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss;
1185         mcs_map = min_t(int, ecrnx_hw->mod_params->he_mcs_map,
1186                         mcs_map_max_2ss);
1187     }
1188     for (; i < 8; i++) {
1189         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
1190         he_cap->he_mcs_nss_supp.rx_mcs_80 |= unsup_for_ss;
1191         he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss;
1192         he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss;
1193     }
1194     mcs_map = ecrnx_hw->mod_params->he_mcs_map;
1195     for (i = 0; i < nss; i++) {
1196         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
1197         he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
1198         he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss;
1199         he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss;
1200         mcs_map = min_t(int, ecrnx_hw->mod_params->he_mcs_map,
1201                         mcs_map_max_2ss);
1202     }
1203     for (; i < 8; i++) {
1204         __le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
1205         he_cap->he_mcs_nss_supp.tx_mcs_80 |= unsup_for_ss;
1206         he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss;
1207         he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss;
1208     }
1209 }
1210
1211 static void ecrnx_set_wiphy_params(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1212 {
1213 #ifdef CONFIG_ECRNX_SOFTMAC
1214     struct ieee80211_hw *hw = ecrnx_hw->hw;
1215
1216     /* SOFTMAC specific parameters */
1217     if (ecrnx_hw->mod_params->hwscan) {
1218         hw->wiphy->max_scan_ssids = SCAN_SSID_MAX;
1219         hw->wiphy->max_scan_ie_len = SCAN_MAX_IE_LEN;
1220     }
1221 #else
1222     /* FULLMAC specific parameters */
1223     wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;
1224     wiphy->max_scan_ssids = SCAN_SSID_MAX;
1225     wiphy->max_scan_ie_len = SCANU_MAX_IE_LEN;
1226 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0)
1227     wiphy->support_mbssid = 1;
1228 #endif
1229 #endif /* CONFIG_ECRNX_FULLMAC */
1230
1231     if (ecrnx_hw->mod_params->tdls) {
1232         /* TDLS support */
1233         wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
1234 #ifdef CONFIG_ECRNX_FULLMAC
1235         /* TDLS external setup support */
1236         wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
1237 #endif
1238     }
1239
1240     if (ecrnx_hw->mod_params->ap_uapsd_on)
1241         wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
1242
1243 #ifdef CONFIG_ECRNX_FULLMAC
1244     if (ecrnx_hw->mod_params->ps_on)
1245         wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
1246     else
1247         wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
1248 #endif
1249
1250     if (ecrnx_hw->mod_params->custregd) {
1251         // Apply custom regulatory. Note that for recent kernel versions we use instead the
1252         // REGULATORY_WIPHY_SELF_MANAGED flag, along with the regulatory_set_wiphy_regd()
1253         // function, that needs to be called after wiphy registration
1254         // Check if custom channel set shall be enabled. In such case only monitor mode is
1255         // supported
1256         if (ecrnx_hw->mod_params->custchan) {
1257             wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR);
1258
1259             // Enable "extra" channels
1260             wiphy->bands[NL80211_BAND_2GHZ]->n_channels += 13;
1261                 #ifdef CONFIG_ECRNX_5G
1262             wiphy->bands[NL80211_BAND_5GHZ]->n_channels += 59;
1263                 #endif
1264         }
1265     }
1266 }
1267
1268 static void ecrnx_set_rf_params(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1269 {
1270 #ifndef CONFIG_ECRNX_SDM
1271 #ifdef CONFIG_ECRNX_5G
1272     struct ieee80211_supported_band *band_5GHz = wiphy->bands[NL80211_BAND_5GHZ];
1273 #else
1274 #endif
1275     u32 mdm_phy_cfg = __MDM_PHYCFG_FROM_VERS(ecrnx_hw->version_cfm.version_phy_1);
1276
1277     /*
1278      * Get configuration file depending on the RF
1279      */
1280 #if 0 /* baoyong: we use the custom rf, do not need this */
1281     struct ecrnx_phy_conf_file phy_conf;
1282     if (mdm_phy_cfg == MDM_PHY_CONFIG_TRIDENT) {
1283         // Retrieve the Trident configuration
1284         ecrnx_parse_phy_configfile(ecrnx_hw, ECRNX_PHY_CONFIG_TRD_NAME,
1285                                   &phy_conf, ecrnx_hw->mod_params->phy_cfg);
1286         memcpy(&ecrnx_hw->phy.cfg, &phy_conf.trd, sizeof(phy_conf.trd));
1287     } else if (mdm_phy_cfg == MDM_PHY_CONFIG_CATAXIA) {
1288         memset(&phy_conf.cataxia, 0, sizeof(phy_conf.cataxia));
1289         phy_conf.cataxia.path_used = ecrnx_hw->mod_params->phy_cfg;
1290         memcpy(&ecrnx_hw->phy.cfg, &phy_conf.cataxia, sizeof(phy_conf.cataxia));
1291     } else if (mdm_phy_cfg == MDM_PHY_CONFIG_KARST) {
1292         // We use the NSS parameter as is
1293         // Retrieve the Karst configuration
1294         ecrnx_parse_phy_configfile(ecrnx_hw, ECRNX_PHY_CONFIG_KARST_NAME,
1295                                   &phy_conf, ecrnx_hw->mod_params->phy_cfg);
1296
1297         memcpy(&ecrnx_hw->phy.cfg, &phy_conf.karst, sizeof(phy_conf.karst));
1298     } else {
1299         WARN_ON(1);
1300     }
1301 #endif
1302
1303     /*
1304      * adjust caps depending on the RF
1305      */
1306     switch (mdm_phy_cfg) {
1307         case MDM_PHY_CONFIG_TRIDENT:
1308         {
1309             wiphy_dbg(wiphy, "found Trident PHY .. limit BW to 40MHz\n");
1310             ecrnx_hw->phy.limit_bw = true;
1311 #ifdef CONFIG_ECRNX_5G
1312 #ifdef CONFIG_VENDOR_ECRNX_VHT_NO80
1313             band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_NOT_SUP_WIDTH_80;
1314 #endif
1315             band_5GHz->vht_cap.cap &= ~(IEEE80211_VHT_CAP_SHORT_GI_80 |
1316                                         IEEE80211_VHT_CAP_RXSTBC_MASK);
1317 #endif
1318             break;
1319         }
1320         case MDM_PHY_CONFIG_CATAXIA:
1321         {
1322             wiphy_dbg(wiphy, "found CATAXIA PHY\n");
1323             break;
1324         }
1325         case MDM_PHY_CONFIG_KARST:
1326         {
1327             wiphy_dbg(wiphy, "found KARST PHY\n");
1328             break;
1329         }
1330         default:
1331             WARN_ON(1);
1332             break;
1333     }
1334 #endif /* CONFIG_ECRNX_SDM */
1335 }
1336
1337 int ecrnx_handle_dynparams(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1338 {
1339     int ret;
1340
1341     /* Check compatibility between requested parameters and HW/SW features */
1342     ret = ecrnx_check_fw_hw_feature(ecrnx_hw, wiphy);
1343     if (ret)
1344         return ret;
1345 #ifndef CONFIG_ECRNX_ESWIN
1346
1347     /* Allocate the RX buffers according to the maximum AMSDU RX size */
1348     ret = ecrnx_ipc_rxbuf_init(ecrnx_hw,
1349                               (4 * (ecrnx_hw->mod_params->amsdu_rx_max + 1) + 1) * 1024);
1350     if (ret) {
1351         wiphy_err(wiphy, "Cannot allocate the RX buffers\n");
1352         return ret;
1353     }
1354 #endif
1355 #ifdef CONFIG_ECRNX_SOFTMAC
1356     /* SOFTMAC specific parameters*/
1357     ecrnx_set_softmac_flags(ecrnx_hw);
1358 #endif /* CONFIG_ECRNX_SOFTMAC */
1359
1360     /* Set wiphy parameters */
1361     ecrnx_set_wiphy_params(ecrnx_hw, wiphy);
1362
1363     /* Set VHT capabilities */
1364     ecrnx_set_vht_capa(ecrnx_hw, wiphy);
1365
1366     /* Set HE capabilities */
1367     ecrnx_set_he_capa(ecrnx_hw, wiphy);
1368
1369     /* Set HT capabilities */
1370     ecrnx_set_ht_capa(ecrnx_hw, wiphy);
1371
1372     /* Set RF specific parameters (shall be done last as it might change some
1373        capabilities previously set) */
1374     ecrnx_set_rf_params(ecrnx_hw, wiphy);
1375
1376     return 0;
1377 }
1378
1379 void ecrnx_custregd(struct ecrnx_hw *ecrnx_hw, struct wiphy *wiphy)
1380 {
1381 // For older kernel version, the custom regulatory is applied before the wiphy
1382 // registration (in ecrnx_set_wiphy_params()), so nothing has to be done here
1383 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
1384     if (!ecrnx_hw->mod_params->custregd)
1385         return;
1386
1387     wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
1388     wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
1389
1390     rtnl_lock();
1391     if (regulatory_set_wiphy_regd_sync_rtnl(wiphy, &ecrnx_regdom))
1392         wiphy_err(wiphy, "Failed to set custom regdomain\n");
1393     else
1394         wiphy_err(wiphy,"\n"
1395                   "*******************************************************\n"
1396                   "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n"
1397                   "*******************************************************\n");
1398      rtnl_unlock();
1399 #endif
1400 }
1401
1402 void ecrnx_adjust_amsdu_maxnb(struct ecrnx_hw *ecrnx_hw)
1403 {
1404     if (ecrnx_hw->mod_params->amsdu_maxnb > NX_TX_PAYLOAD_MAX)
1405         ecrnx_hw->mod_params->amsdu_maxnb = NX_TX_PAYLOAD_MAX;
1406     else if (ecrnx_hw->mod_params->amsdu_maxnb == 0)
1407         ecrnx_hw->mod_params->amsdu_maxnb = 1;
1408 }