iwlwifi: mvm: Add support for connection monitor offload
authorHila Gonen <hila.gonen@intel.com>
Wed, 13 Mar 2013 16:00:03 +0000 (18:00 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 29 May 2013 07:03:24 +0000 (09:03 +0200)
The firmware supports periodic keep alive and beacon monitoring,
so advertise connection monitor offload capability by setting
IEEE80211_HW_CONNECTION_MONITOR flag. Implement missed beacons
notification handler. Call ieee80211_beacon_loss in case of
missed beacons, so AP probing by mac80211 can be triggered.

Signed-off-by: Hila Gonen <hila.gonen@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c

index db6f474..cbfb3be 100644 (file)
@@ -164,6 +164,8 @@ enum {
        CARD_STATE_CMD = 0xa0,
        CARD_STATE_NOTIFICATION = 0xa1,
 
+       MISSED_BEACONS_NOTIFICATION = 0xa2,
+
        REPLY_RX_PHY_CMD = 0xc0,
        REPLY_RX_MPDU_CMD = 0xc1,
        BA_NOTIF = 0xc5,
@@ -943,6 +945,24 @@ struct iwl_card_state_notif {
 } __packed; /* CARD_STATE_NTFY_API_S_VER_1 */
 
 /**
+ * struct iwl_missed_beacons_notif - information on missed beacons
+ * ( MISSED_BEACONS_NOTIFICATION = 0xa2 )
+ * @mac_id: interface ID
+ * @consec_missed_beacons_since_last_rx: number of consecutive missed
+ *     beacons since last RX.
+ * @consec_missed_beacons: number of consecutive missed beacons
+ * @num_expected_beacons:
+ * @num_recvd_beacons:
+ */
+struct iwl_missed_beacons_notif {
+       __le32 mac_id;
+       __le32 consec_missed_beacons_since_last_rx;
+       __le32 consec_missed_beacons;
+       __le32 num_expected_beacons;
+       __le32 num_recvd_beacons;
+} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
+
+/**
  * struct iwl_set_calib_default_cmd - set default value for calibration.
  * ( SET_CALIB_DEFAULT_CMD = 0x8e )
  * @calib_index: the calibration to set value for
index dc5f4ef..b4e8e59 100644 (file)
@@ -1050,3 +1050,28 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
                     rate);
        return 0;
 }
+
+static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
+                                        struct ieee80211_vif *vif)
+{
+       u16 *id = _data;
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+       if (mvmvif->id == *id)
+               ieee80211_beacon_loss(vif);
+}
+
+int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
+                                   struct iwl_rx_cmd_buffer *rxb,
+                                   struct iwl_device_cmd *cmd)
+{
+       struct iwl_rx_packet *pkt = rxb_addr(rxb);
+       struct iwl_missed_beacons_notif *missed_beacons = (void *)pkt->data;
+       u16 id = (u16)le32_to_cpu(missed_beacons->mac_id);
+
+       ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+                                                  IEEE80211_IFACE_ITER_NORMAL,
+                                                  iwl_mvm_beacon_loss_iterator,
+                                                  &id);
+       return 0;
+}
index c26f6b5..dc50020 100644 (file)
@@ -152,7 +152,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                    IEEE80211_HW_SUPPORTS_PS |
                    IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
                    IEEE80211_HW_AMPDU_AGGREGATION |
-                   IEEE80211_HW_TIMING_BEACON_ONLY;
+                   IEEE80211_HW_TIMING_BEACON_ONLY |
+                   IEEE80211_HW_CONNECTION_MONITOR;
 
        hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
        hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
index a288552..0e74503 100644 (file)
@@ -552,6 +552,9 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
 int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
                            struct iwl_rx_cmd_buffer *rxb,
                            struct iwl_device_cmd *cmd);
+int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
+                                   struct iwl_rx_cmd_buffer *rxb,
+                                   struct iwl_device_cmd *cmd);
 
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
index 8431637..d7a199b 100644 (file)
@@ -227,6 +227,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
        RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
        RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
 
+       RX_HANDLER(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif,
+                  false),
+
        RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
 };
 #undef RX_HANDLER
@@ -289,6 +292,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
        CMD(NET_DETECT_HOTSPOTS_CMD),
        CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
        CMD(CARD_STATE_NOTIFICATION),
+       CMD(MISSED_BEACONS_NOTIFICATION),
        CMD(BT_COEX_PRIO_TABLE),
        CMD(BT_COEX_PROT_ENV),
        CMD(BT_PROFILE_NOTIFICATION),