]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-6000.c
iwlwifi: add bt full concurrency support
[karo-tx-linux.git] / drivers / net / wireless / iwlwifi / iwl-6000.c
index 59681c5eeb9f01b16d664517191896ef97864b9f..a4601b58a5dbaee9e11ffe7023662fc6ceade70c 100644 (file)
@@ -52,7 +52,7 @@
 /* Highest firmware API version supported */
 #define IWL6000_UCODE_API_MAX 4
 #define IWL6050_UCODE_API_MAX 4
-#define IWL6000G2_UCODE_API_MAX 4
+#define IWL6000G2_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
@@ -122,6 +122,164 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
                priv->cfg->ops->lib->temp_ops.set_calib_version(priv);
 }
 
+/*
+ * Macros to access the lookup table.
+ *
+ * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
+ * wifi_prio, wifi_txrx and wifi_sh_ant_req.
+ *
+ * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
+ *
+ * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
+ * one after another in 32-bit registers, and "registers" 0 through 7 contain
+ * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
+ *
+ * These macros encode that format.
+ */
+#define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
+       wifi_txrx, wifi_sh_ant_req) \
+       (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
+       (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
+
+#define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
+       lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
+#define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx,\
+       bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
+#define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
+       bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
+       bt_rf_act, wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+#define LUT_WLAN_KILL_OP(lut, op, val) \
+       lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
+#define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
+#define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+#define LUT_ANT_SWITCH_OP(lut, op, val) \
+       lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
+#define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
+#define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+#define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
+       wifi_prio, wifi_txrx, wifi_sh_ant_req) \
+       LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
+       wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
+
+static const __le32 iwl6000g2b_def_3w_lookup[12] = {
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaeaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xcc00ff28),
+       cpu_to_le32(0x0000aaaa),
+       cpu_to_le32(0xcc00aaaa),
+       cpu_to_le32(0x0000aaaa),
+       cpu_to_le32(0xc0004000),
+       cpu_to_le32(0x00004000),
+       cpu_to_le32(0xf0005000),
+       cpu_to_le32(0xf0004000),
+};
+
+static const __le32 iwl6000g2b_concurrent_lookup[12] = {
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0xaaaaaaaa),
+       cpu_to_le32(0x00000000),
+       cpu_to_le32(0x00000000),
+       cpu_to_le32(0x00000000),
+       cpu_to_le32(0x00000000),
+};
+
+static void iwl6000g2b_send_bt_config(struct iwl_priv *priv)
+{
+       struct iwl6000g2b_bt_cmd bt_cmd = {
+               .prio_boost = IWL6000G2B_BT_PRIO_BOOST_DEFAULT,
+               .max_kill = IWL6000G2B_BT_MAX_KILL_DEFAULT,
+               .bt3_timer_t7_value = IWL6000G2B_BT3_T7_DEFAULT,
+               .kill_ack_mask = IWL6000G2B_BT_KILL_ACK_MASK_DEFAULT,
+               .kill_cts_mask = IWL6000G2B_BT_KILL_CTS_MASK_DEFAULT,
+               .bt3_prio_sample_time = IWL6000G2B_BT3_PRIO_SAMPLE_DEFAULT,
+               .bt3_timer_t2_value = IWL6000G2B_BT3_T2_DEFAULT,
+               .valid = IWL6000G2B_BT_VALID_ENABLE_FLAGS,
+       };
+
+       BUILD_BUG_ON(sizeof(iwl6000g2b_def_3w_lookup) !=
+                       sizeof(bt_cmd.bt3_lookup_table));
+
+       /*
+        * Configure BT coex mode to "no coexistence" when the
+        * user disabled BT coexistence, we have no interface
+        * (might be in monitor mode), or the interface is in
+        * IBSS mode (no proper uCode support for coex then).
+        */
+       if (!bt_coex_active || !priv->vif ||
+           priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+               bt_cmd.flags = 0;
+       } else {
+               bt_cmd.flags = IWL6000G2B_BT_FLAG_CHANNEL_INHIBITION |
+                               IWL6000G2B_BT_FLAG_COEX_MODE_3W <<
+                                       IWL6000G2B_BT_FLAG_COEX_MODE_SHIFT;
+               bt_cmd.valid |= IWL6000G2B_BT_ALL_VALID_MSK;
+       }
+
+       if (priv->bt_full_concurrent)
+               memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_concurrent_lookup,
+                       sizeof(iwl6000g2b_concurrent_lookup));
+       else
+               memcpy(bt_cmd.bt3_lookup_table, iwl6000g2b_def_3w_lookup,
+                       sizeof(iwl6000g2b_def_3w_lookup));
+
+       IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+                      bt_cmd.flags ? "active" : "disabled",
+                      priv->bt_full_concurrent ?
+                      "full concurrency" : "3-wire");
+
+       if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
+               IWL_ERR(priv, "failed to send BT Coex Config\n");
+
+       /*
+        * When we are doing a restart, need to also reconfigure BT
+        * SCO to the device. If not doing a restart, bt_sco_active
+        * will always be false, so there's no need to have an extra
+        * variable to check for it.
+        */
+       if (priv->bt_sco_active) {
+               struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 };
+
+               if (priv->bt_sco_active)
+                       sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE;
+               if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO,
+                                    sizeof(sco_cmd), &sco_cmd))
+                       IWL_ERR(priv, "failed to send BT SCO command\n");
+       }
+}
+
 static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
        .min_nrg_cck = 97,
        .max_nrg_cck = 0, /* not used, set to 0 */
