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