Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / wireless / intel / iwlwifi / dvm / devices.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /******************************************************************************
3  *
4  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
5  *
6  * Contact Information:
7  *  Intel Linux Wireless <linuxwifi@intel.com>
8  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
9  *
10  *****************************************************************************/
11
12 /*
13  * DVM device-specific data & functions
14  */
15 #include "iwl-io.h"
16 #include "iwl-prph.h"
17 #include "iwl-eeprom-parse.h"
18
19 #include "agn.h"
20 #include "dev.h"
21 #include "commands.h"
22
23
24 /*
25  * 1000 series
26  * ===========
27  */
28
29 /*
30  * For 1000, use advance thermal throttling critical temperature threshold,
31  * but legacy thermal management implementation for now.
32  * This is for the reason of 1000 uCode using advance thermal throttling API
33  * but not implement ct_kill_exit based on ct_kill exit temperature
34  * so the thermal throttling will still based on legacy thermal throttling
35  * management.
36  * The code here need to be modified once 1000 uCode has the advanced thermal
37  * throttling algorithm in place
38  */
39 static void iwl1000_set_ct_threshold(struct iwl_priv *priv)
40 {
41         /* want Celsius */
42         priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
43         priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
44 }
45
46 /* NIC configuration for 1000 series */
47 static void iwl1000_nic_config(struct iwl_priv *priv)
48 {
49         /* Setting digital SVR for 1000 card to 1.32V */
50         /* locking is acquired in iwl_set_bits_mask_prph() function */
51         iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG,
52                                 APMG_SVR_DIGITAL_VOLTAGE_1_32,
53                                 ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
54 }
55
56 /**
57  * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
58  * @priv -- pointer to iwl_priv data structure
59  * @tsf_bits -- number of bits need to shift for masking)
60  */
61 static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
62                                            u16 tsf_bits)
63 {
64         return (1 << tsf_bits) - 1;
65 }
66
67 /**
68  * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
69  * @priv -- pointer to iwl_priv data structure
70  * @tsf_bits -- number of bits need to shift for masking)
71  */
72 static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
73                                             u16 tsf_bits)
74 {
75         return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
76 }
77
78 /*
79  * extended beacon time format
80  * time in usec will be changed into a 32-bit value in extended:internal format
81  * the extended part is the beacon counts
82  * the internal part is the time in usec within one beacon interval
83  */
84 static u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec,
85                                 u32 beacon_interval)
86 {
87         u32 quot;
88         u32 rem;
89         u32 interval = beacon_interval * TIME_UNIT;
90
91         if (!interval || !usec)
92                 return 0;
93
94         quot = (usec / interval) &
95                 (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
96                 IWLAGN_EXT_BEACON_TIME_POS);
97         rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
98                                    IWLAGN_EXT_BEACON_TIME_POS);
99
100         return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
101 }
102
103 /* base is usually what we get from ucode with each received frame,
104  * the same as HW timer counter counting down
105  */
106 static __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
107                            u32 addon, u32 beacon_interval)
108 {
109         u32 base_low = base & iwl_beacon_time_mask_low(priv,
110                                 IWLAGN_EXT_BEACON_TIME_POS);
111         u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
112                                 IWLAGN_EXT_BEACON_TIME_POS);
113         u32 interval = beacon_interval * TIME_UNIT;
114         u32 res = (base & iwl_beacon_time_mask_high(priv,
115                                 IWLAGN_EXT_BEACON_TIME_POS)) +
116                                 (addon & iwl_beacon_time_mask_high(priv,
117                                 IWLAGN_EXT_BEACON_TIME_POS));
118
119         if (base_low > addon_low)
120                 res += base_low - addon_low;
121         else if (base_low < addon_low) {
122                 res += interval + base_low - addon_low;
123                 res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
124         } else
125                 res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
126
127         return cpu_to_le32(res);
128 }
129
130 static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
131         .min_nrg_cck = 95,
132         .auto_corr_min_ofdm = 90,
133         .auto_corr_min_ofdm_mrc = 170,
134         .auto_corr_min_ofdm_x1 = 120,
135         .auto_corr_min_ofdm_mrc_x1 = 240,
136
137         .auto_corr_max_ofdm = 120,
138         .auto_corr_max_ofdm_mrc = 210,
139         .auto_corr_max_ofdm_x1 = 155,
140         .auto_corr_max_ofdm_mrc_x1 = 290,
141
142         .auto_corr_min_cck = 125,
143         .auto_corr_max_cck = 200,
144         .auto_corr_min_cck_mrc = 170,
145         .auto_corr_max_cck_mrc = 400,
146         .nrg_th_cck = 95,
147         .nrg_th_ofdm = 95,
148
149         .barker_corr_th_min = 190,
150         .barker_corr_th_min_mrc = 390,
151         .nrg_th_cca = 62,
152 };
153
154 static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
155 {
156         iwl1000_set_ct_threshold(priv);
157
158         /* Set initial sensitivity parameters */
159         priv->hw_params.sens = &iwl1000_sensitivity;
160 }
161
162 const struct iwl_dvm_cfg iwl_dvm_1000_cfg = {
163         .set_hw_params = iwl1000_hw_set_hw_params,
164         .nic_config = iwl1000_nic_config,
165         .temperature = iwlagn_temperature,
166         .support_ct_kill_exit = true,
167         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
168         .chain_noise_scale = 1000,
169 };
170
171
172 /*
173  * 2000 series
174  * ===========
175  */
176
177 static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
178 {
179         /* want Celsius */
180         priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
181         priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
182 }
183
184 /* NIC configuration for 2000 series */
185 static void iwl2000_nic_config(struct iwl_priv *priv)
186 {
187         iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
188                     CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
189 }
190
191 static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
192         .min_nrg_cck = 97,
193         .auto_corr_min_ofdm = 80,
194         .auto_corr_min_ofdm_mrc = 128,
195         .auto_corr_min_ofdm_x1 = 105,
196         .auto_corr_min_ofdm_mrc_x1 = 192,
197
198         .auto_corr_max_ofdm = 145,
199         .auto_corr_max_ofdm_mrc = 232,
200         .auto_corr_max_ofdm_x1 = 110,
201         .auto_corr_max_ofdm_mrc_x1 = 232,
202
203         .auto_corr_min_cck = 125,
204         .auto_corr_max_cck = 175,
205         .auto_corr_min_cck_mrc = 160,
206         .auto_corr_max_cck_mrc = 310,
207         .nrg_th_cck = 97,
208         .nrg_th_ofdm = 100,
209
210         .barker_corr_th_min = 190,
211         .barker_corr_th_min_mrc = 390,
212         .nrg_th_cca = 62,
213 };
214
215 static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
216 {
217         iwl2000_set_ct_threshold(priv);
218
219         /* Set initial sensitivity parameters */
220         priv->hw_params.sens = &iwl2000_sensitivity;
221 }
222
223 const struct iwl_dvm_cfg iwl_dvm_2000_cfg = {
224         .set_hw_params = iwl2000_hw_set_hw_params,
225         .nic_config = iwl2000_nic_config,
226         .temperature = iwlagn_temperature,
227         .adv_thermal_throttle = true,
228         .support_ct_kill_exit = true,
229         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
230         .chain_noise_scale = 1000,
231         .hd_v2 = true,
232         .need_temp_offset_calib = true,
233         .temp_offset_v2 = true,
234 };
235
236 const struct iwl_dvm_cfg iwl_dvm_105_cfg = {
237         .set_hw_params = iwl2000_hw_set_hw_params,
238         .nic_config = iwl2000_nic_config,
239         .temperature = iwlagn_temperature,
240         .adv_thermal_throttle = true,
241         .support_ct_kill_exit = true,
242         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
243         .chain_noise_scale = 1000,
244         .hd_v2 = true,
245         .need_temp_offset_calib = true,
246         .temp_offset_v2 = true,
247         .adv_pm = true,
248 };
249
250 static const struct iwl_dvm_bt_params iwl2030_bt_params = {
251         /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
252         .advanced_bt_coexist = true,
253         .agg_time_limit = BT_AGG_THRESHOLD_DEF,
254         .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
255         .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
256         .bt_sco_disable = true,
257         .bt_session_2 = true,
258 };
259
260 const struct iwl_dvm_cfg iwl_dvm_2030_cfg = {
261         .set_hw_params = iwl2000_hw_set_hw_params,
262         .nic_config = iwl2000_nic_config,
263         .temperature = iwlagn_temperature,
264         .adv_thermal_throttle = true,
265         .support_ct_kill_exit = true,
266         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
267         .chain_noise_scale = 1000,
268         .hd_v2 = true,
269         .bt_params = &iwl2030_bt_params,
270         .need_temp_offset_calib = true,
271         .temp_offset_v2 = true,
272         .adv_pm = true,
273 };
274
275 /*
276  * 5000 series
277  * ===========
278  */
279
280 /* NIC configuration for 5000 series */
281 static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
282         .min_nrg_cck = 100,
283         .auto_corr_min_ofdm = 90,
284         .auto_corr_min_ofdm_mrc = 170,
285         .auto_corr_min_ofdm_x1 = 105,
286         .auto_corr_min_ofdm_mrc_x1 = 220,
287
288         .auto_corr_max_ofdm = 120,
289         .auto_corr_max_ofdm_mrc = 210,
290         .auto_corr_max_ofdm_x1 = 120,
291         .auto_corr_max_ofdm_mrc_x1 = 240,
292
293         .auto_corr_min_cck = 125,
294         .auto_corr_max_cck = 200,
295         .auto_corr_min_cck_mrc = 200,
296         .auto_corr_max_cck_mrc = 400,
297         .nrg_th_cck = 100,
298         .nrg_th_ofdm = 100,
299
300         .barker_corr_th_min = 190,
301         .barker_corr_th_min_mrc = 390,
302         .nrg_th_cca = 62,
303 };
304
305 static const struct iwl_sensitivity_ranges iwl5150_sensitivity = {
306         .min_nrg_cck = 95,
307         .auto_corr_min_ofdm = 90,
308         .auto_corr_min_ofdm_mrc = 170,
309         .auto_corr_min_ofdm_x1 = 105,
310         .auto_corr_min_ofdm_mrc_x1 = 220,
311
312         .auto_corr_max_ofdm = 120,
313         .auto_corr_max_ofdm_mrc = 210,
314         /* max = min for performance bug in 5150 DSP */
315         .auto_corr_max_ofdm_x1 = 105,
316         .auto_corr_max_ofdm_mrc_x1 = 220,
317
318         .auto_corr_min_cck = 125,
319         .auto_corr_max_cck = 200,
320         .auto_corr_min_cck_mrc = 170,
321         .auto_corr_max_cck_mrc = 400,
322         .nrg_th_cck = 95,
323         .nrg_th_ofdm = 95,
324
325         .barker_corr_th_min = 190,
326         .barker_corr_th_min_mrc = 390,
327         .nrg_th_cca = 62,
328 };
329
330 #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF   (-5)
331
332 static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
333 {
334         u16 temperature, voltage;
335
336         temperature = le16_to_cpu(priv->nvm_data->kelvin_temperature);
337         voltage = le16_to_cpu(priv->nvm_data->kelvin_voltage);
338
339         /* offset = temp - volt / coeff */
340         return (s32)(temperature -
341                         voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
342 }
343
344 static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
345 {
346         const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
347         s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
348                         iwl_temp_calib_to_offset(priv);
349
350         priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
351 }
352
353 static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
354 {
355         /* want Celsius */
356         priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
357 }
358
359 static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
360 {
361         iwl5000_set_ct_threshold(priv);
362
363         /* Set initial sensitivity parameters */
364         priv->hw_params.sens = &iwl5000_sensitivity;
365 }
366
367 static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
368 {
369         iwl5150_set_ct_threshold(priv);
370
371         /* Set initial sensitivity parameters */
372         priv->hw_params.sens = &iwl5150_sensitivity;
373 }
374
375 static void iwl5150_temperature(struct iwl_priv *priv)
376 {
377         u32 vt = 0;
378         s32 offset =  iwl_temp_calib_to_offset(priv);
379
380         vt = le32_to_cpu(priv->statistics.common.temperature);
381         vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
382         /* now vt hold the temperature in Kelvin */
383         priv->temperature = KELVIN_TO_CELSIUS(vt);
384         iwl_tt_handler(priv);
385 }
386
387 static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
388                                      struct ieee80211_channel_switch *ch_switch)
389 {
390         /*
391          * MULTI-FIXME
392          * See iwlagn_mac_channel_switch.
393          */
394         struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
395         struct iwl5000_channel_switch_cmd cmd;
396         u32 switch_time_in_usec, ucode_switch_time;
397         u16 ch;
398         u32 tsf_low;
399         u8 switch_count;
400         u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
401         struct ieee80211_vif *vif = ctx->vif;
402         struct iwl_host_cmd hcmd = {
403                 .id = REPLY_CHANNEL_SWITCH,
404                 .len = { sizeof(cmd), },
405                 .data = { &cmd, },
406         };
407
408         cmd.band = priv->band == NL80211_BAND_2GHZ;
409         ch = ch_switch->chandef.chan->hw_value;
410         IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
411                       ctx->active.channel, ch);
412         cmd.channel = cpu_to_le16(ch);
413         cmd.rxon_flags = ctx->staging.flags;
414         cmd.rxon_filter_flags = ctx->staging.filter_flags;
415         switch_count = ch_switch->count;
416         tsf_low = ch_switch->timestamp & 0x0ffffffff;
417         /*
418          * calculate the ucode channel switch time
419          * adding TSF as one of the factor for when to switch
420          */
421         if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
422                 if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
423                     beacon_interval)) {
424                         switch_count -= (priv->ucode_beacon_time -
425                                 tsf_low) / beacon_interval;
426                 } else
427                         switch_count = 0;
428         }
429         if (switch_count <= 1)
430                 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
431         else {
432                 switch_time_in_usec =
433                         vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
434                 ucode_switch_time = iwl_usecs_to_beacons(priv,
435                                                          switch_time_in_usec,
436                                                          beacon_interval);
437                 cmd.switch_time = iwl_add_beacon_time(priv,
438                                                       priv->ucode_beacon_time,
439                                                       ucode_switch_time,
440                                                       beacon_interval);
441         }
442         IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
443                       cmd.switch_time);
444         cmd.expect_beacon =
445                 ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
446
447         return iwl_dvm_send_cmd(priv, &hcmd);
448 }
449
450 const struct iwl_dvm_cfg iwl_dvm_5000_cfg = {
451         .set_hw_params = iwl5000_hw_set_hw_params,
452         .set_channel_switch = iwl5000_hw_channel_switch,
453         .temperature = iwlagn_temperature,
454         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
455         .chain_noise_scale = 1000,
456         .no_idle_support = true,
457 };
458
459 const struct iwl_dvm_cfg iwl_dvm_5150_cfg = {
460         .set_hw_params = iwl5150_hw_set_hw_params,
461         .set_channel_switch = iwl5000_hw_channel_switch,
462         .temperature = iwl5150_temperature,
463         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
464         .chain_noise_scale = 1000,
465         .no_idle_support = true,
466         .no_xtal_calib = true,
467 };
468
469
470
471 /*
472  * 6000 series
473  * ===========
474  */
475
476 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
477 {
478         /* want Celsius */
479         priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
480         priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
481 }
482
483 /* NIC configuration for 6000 series */
484 static void iwl6000_nic_config(struct iwl_priv *priv)
485 {
486         switch (priv->cfg->device_family) {
487         case IWL_DEVICE_FAMILY_6005:
488         case IWL_DEVICE_FAMILY_6030:
489         case IWL_DEVICE_FAMILY_6000:
490                 break;
491         case IWL_DEVICE_FAMILY_6000i:
492                 /* 2x2 IPA phy type */
493                 iwl_write32(priv->trans, CSR_GP_DRIVER_REG,
494                              CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
495                 break;
496         case IWL_DEVICE_FAMILY_6050:
497                 /* Indicate calibration version to uCode. */
498                 if (priv->nvm_data->calib_version >= 6)
499                         iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
500                                         CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
501                 break;
502         case IWL_DEVICE_FAMILY_6150:
503                 /* Indicate calibration version to uCode. */
504                 if (priv->nvm_data->calib_version >= 6)
505                         iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
506                                         CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
507                 iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG,
508                             CSR_GP_DRIVER_REG_BIT_6050_1x2);
509                 break;
510         default:
511                 WARN_ON(1);
512         }
513 }
514
515 static const struct iwl_sensitivity_ranges iwl6000_sensitivity = {
516         .min_nrg_cck = 110,
517         .auto_corr_min_ofdm = 80,
518         .auto_corr_min_ofdm_mrc = 128,
519         .auto_corr_min_ofdm_x1 = 105,
520         .auto_corr_min_ofdm_mrc_x1 = 192,
521
522         .auto_corr_max_ofdm = 145,
523         .auto_corr_max_ofdm_mrc = 232,
524         .auto_corr_max_ofdm_x1 = 110,
525         .auto_corr_max_ofdm_mrc_x1 = 232,
526
527         .auto_corr_min_cck = 125,
528         .auto_corr_max_cck = 175,
529         .auto_corr_min_cck_mrc = 160,
530         .auto_corr_max_cck_mrc = 310,
531         .nrg_th_cck = 110,
532         .nrg_th_ofdm = 110,
533
534         .barker_corr_th_min = 190,
535         .barker_corr_th_min_mrc = 336,
536         .nrg_th_cca = 62,
537 };
538
539 static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
540 {
541         iwl6000_set_ct_threshold(priv);
542
543         /* Set initial sensitivity parameters */
544         priv->hw_params.sens = &iwl6000_sensitivity;
545
546 }
547
548 static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
549                                      struct ieee80211_channel_switch *ch_switch)
550 {
551         /*
552          * MULTI-FIXME
553          * See iwlagn_mac_channel_switch.
554          */
555         struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
556         struct iwl6000_channel_switch_cmd *cmd;
557         u32 switch_time_in_usec, ucode_switch_time;
558         u16 ch;
559         u32 tsf_low;
560         u8 switch_count;
561         u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
562         struct ieee80211_vif *vif = ctx->vif;
563         struct iwl_host_cmd hcmd = {
564                 .id = REPLY_CHANNEL_SWITCH,
565                 .len = { sizeof(*cmd), },
566                 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
567         };
568         int err;
569
570         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
571         if (!cmd)
572                 return -ENOMEM;
573
574         hcmd.data[0] = cmd;
575
576         cmd->band = priv->band == NL80211_BAND_2GHZ;
577         ch = ch_switch->chandef.chan->hw_value;
578         IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
579                       ctx->active.channel, ch);
580         cmd->channel = cpu_to_le16(ch);
581         cmd->rxon_flags = ctx->staging.flags;
582         cmd->rxon_filter_flags = ctx->staging.filter_flags;
583         switch_count = ch_switch->count;
584         tsf_low = ch_switch->timestamp & 0x0ffffffff;
585         /*
586          * calculate the ucode channel switch time
587          * adding TSF as one of the factor for when to switch
588          */
589         if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
590                 if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
591                     beacon_interval)) {
592                         switch_count -= (priv->ucode_beacon_time -
593                                 tsf_low) / beacon_interval;
594                 } else
595                         switch_count = 0;
596         }
597         if (switch_count <= 1)
598                 cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
599         else {
600                 switch_time_in_usec =
601                         vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
602                 ucode_switch_time = iwl_usecs_to_beacons(priv,
603                                                          switch_time_in_usec,
604                                                          beacon_interval);
605                 cmd->switch_time = iwl_add_beacon_time(priv,
606                                                        priv->ucode_beacon_time,
607                                                        ucode_switch_time,
608                                                        beacon_interval);
609         }
610         IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
611                       cmd->switch_time);
612         cmd->expect_beacon =
613                 ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR;
614
615         err = iwl_dvm_send_cmd(priv, &hcmd);
616         kfree(cmd);
617         return err;
618 }
619
620 const struct iwl_dvm_cfg iwl_dvm_6000_cfg = {
621         .set_hw_params = iwl6000_hw_set_hw_params,
622         .set_channel_switch = iwl6000_hw_channel_switch,
623         .nic_config = iwl6000_nic_config,
624         .temperature = iwlagn_temperature,
625         .adv_thermal_throttle = true,
626         .support_ct_kill_exit = true,
627         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
628         .chain_noise_scale = 1000,
629 };
630
631 const struct iwl_dvm_cfg iwl_dvm_6005_cfg = {
632         .set_hw_params = iwl6000_hw_set_hw_params,
633         .set_channel_switch = iwl6000_hw_channel_switch,
634         .nic_config = iwl6000_nic_config,
635         .temperature = iwlagn_temperature,
636         .adv_thermal_throttle = true,
637         .support_ct_kill_exit = true,
638         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
639         .chain_noise_scale = 1000,
640         .need_temp_offset_calib = true,
641 };
642
643 const struct iwl_dvm_cfg iwl_dvm_6050_cfg = {
644         .set_hw_params = iwl6000_hw_set_hw_params,
645         .set_channel_switch = iwl6000_hw_channel_switch,
646         .nic_config = iwl6000_nic_config,
647         .temperature = iwlagn_temperature,
648         .adv_thermal_throttle = true,
649         .support_ct_kill_exit = true,
650         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
651         .chain_noise_scale = 1500,
652 };
653
654 static const struct iwl_dvm_bt_params iwl6000_bt_params = {
655         /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
656         .advanced_bt_coexist = true,
657         .agg_time_limit = BT_AGG_THRESHOLD_DEF,
658         .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
659         .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
660         .bt_sco_disable = true,
661 };
662
663 const struct iwl_dvm_cfg iwl_dvm_6030_cfg = {
664         .set_hw_params = iwl6000_hw_set_hw_params,
665         .set_channel_switch = iwl6000_hw_channel_switch,
666         .nic_config = iwl6000_nic_config,
667         .temperature = iwlagn_temperature,
668         .adv_thermal_throttle = true,
669         .support_ct_kill_exit = true,
670         .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
671         .chain_noise_scale = 1000,
672         .bt_params = &iwl6000_bt_params,
673         .need_temp_offset_calib = true,
674         .adv_pm = true,
675 };