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 d37865a..61159f8 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 b7f27d5..a1f1a86 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 2003daa..54595eb 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),