@@ -214,7 +372,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        };
 
        cmd.band = priv->band == IEEE80211_BAND_2GHZ;
-       ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
+       ch = ch_switch->channel->hw_value;
        IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
                      priv->active_rxon.channel, ch);
        cmd.channel = cpu_to_le16(ch);
@@ -263,6 +421,100 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        return iwl_send_cmd_sync(priv, &hcmd);
 }
 
+static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work)
+{
+       struct iwl_priv *priv =
+               container_of(work, struct iwl_priv, bt_traffic_change_work);
+       int smps_request = -1;
+
+       switch (priv->bt_traffic_load) {
+       case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
+               smps_request = IEEE80211_SMPS_AUTOMATIC;
+               break;
+       case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
+               smps_request = IEEE80211_SMPS_DYNAMIC;
+               break;
+       case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
+       case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
+               smps_request = IEEE80211_SMPS_STATIC;
+               break;
+       default:
+               IWL_ERR(priv, "Invalid BT traffic load: %d\n",
+                       priv->bt_traffic_load);
+               break;
+       }
+
+       mutex_lock(&priv->mutex);
+
+       if (smps_request != -1 &&
+           priv->vif && priv->vif->type == NL80211_IFTYPE_STATION)
+               ieee80211_request_smps(priv->vif, smps_request);
+
+       mutex_unlock(&priv->mutex);
+}
+
+static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv,
+                                            struct iwl_rx_mem_buffer *rxb)
+{
+       unsigned long flags;
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
+       struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 };
+
+       IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
+       IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
+       IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
+       IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n", coex->bt_ci_compliance);
+       IWL_DEBUG_NOTIF(priv, "    UART msg: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x:"
+                             "%.2x:%.2x\n",
+                       coex->uart_msg[0], coex->uart_msg[1], coex->uart_msg[2],
+                       coex->uart_msg[3], coex->uart_msg[4], coex->uart_msg[5],
+                       coex->uart_msg[6], coex->uart_msg[7]);
+
+       priv->notif_bt_traffic_load = coex->bt_traffic_load;
+
+       if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
+               if (coex->bt_traffic_load != priv->bt_traffic_load) {
+                       priv->bt_traffic_load = coex->bt_traffic_load;
+
+                       queue_work(priv->workqueue,
+                                  &priv->bt_traffic_change_work);
+               }
+
+               /* FIXME: add defines for this check */
+               priv->bt_sco_active = coex->uart_msg[3] & 1;
+               if (priv->bt_sco_active)
+                       sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE;
+               iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
+                                      sizeof(sco_cmd), &sco_cmd, NULL);
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->bt_ci_compliance = coex->bt_ci_compliance;
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv)
+{
+       iwlagn_rx_handler_setup(priv);
+       priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
+               iwl6000g2b_bt_coex_profile_notif;
+}
+
+static void iwl6000g2b_bt_setup_deferred_work(struct iwl_priv *priv)
+{
+       iwlagn_setup_deferred_work(priv);
+
+       INIT_WORK(&priv->bt_traffic_change_work,
+                 iwl6000g2b_bt_traffic_change_work);
+
+}
+
+static void iwl6000g2b_bt_cancel_deferred_work(struct iwl_priv *priv)
+{
+       cancel_work_sync(&priv->bt_traffic_change_work);
+}
+
 static struct iwl_lib_ops iwl6000_lib = {
        .set_hw_params = iwl6000_hw_set_hw_params,
        .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
@@ -323,12 +575,93 @@ static struct iwl_lib_ops iwl6000_lib = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
+               .bt_stats_read = iwl_ucode_bt_stats_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
        .check_ack_health = iwl_good_ack_health,
        .txfifo_flush = iwlagn_txfifo_flush,
        .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+       .tt_ops = {
+               .lower_power_detection = iwl_tt_is_low_power_state,
+               .tt_power_mode = iwl_tt_current_power_mode,
+               .ct_kill_check = iwl_check_for_ct_kill,
+       }
+};
+
+static struct iwl_lib_ops iwl6000g2b_lib = {
+       .set_hw_params = iwl6000_hw_set_hw_params,
+       .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
+       .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
+       .txq_set_sched = iwlagn_txq_set_sched,
+       .txq_agg_enable = iwlagn_txq_agg_enable,
+       .txq_agg_disable = iwlagn_txq_agg_disable,
+       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+       .txq_free_tfd = iwl_hw_txq_free_tfd,
+       .txq_init = iwl_hw_tx_queue_init,
+       .rx_handler_setup = iwl6000g2b_rx_handler_setup,
+       .setup_deferred_work = iwl6000g2b_bt_setup_deferred_work,
+       .cancel_deferred_work = iwl6000g2b_bt_cancel_deferred_work,
+       .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
+       .load_ucode = iwlagn_load_ucode,
+       .dump_nic_event_log = iwl_dump_nic_event_log,
+       .dump_nic_error_log = iwl_dump_nic_error_log,
+       .dump_csr = iwl_dump_csr,
+       .dump_fh = iwl_dump_fh,
+       .init_alive_start = iwlagn_init_alive_start,
+       .alive_notify = iwlagn_alive_notify,
+       .send_tx_power = iwlagn_send_tx_power,
+       .update_chain_flags = iwl_update_chain_flags,
+       .set_channel_switch = iwl6000_hw_channel_switch,
+       .apm_ops = {
+               .init = iwl_apm_init,
+               .stop = iwl_apm_stop,
+               .config = iwl6000_nic_config,
+               .set_pwr_src = iwl_set_pwr_src,
+       },
+       .eeprom_ops = {
+               .regulatory_bands = {
+                       EEPROM_REG_BAND_1_CHANNELS,
+                       EEPROM_REG_BAND_2_CHANNELS,
+                       EEPROM_REG_BAND_3_CHANNELS,
+                       EEPROM_REG_BAND_4_CHANNELS,
+                       EEPROM_REG_BAND_5_CHANNELS,
+                       EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+                       EEPROM_REG_BAND_52_HT40_CHANNELS
+               },
+               .verify_signature  = iwlcore_eeprom_verify_signature,
+               .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+               .release_semaphore = iwlcore_eeprom_release_semaphore,
+               .calib_version  = iwlagn_eeprom_calib_version,
+               .query_addr = iwlagn_eeprom_query_addr,
+               .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+       },
+       .post_associate = iwl_post_associate,
+       .isr = iwl_isr_ict,
+       .config_ap = iwl_config_ap,
+       .temp_ops = {
+               .temperature = iwlagn_temperature,
+               .set_ct_kill = iwl6000_set_ct_threshold,
+               .set_calib_version = iwl6000_set_calib_version,
+        },
+       .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
+       .debugfs_ops = {
+               .rx_stats_read = iwl_ucode_rx_stats_read,
+               .tx_stats_read = iwl_ucode_tx_stats_read,
+               .general_stats_read = iwl_ucode_general_stats_read,
+               .bt_stats_read = iwl_ucode_bt_stats_read,
+       },
+       .recover_from_tx_stall = iwl_bg_monitor_recover,
+       .check_plcp_health = iwl_good_plcp_health,
+       .check_ack_health = iwl_good_ack_health,
+       .txfifo_flush = iwlagn_txfifo_flush,
+       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+       .tt_ops = {
+               .lower_power_detection = iwl_tt_is_low_power_state,
+               .tt_power_mode = iwl_tt_current_power_mode,
+               .ct_kill_check = iwl_check_for_ct_kill,
+       }
 };
 
 static const struct iwl_ops iwl6000_ops = {
@@ -338,20 +671,16 @@ static const struct iwl_ops iwl6000_ops = {
        .led = &iwlagn_led_ops,
 };
 
-static void do_not_send_bt_config(struct iwl_priv *priv)
-{
-}
-
 static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
        .rxon_assoc = iwlagn_send_rxon_assoc,
        .commit_rxon = iwl_commit_rxon,
        .set_rxon_chain = iwl_set_rxon_chain,
        .set_tx_ant = iwlagn_send_tx_ant_config,
-       .send_bt_config = do_not_send_bt_config,
+       .send_bt_config = iwl6000g2b_send_bt_config,
 };
 
 static const struct iwl_ops iwl6000g2b_ops = {
-       .lib = &iwl6000_lib,
+       .lib = &iwl6000g2b_lib,
        .hcmd = &iwl6000g2b_hcmd,
        .utils = &iwlagn_hcmd_utils,
        .led = &iwlagn_led_ops,
@@ -380,14 +709,14 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -423,7 +752,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -458,7 +787,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
@@ -488,18 +817,22 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -528,13 +861,17 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -560,18 +897,22 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -600,13 +941,17 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -632,18 +977,22 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -672,13 +1021,17 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
        .max_event_log_size = 512,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
        .need_dc_calib = true,
+       .bt_statistics = true,
+       /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+       .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .advanced_bt_coexist = true,
 };
 
 /*
@@ -707,14 +1060,14 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -749,7 +1102,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -784,7 +1137,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -814,14 +1167,52 @@ struct iwl_cfg iwl6050_2agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
+       .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+       .supports_idle = true,
+       .adv_thermal_throttle = true,
+       .support_ct_kill_exit = true,
+       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+       .chain_noise_scale = 1500,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
+       .max_event_log_size = 1024,
+       .ucode_tracing = true,
+       .sensitivity_calib_by_driver = true,
+       .chain_noise_calib_by_driver = true,
+       .need_dc_calib = true,
+};
+
+struct iwl_cfg iwl6050g2_bgn_cfg = {
+       .name = "6050 Series 1x2 BGN Gen2",
+       .fw_name_pre = IWL6050_FW_PRE,
+       .ucode_api_max = IWL6050_UCODE_API_MAX,
+       .ucode_api_min = IWL6050_UCODE_API_MIN,
+       .sku = IWL_SKU_G|IWL_SKU_N,
+       .ops = &iwl6000_ops,
+       .eeprom_size = OTP_LOW_IMAGE_SIZE,
+       .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
+       .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
+       .num_of_queues = IWLAGN_NUM_QUEUES,
+       .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+       .mod_params = &iwlagn_mod_params,
+       .valid_tx_ant = ANT_A,
+       .valid_rx_ant = ANT_AB,
+       .pll_cfg_val = 0,
+       .set_l0s = true,
+       .use_bsm = false,
+       .pa_type = IWL_PA_SYSTEM,
+       .max_ll_items = OTP_MAX_LL_ITEMS_6x50,
+       .shadow_ram_support = true,
+       .ht_greenfield_support = true,
+       .led_compensation = 51,
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1500,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -857,7 +1248,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1500,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
@@ -888,14 +1279,14 @@ struct iwl_cfg iwl6000_3agn_cfg = {
        .shadow_ram_support = true,
        .ht_greenfield_support = true,
        .led_compensation = 51,
-       .use_rts_for_ht = true, /* use rts/cts protection */
+       .use_rts_for_aggregation = true, /* use rts/cts protection */
        .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
        .supports_idle = true,
        .adv_thermal_throttle = true,
        .support_ct_kill_exit = true,
        .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .chain_noise_scale = 1000,
-       .monitor_recover_period = IWL_MONITORING_PERIOD,
+       .monitor_recover_period = IWL_DEF_MONITORING_PERIOD,
        .max_event_log_size = 1024,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,