mac80211: allow driver to iterate keys
authorJohannes Berg <johannes.berg@intel.com>
Tue, 5 Jul 2011 14:35:39 +0000 (16:35 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Jul 2011 19:05:41 +0000 (15:05 -0400)
When in suspend/wowlan, devices might implement crypto
offload differently (more features), and might require
reprogramming keys for the WoWLAN (as it is the case
for Intel devices that use another uCode image). Thus
allow the driver to iterate all keys in this context.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/net/mac80211.h
net/mac80211/key.c

index 2858b4d02f5f7ed3004de234ad1d2d429e88d886..4703c0f07ba403c466d3866abfc5ec582c39bfaf 100644 (file)
@@ -2849,6 +2849,29 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
 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().
index 0af958c74342431b18056b131faec2d1d6ac05c3..fcab5fe726a113b22cede63a59a389858cab3cdc 100644 (file)
@@ -551,6 +551,39 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
        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;