cfg80211: add channel tracking for AP and mesh
authorMichal Kazior <michal.kazior@tieto.com>
Fri, 29 Jun 2012 10:46:58 +0000 (12:46 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 29 Jun 2012 11:39:15 +0000 (13:39 +0200)
We need to know which channel is used by a running
AP and mesh for channel context accounting and
finding matching/active interface combination.

STA/IBSS have current_bss already which allows us
to check which channel a vif is tuned to.
Non-fixed channel IBSS can be handled with
additional changes.

Monitor mode is going to be handled differently.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/wireless/ap.c
net/wireless/mesh.c
net/wireless/mlme.c
net/wireless/nl80211.c

index 1fc89c4f930c7bfabc3a2d911f9850ca0166f406..c62bc7864adfd839d5175bc7fc232209895431bf 100644 (file)
@@ -2408,6 +2408,9 @@ struct wireless_dev {
        struct ieee80211_channel *preset_chan;
        enum nl80211_channel_type preset_chantype;
 
+       /* for AP and mesh channel tracking */
+       struct ieee80211_channel *channel;
+
        bool ps;
        int ps_timeout;
 
index 45199cca63d5e07d9f26c4ec093904f8ab47e820..fcc60d8dbefa2bd9a4ae96b42aa4c8b67271cda2 100644 (file)
@@ -24,8 +24,10 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
                return -ENOENT;
 
        err = rdev->ops->stop_ap(&rdev->wiphy, dev);
-       if (!err)
+       if (!err) {
                wdev->beacon_interval = 0;
+               wdev->channel = NULL;
+       }
 
        return err;
 }
index 3b73b07486cfb34197f653f1e4896e1cb56c6173..bab3813447238656ec1ae397492299fd9519069c 100644 (file)
@@ -159,6 +159,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        if (!err) {
                memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
                wdev->mesh_id_len = setup->mesh_id_len;
+               wdev->channel = setup->channel;
        }
 
        return err;
@@ -184,6 +185,7 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
                           enum nl80211_channel_type channel_type)
 {
        struct ieee80211_channel *channel;
+       int err;
 
        channel = rdev_freq_to_chan(rdev, freq, channel_type);
        if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
@@ -205,9 +207,14 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev,
 
                if (!netif_running(wdev->netdev))
                        return -ENETDOWN;
-               return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
-                                                           wdev->netdev,
-                                                           channel);
+
+               err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
+                                                          wdev->netdev,
+                                                          channel);
+               if (!err)
+                       wdev->channel = channel;
+
+               return err;
        }
 
        if (wdev->mesh_id_len)
@@ -249,8 +256,11 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
                return -ENOTCONN;
 
        err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
-       if (!err)
+       if (!err) {
                wdev->mesh_id_len = 0;
+               wdev->channel = NULL;
+       }
+
        return err;
 }
 
index da4406f11929e8235ac934ee40c04cc1b2a1547c..a7882eb8c46e9d345358e9b86a4a111eddc835c4 100644 (file)
@@ -947,6 +947,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
        if (WARN_ON(!chan))
                goto out;
 
+       wdev->channel = chan;
        nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL);
 out:
        wdev_unlock(wdev);
index 20d0fd6d1286ef9a8a0953d707e0a176fe550dd4..12096b4ebf62473d747426d89a4c95354bbe3a0d 100644 (file)
@@ -2488,6 +2488,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                wdev->preset_chan = params.channel;
                wdev->preset_chantype = params.channel_type;
                wdev->beacon_interval = params.beacon_interval;
+               wdev->channel = params.channel;
        }
        return err;
 }