cfg80211: notify drivers about frame registrations

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>
This commit is contained in:
Johannes Berg 2010-10-13 12:06:23 +02:00 committed by John W. Linville
parent 7a8266524a
commit 271733cf84
2 changed files with 27 additions and 3 deletions

View file

@ -1147,6 +1147,9 @@ struct cfg80211_pmksa {
* allows the driver to adjust the dynamic ps timeout value. * allows the driver to adjust the dynamic ps timeout value.
* @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. * @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 { struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy); int (*suspend)(struct wiphy *wiphy);
@ -1297,6 +1300,10 @@ struct cfg80211_ops {
int (*set_cqm_rssi_config)(struct wiphy *wiphy, int (*set_cqm_rssi_config)(struct wiphy *wiphy,
struct net_device *dev, struct net_device *dev,
s32 rssi_thold, u32 rssi_hyst); s32 rssi_thold, u32 rssi_hyst);
void (*mgmt_frame_register)(struct wiphy *wiphy,
struct net_device *dev,
u16 frame_type, bool reg);
}; };
/* /*

View file

@ -764,6 +764,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid,
u16 frame_type, const u8 *match_data, u16 frame_type, const u8 *match_data,
int match_len) int match_len)
{ {
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct cfg80211_mgmt_registration *reg, *nreg; struct cfg80211_mgmt_registration *reg, *nreg;
int err = 0; int err = 0;
u16 mgmt_type; 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); nreg->frame_type = cpu_to_le16(frame_type);
list_add(&nreg->list, &wdev->mgmt_registrations); 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: out:
spin_unlock_bh(&wdev->mgmt_registrations_lock); spin_unlock_bh(&wdev->mgmt_registrations_lock);
return err; return err;
} }
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) 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; struct cfg80211_mgmt_registration *reg, *tmp;
spin_lock_bh(&wdev->mgmt_registrations_lock); spin_lock_bh(&wdev->mgmt_registrations_lock);
list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) {
if (reg->nlpid == nlpid) { if (reg->nlpid != nlpid)
list_del(&reg->list); continue;
kfree(reg);
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); spin_unlock_bh(&wdev->mgmt_registrations_lock);