void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
                               struct ieee80211_sta *pubsta, bool block);
 
+/**
+ * ieee80211_iter_keys - iterate keys programmed into the device
+ * @hw: pointer obtained from ieee80211_alloc_hw()
+ * @vif: virtual interface to iterate, may be %NULL for all
+ * @iter: iterator function that will be called for each key
+ * @iter_data: custom data to pass to the iterator function
+ *
+ * This function can be used to iterate all the keys known to
+ * mac80211, even those that weren't previously programmed into
+ * the device. This is intended for use in WoWLAN if the device
+ * needs reprogramming of the keys during suspend. Note that due
+ * to locking reasons, it is also only safe to call this at few
+ * spots since it must hold the RTNL and be able to sleep.
+ */
+void ieee80211_iter_keys(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif,
+                        void (*iter)(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif *vif,
+                                     struct ieee80211_sta *sta,
+                                     struct ieee80211_key_conf *key,
+                                     void *data),
+                        void *iter_data);
+
 /**
  * ieee80211_ap_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
 
        mutex_unlock(&sdata->local->key_mtx);
 }
 
+void ieee80211_iter_keys(struct ieee80211_hw *hw,
+                        struct ieee80211_vif *vif,
+                        void (*iter)(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif *vif,
+                                     struct ieee80211_sta *sta,
+                                     struct ieee80211_key_conf *key,
+                                     void *data),
+                        void *iter_data)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_key *key;
+       struct ieee80211_sub_if_data *sdata;
+
+       ASSERT_RTNL();
+
+       mutex_lock(&local->key_mtx);
+       if (vif) {
+               sdata = vif_to_sdata(vif);
+               list_for_each_entry(key, &sdata->key_list, list)
+                       iter(hw, &sdata->vif,
+                            key->sta ? &key->sta->sta : NULL,
+                            &key->conf, iter_data);
+       } else {
+               list_for_each_entry(sdata, &local->interfaces, list)
+                       list_for_each_entry(key, &sdata->key_list, list)
+                               iter(hw, &sdata->vif,
+                                    key->sta ? &key->sta->sta : NULL,
+                                    &key->conf, iter_data);
+       }
+       mutex_unlock(&local->key_mtx);
+}
+EXPORT_SYMBOL(ieee80211_iter_keys);
+
 void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_key *key;