cfg80211: notify drivers about frame registrations
authorJohannes Berg <johannes.berg@intel.com>
Wed, 13 Oct 2010 10:06:23 +0000 (12:06 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 13 Oct 2010 19:45:22 +0000 (15:45 -0400)
Drivers may need to adjust their filters according
to frame registrations, so notify them about them.

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

index 24d5b58..2a7936d 100644 (file)
@@ -1147,6 +1147,9 @@ struct cfg80211_pmksa {
  *     allows the driver to adjust the dynamic ps timeout value.
  * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
  *
+ * @mgmt_frame_register: Notify driver that a management frame type was
+ *     registered. Note that this callback may not sleep, and cannot run
+ *     concurrently with itself.
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy);
@@ -1297,6 +1300,10 @@ struct cfg80211_ops {
        int     (*set_cqm_rssi_config)(struct wiphy *wiphy,
                                       struct net_device *dev,
                                       s32 rssi_thold, u32 rssi_hyst);
+
+       void    (*mgmt_frame_register)(struct wiphy *wiphy,
+                                      struct net_device *dev,
+                                      u16 frame_type, bool reg);
 };
 
 /*
index caf11a4..26838d9 100644 (file)
@@ -764,6 +764,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
                                u16 frame_type, const u8 *match_data,
                                int match_len)
 {
+       struct wiphy *wiphy = wdev->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
        struct cfg80211_mgmt_registration *reg, *nreg;
        int err = 0;
        u16 mgmt_type;
@@ -810,22 +812,37 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
        nreg->frame_type = cpu_to_le16(frame_type);
        list_add(&nreg->list, &wdev->mgmt_registrations);
 
+       if (rdev->ops->mgmt_frame_register)
+               rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+                                              frame_type, true);
+
  out:
        spin_unlock_bh(&wdev->mgmt_registrations_lock);
+
        return err;
 }
 
 void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid)
 {
+       struct wiphy *wiphy = wdev->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
        struct cfg80211_mgmt_registration *reg, *tmp;
 
        spin_lock_bh(&wdev->mgmt_registrations_lock);
 
        list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
-               if (reg->nlpid == nlpid) {
-                       list_del(&reg->list);
-                       kfree(reg);
+               if (reg->nlpid != nlpid)
+                       continue;
+
+               if (rdev->ops->mgmt_frame_register) {
+                       u16 frame_type = le16_to_cpu(reg->frame_type);
+
+                       rdev->ops->mgmt_frame_register(wiphy, wdev->netdev,
+                                                      frame_type, false);
                }
+
+               list_del(&reg->list);
+               kfree(reg);
        }
 
        spin_unlock_bh(&wdev->mgmt_registrations_lock);