iwlwifi: mvm: handle BT-coex notification
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Thu, 17 Jan 2013 12:20:29 +0000 (14:20 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 6 Mar 2013 15:47:59 +0000 (16:47 +0100)
The BT-Coex notification is sent by the fw when there are
updates wrt. BT activity. Driver action might be taken
based on the info in this notification.

For now, update the Ack/Cts_kill_msk if HID / SCO / A2DP
profiles are active.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c

index d37865af32549a368c52fb13176533cee2c871f9..61159f8abe78849d6a7ba15e882bc74c2f40c701 100644 (file)
@@ -64,6 +64,7 @@
 #include "fw-api-bt-coex.h"
 #include "iwl-modparams.h"
 #include "mvm.h"
+#include "iwl-debug.h"
 
 #define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant)                 \
        [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) |    \
@@ -240,3 +241,52 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
        return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
                                    sizeof(cmd), &cmd);
 }
+
+int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
+                            struct iwl_rx_cmd_buffer *rxb,
+                            struct iwl_device_cmd *dev_cmd)
+{
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
+       struct iwl_bt_coex_cmd cmd = {};
+       enum iwl_bt_kill_msk bt_kill_msk;
+
+       IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
+       IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not ");
+       IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
+       IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load);
+       IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
+                      notif->bt_agg_traffic_load);
+       IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
+
+       /* Low latency BT profile is active: give higher prio to BT */
+       if (BT_MBOX_MSG(notif, 3, SCO_STATE)  ||
+           BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
+           BT_MBOX_MSG(notif, 3, SNIFF_STATE))
+               bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
+       else
+               bt_kill_msk = BT_KILL_MSK_DEFAULT;
+
+       /* Don't send HCMD if there is no update */
+       if (bt_kill_msk == mvm->bt_kill_msk)
+               return 0;
+
+       IWL_DEBUG_COEX(mvm,
+                      "Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n",
+                      bt_kill_msk,
+                      BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
+                      BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
+                      BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
+
+       mvm->bt_kill_msk = bt_kill_msk;
+       cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
+       cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
+
+       cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
+
+       if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd))
+               IWL_ERR(mvm, "Failed to sent BT Coex CMD\n");
+
+       /* This handler is ASYNC */
+       return 0;
+}
index b7f27d59fc244d4d202cc2f451c898a3ba35bbc6..a1f1a86643e594ed84f7603785e256c93605171e 100644 (file)
@@ -334,6 +334,9 @@ struct iwl_mvm {
 #ifdef CONFIG_PM_SLEEP
        int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
 #endif
+
+       /* BT-Coex */
+       u8 bt_kill_msk;
 };
 
 /* Extract MVM priv from op_mode and _hw */
@@ -507,5 +510,8 @@ void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
 /* BT Coex */
 int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
+int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
+                            struct iwl_rx_cmd_buffer *rxb,
+                            struct iwl_device_cmd *cmd);
 
 #endif /* __IWL_MVM_H__ */
index 2003daa0cf7620ec087ca5f8de86a04e7f377f36..54595eb7b92a239df75ed0268205958850f2bb80 100644 (file)
@@ -230,6 +230,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
        RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
        RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
 
+       RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
+
        RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
        RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),