linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Wey-Yi Guy <wey-yi.w.guy@intel.com>
To: linville@tuxdriver.com
Cc: linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net,
	Johannes Berg <johannes.berg@intel.com>,
	Wey-Yi Guy <wey-yi.w.guy@intel.com>
Subject: [PATCH 06/26] iwlwifi: add BT notification support for bt coex
Date: Mon, 23 Aug 2010 07:56:57 -0700	[thread overview]
Message-ID: <1282575437-23270-7-git-send-email-wey-yi.w.guy@intel.com> (raw)
In-Reply-To: <1282575437-23270-1-git-send-email-wey-yi.w.guy@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

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>
---
 drivers/net/wireless/iwlwifi/iwl-6000.c     |  161 ++++++++++++++++++++++++++-
 drivers/net/wireless/iwlwifi/iwl-commands.h |    7 +
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    4 +
 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 fc2eeb0..f049ebc 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,
 	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)
+{
+	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]);
+
+	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);
+}
+
+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,
@@ -451,6 +535,81 @@ static struct iwl_lib_ops iwl6000_lib = {
 	}
 };
 
+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 = {
 	.lib = &iwl6000_lib,
 	.hcmd = &iwlagn_hcmd,
@@ -467,7 +626,7 @@ static struct iwl_hcmd_ops iwl6000g2b_hcmd = {
 };
 
 static const struct iwl_ops iwl6000g2b_ops = {
-	.lib = &iwl6000_lib,
+	.lib = &iwl6000g2b_lib,
 	.hcmd = &iwl6000g2b_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 69fc774..67eaeb6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -178,6 +178,7 @@ enum {
 	REPLY_BT_COEX_PRIO_TABLE = 0xcc,
 	REPLY_BT_COEX_PROT_ENV = 0xcd,
 	REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
+	REPLY_BT_COEX_SCO = 0xcf,
 
 	REPLY_MAX = 0xff
 };
@@ -2456,6 +2457,12 @@ struct iwl6000g2b_bt_cmd {
 	u8 reserved[3];
 };
 
+#define IWL6000G2B_BT_SCO_ACTIVE	cpu_to_le32(BIT(0))
+
+struct iwl6000g2b_bt_sco_cmd {
+	__le32 flags;
+};
+
 /******************************************************************************
  * (6)
  * 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 1ad3303..5d327b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1362,6 +1362,10 @@ struct iwl_priv {
 #endif
 	};
 
+	u8 bt_traffic_load;
+	bool bt_sco_active;
+	struct work_struct bt_traffic_change_work;
+
 	struct iwl_hw_params hw_params;
 
 	u32 inta_mask;
-- 
1.7.0.4


  parent reply	other threads:[~2010-08-23 14:53 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-23 14:56 [PATCH 00/26] iwlwifi update for 2.6.37 Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 01/26] iwlwifi: update out-of-date comments Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 02/26] iwlwifi: comments cleanup Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 03/26] iwlwifi: add 6000g2b BT coexist API Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 04/26] iwlagn: implement advance BT config command Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 05/26] iwlagn: set BT IGNORE for some frames Wey-Yi Guy
2010-08-23 14:56 ` Wey-Yi Guy [this message]
2010-08-23 14:56 ` [PATCH 07/26] iwlagn: let bluetooth traffic load impact rate scale Wey-Yi Guy
2010-08-23 14:56 ` [PATCH 08/26] iwlwifi: reset BT when going down Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 09/26] iwlagn: disable gen2b BT coexistence in IBSS Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 10/26] iwlagn: keep BT settings across restart Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 11/26] iwlwifi: Relax uCode timeout/error checking for 6000g2b Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 12/26] iwlwifi: use antenna A only under high BT load Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 13/26] iwlwifi: add bt full concurrency support Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 14/26] iwlagn: wifi/bt coex configuration sequence Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 15/26] iwlwifi: indicate bt_kill condition when receive tx reply Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 16/26] iwlwifi: add debugfs to control stuck queue timer Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 17/26] iwlwifi: add bt_init_traffic_load as configurable parameter Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 18/26] iwlagn: add bt prio_boost to .cfg Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 19/26] iwlagn: parsing uart message and take actions Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 20/26] iwlagn: add additional bt related parameters Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 21/26] iwlagn: add bt_ch_announce module parameter Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 22/26] iwlagn: set traffic load based on multiple factors Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 23/26] iwlagn: generic bt coex functions Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 24/26] iwlagn: update bt status upon scan complete Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 25/26] iwlwifi: add bt traffic load debugfs file Wey-Yi Guy
2010-08-23 14:57 ` [PATCH 26/26] iwlwifi: disable aggregation queue if stopped early Wey-Yi Guy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1282575437-23270-7-git-send-email-wey-yi.w.guy@intel.com \
    --to=wey-yi.w.guy@intel.com \
    --cc=ipw3945-devel@lists.sourceforge.net \
    --cc=johannes.berg@intel.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).