aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-08-23 10:56:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-25 14:33:21 -0400
commit9e4afc21895476114f131b70d1e8fdc3a9c75bb3 (patch)
tree53c858628a54f258589b5b5d7ea23871f0c58992 /drivers/net/wireless
parentd44ae69e80358ff88d39a14d92c27dba4e90c0c5 (diff)
iwlwifi: add BT notification support for bt coex
When advanced bt coex enabled, uCode will send bt status notification to driver, here add support for it. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c161
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h4
3 files changed, 171 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index fc2eeb00c78c..f049ebc4a6aa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -377,6 +377,90 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
377 return iwl_send_cmd_sync(priv, &hcmd); 377 return iwl_send_cmd_sync(priv, &hcmd);
378} 378}
379 379
380static void iwl6000g2b_bt_traffic_change_work(struct work_struct *work)
381{
382 struct iwl_priv *priv =
383 container_of(work, struct iwl_priv, bt_traffic_change_work);
384 int smps_request = -1;
385
386 switch (priv->bt_traffic_load) {
387 case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
388 smps_request = IEEE80211_SMPS_AUTOMATIC;
389 break;
390 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
391 smps_request = IEEE80211_SMPS_DYNAMIC;
392 break;
393 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
394 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
395 smps_request = IEEE80211_SMPS_STATIC;
396 break;
397 default:
398 IWL_ERR(priv, "Invalid BT traffic load: %d\n",
399 priv->bt_traffic_load);
400 break;
401 }
402
403 mutex_lock(&priv->mutex);
404
405 if (smps_request != -1 &&
406 priv->vif && priv->vif->type == NL80211_IFTYPE_STATION)
407 ieee80211_request_smps(priv->vif, smps_request);
408
409 mutex_unlock(&priv->mutex);
410}
411
412static void iwl6000g2b_bt_coex_profile_notif(struct iwl_priv *priv,
413 struct iwl_rx_mem_buffer *rxb)
414{
415 struct iwl_rx_packet *pkt = rxb_addr(rxb);
416 struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
417 struct iwl6000g2b_bt_sco_cmd sco_cmd = { .flags = 0 };
418
419 IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
420 IWL_DEBUG_NOTIF(priv, " status: %d\n", coex->bt_status);
421 IWL_DEBUG_NOTIF(priv, " traffic load: %d\n", coex->bt_traffic_load);
422 IWL_DEBUG_NOTIF(priv, " CI compliance: %d\n", coex->bt_ci_compliance);
423 IWL_DEBUG_NOTIF(priv, " UART msg: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x:"
424 "%.2x:%.2x\n",
425 coex->uart_msg[0], coex->uart_msg[1], coex->uart_msg[2],
426 coex->uart_msg[3], coex->uart_msg[4], coex->uart_msg[5],
427 coex->uart_msg[6], coex->uart_msg[7]);
428
429 if (coex->bt_traffic_load != priv->bt_traffic_load) {
430 priv->bt_traffic_load = coex->bt_traffic_load;
431
432 queue_work(priv->workqueue, &priv->bt_traffic_change_work);
433 }
434
435 /* FIXME: add defines for this check */
436 priv->bt_sco_active = coex->uart_msg[3] & 1;
437 if (priv->bt_sco_active)
438 sco_cmd.flags |= IWL6000G2B_BT_SCO_ACTIVE;
439 iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
440 sizeof(sco_cmd), &sco_cmd, NULL);
441}
442
443void iwl6000g2b_rx_handler_setup(struct iwl_priv *priv)
444{
445 iwlagn_rx_handler_setup(priv);
446 priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
447 iwl6000g2b_bt_coex_profile_notif;
448}
449
450static void iwl6000g2b_bt_setup_deferred_work(struct iwl_priv *priv)
451{
452 iwlagn_setup_deferred_work(priv);
453
454 INIT_WORK(&priv->bt_traffic_change_work,
455 iwl6000g2b_bt_traffic_change_work);
456
457}
458
459static void iwl6000g2b_bt_cancel_deferred_work(struct iwl_priv *priv)
460{
461 cancel_work_sync(&priv->bt_traffic_change_work);
462}
463
380static struct iwl_lib_ops iwl6000_lib = { 464static struct iwl_lib_ops iwl6000_lib = {
381 .set_hw_params = iwl6000_hw_set_hw_params, 465 .set_hw_params = iwl6000_hw_set_hw_params,
382 .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, 466 .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
@@ -451,6 +535,81 @@ static struct iwl_lib_ops iwl6000_lib = {
451 } 535 }
452}; 536};
453 537
538static struct iwl_lib_ops iwl6000g2b_lib = {
539 .set_hw_params = iwl6000_hw_set_hw_params,
540 .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
541 .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
542 .txq_set_sched = iwlagn_txq_set_sched,
543 .txq_agg_enable = iwlagn_txq_agg_enable,
544 .txq_agg_disable = iwlagn_txq_agg_disable,
545 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
546 .txq_free_tfd = iwl_hw_txq_free_tfd,
547 .txq_init = iwl_hw_tx_queue_init,
548 .rx_handler_setup = iwl6000g2b_rx_handler_setup,
549 .setup_deferred_work = iwl6000g2b_bt_setup_deferred_work,
550 .cancel_deferred_work = iwl6000g2b_bt_cancel_deferred_work,
551 .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
552 .load_ucode = iwlagn_load_ucode,
553 .dump_nic_event_log = iwl_dump_nic_event_log,
554 .dump_nic_error_log = iwl_dump_nic_error_log,
555 .dump_csr = iwl_dump_csr,
556 .dump_fh = iwl_dump_fh,
557 .init_alive_start = iwlagn_init_alive_start,
558 .alive_notify = iwlagn_alive_notify,
559 .send_tx_power = iwlagn_send_tx_power,
560 .update_chain_flags = iwl_update_chain_flags,
561 .set_channel_switch = iwl6000_hw_channel_switch,
562 .apm_ops = {
563 .init = iwl_apm_init,
564 .stop = iwl_apm_stop,
565 .config = iwl6000_nic_config,
566 .set_pwr_src = iwl_set_pwr_src,
567 },
568 .eeprom_ops = {
569 .regulatory_bands = {
570 EEPROM_REG_BAND_1_CHANNELS,
571 EEPROM_REG_BAND_2_CHANNELS,
572 EEPROM_REG_BAND_3_CHANNELS,
573 EEPROM_REG_BAND_4_CHANNELS,
574 EEPROM_REG_BAND_5_CHANNELS,
575 EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
576 EEPROM_REG_BAND_52_HT40_CHANNELS
577 },
578 .verify_signature = iwlcore_eeprom_verify_signature,
579 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
580 .release_semaphore = iwlcore_eeprom_release_semaphore,
581 .calib_version = iwlagn_eeprom_calib_version,
582 .query_addr = iwlagn_eeprom_query_addr,
583 .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
584 },
585 .post_associate = iwl_post_associate,
586 .isr = iwl_isr_ict,
587 .config_ap = iwl_config_ap,
588 .temp_ops = {
589 .temperature = iwlagn_temperature,
590 .set_ct_kill = iwl6000_set_ct_threshold,
591 .set_calib_version = iwl6000_set_calib_version,
592 },
593 .manage_ibss_station = iwlagn_manage_ibss_station,
594 .update_bcast_station = iwl_update_bcast_station,
595 .debugfs_ops = {
596 .rx_stats_read = iwl_ucode_rx_stats_read,
597 .tx_stats_read = iwl_ucode_tx_stats_read,
598 .general_stats_read = iwl_ucode_general_stats_read,
599 .bt_stats_read = iwl_ucode_bt_stats_read,
600 },
601 .recover_from_tx_stall = iwl_bg_monitor_recover,
602 .check_plcp_health = iwl_good_plcp_health,
603 .check_ack_health = iwl_good_ack_health,
604 .txfifo_flush = iwlagn_txfifo_flush,
605 .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
606 .tt_ops = {
607 .lower_power_detection = iwl_tt_is_low_power_state,
608 .tt_power_mode = iwl_tt_current_power_mode,
609 .ct_kill_check = iwl_check_for_ct_kill,
610 }
611};
612
454static const struct iwl_ops iwl6000_ops = { 613static const struct iwl_ops iwl6000_ops = {
455 .lib = &iwl6000_lib, 614 .lib = &iwl6000_lib,
456 .hcmd = &iwlagn_hcmd, 615 .hcmd = &iwlagn_hcmd,
@@ -467,7 +626,7 @@ static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
467}; 626};
468 627
469static const struct iwl_ops iwl6000g2b_ops = { 628static const struct iwl_ops iwl6000g2b_ops = {
470 .lib = &iwl6000_lib, 629 .lib = &iwl6000g2b_lib,
471 .hcmd = &iwl6000g2b_hcmd, 630 .hcmd = &iwl6000g2b_hcmd,
472 .utils = &iwlagn_hcmd_utils, 631 .utils = &iwlagn_hcmd_utils,
473 .led = &iwlagn_led_ops, 632 .led = &iwlagn_led_ops,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 69fc7745edaa..67eaeb6822cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -178,6 +178,7 @@ enum {
178 REPLY_BT_COEX_PRIO_TABLE = 0xcc, 178 REPLY_BT_COEX_PRIO_TABLE = 0xcc,
179 REPLY_BT_COEX_PROT_ENV = 0xcd, 179 REPLY_BT_COEX_PROT_ENV = 0xcd,
180 REPLY_BT_COEX_PROFILE_NOTIF = 0xce, 180 REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
181 REPLY_BT_COEX_SCO = 0xcf,
181 182
182 REPLY_MAX = 0xff 183 REPLY_MAX = 0xff
183}; 184};
@@ -2456,6 +2457,12 @@ struct iwl6000g2b_bt_cmd {
2456 u8 reserved[3]; 2457 u8 reserved[3];
2457}; 2458};
2458 2459
2460#define IWL6000G2B_BT_SCO_ACTIVE cpu_to_le32(BIT(0))
2461
2462struct iwl6000g2b_bt_sco_cmd {
2463 __le32 flags;
2464};
2465
2459/****************************************************************************** 2466/******************************************************************************
2460 * (6) 2467 * (6)
2461 * Spectrum Management (802.11h) Commands, Responses, Notifications: 2468 * Spectrum Management (802.11h) Commands, Responses, Notifications:
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 1ad330342ffc..5d327b44533b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1362,6 +1362,10 @@ struct iwl_priv {
1362#endif 1362#endif
1363 }; 1363 };
1364 1364
1365 u8 bt_traffic_load;
1366 bool bt_sco_active;
1367 struct work_struct bt_traffic_change_work;
1368
1365 struct iwl_hw_params hw_params; 1369 struct iwl_hw_params hw_params;
1366 1370
1367 u32 inta_mask; 1371 u32 inta_mask;