Message ID | 1387209049-25529-1-git-send-email-marek.puzyniak@tieto.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
On Mon, 2013-12-16 at 16:50 +0100, Marek Puzyniak wrote: > In AP mode DFS channel state is changed to DFS_AVAILABLE > after successful CAC and remains as such until a radar > signal is detected during the In-Service Monitoring. > When AP is stopped it is no longer monitoring current channel > for radar signals. DFS channel state should be changed > to DFS_USABLE when last AP interface is stopped. Starting AP > again on that channel will start CAC instead of starting radiation. Applied. Since it didn't apply/compile on 3.13, I put it into -next (even though you said before that it should be in 3.13 ... sorry. gotta make sure your patches actually apply where you want them) johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> In AP mode DFS channel state is changed to DFS_AVAILABLE > after successful CAC and remains as such until a radar > signal is detected during the In-Service Monitoring. > When AP is stopped it is no longer monitoring current channel > for radar signals. DFS channel state should be changed > to DFS_USABLE when last AP interface is stopped. Starting AP > again on that channel will start CAC instead of starting radiation. > Sorry for answering after so many revisions, but ... why do you think this is required? Many APs first do a CAC on all available channels, but then pick one channel and use that, while being able to switch to another channel immediately. WIth this patch (if I understand that correctly), this is not possible anymore. Why do you think it is required? I can not find this requirement in ETSI, at least. To quote from ETSI 301.893: Once the RLAN has started operations on an Available Channel, then that channel becomes an Operating Channel. During normal operation, the master device shall monitor all Operating Channels (In-Service Monitoring) to ensure that there is no radar operating within these channel(s). If no radar was detected on an Operating Channel but the RLAN stops operating on that channel, then the channel becomes an Available Channel. I think this patch is wrong and should not be applied. Thanks, Simon -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, 2013-12-17 at 15:44 +0100, Simon Wunderlich wrote: > > In AP mode DFS channel state is changed to DFS_AVAILABLE > > after successful CAC and remains as such until a radar > > signal is detected during the In-Service Monitoring. > > When AP is stopped it is no longer monitoring current channel > > for radar signals. DFS channel state should be changed > > to DFS_USABLE when last AP interface is stopped. Starting AP > > again on that channel will start CAC instead of starting radiation. > > > > Sorry for answering after so many revisions, but ... why do you think this is > required? Many APs first do a CAC on all available channels, but then pick one > channel and use that, while being able to switch to another channel > immediately. I'll drop the patch for now - please discuss :P johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 324e8d8..28d1a3c 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -6,6 +6,39 @@ #include "rdev-ops.h" +static bool cfg80211_is_last_ap_running(struct cfg80211_registered_device *rdev, + struct net_device *dev) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wireless_dev *wdev_iter; + + ASSERT_WDEV_LOCK(wdev); + + if (rdev->num_running_ifaces == 1) { + /* Last running AP iface */ + return true; + } + + /* More running interfaces */ + list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { + if (wdev_iter == wdev) + continue; + + if (!wdev_iter->netdev) + continue; + + if (!netif_running(wdev_iter->netdev)) { + continue; + } + + if (wdev_iter->iftype == NL80211_IFTYPE_AP) { + return false; + } + } + + return true; +} + static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, struct net_device *dev) { @@ -31,6 +64,9 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, wdev->ssid_len = 0; } + if (cfg80211_is_last_ap_running(rdev, dev)) + cfg80211_leave_dfs_chandef(wdev->wiphy, &wdev->preset_chandef); + return err; } diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 78559b5..54c217a 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -490,6 +490,44 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, return r; } +static void cfg80211_leave_dfs_chans(struct wiphy *wiphy, + u32 center_freq, + u32 bandwidth) +{ + struct ieee80211_channel *c; + u32 freq, start_freq, end_freq; + + start_freq = cfg80211_get_start_freq(center_freq, bandwidth); + end_freq = cfg80211_get_end_freq(center_freq, bandwidth); + + for (freq = start_freq; freq <= end_freq; freq += 20) { + c = ieee80211_get_channel(wiphy, freq); + if (!c) + continue; + if (c->dfs_state != NL80211_DFS_AVAILABLE) + continue; + + c->dfs_state = NL80211_DFS_USABLE; + c->dfs_state_entered = jiffies; + } +} + +void cfg80211_leave_dfs_chandef(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + int width; + + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return; + + width = cfg80211_chandef_get_width(chandef); + cfg80211_leave_dfs_chans(wiphy, chandef->center_freq1, width); + + if (!chandef->center_freq2) + return; + + cfg80211_leave_dfs_chans(wiphy, chandef->center_freq2, width); +} static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, u32 center_freq, u32 bandwidth, diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d..4ed2c81 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -398,6 +398,17 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, void cfg80211_dfs_channels_update_work(struct work_struct *work); +/** + * cfg80211_leave_dfs_chandef - Leaving dfs chandef + * @wiphy: the wiphy + * @chandef: chandef for the current channel + * + * This function is called when dfs chandef is being not used for different + * reasons. Change channels DFS_AVAILABLE to DFS_USABLE again. Leave channels + * DFS_UNAVAILABLE untouched. + */ +void cfg80211_leave_dfs_chandef(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef); static inline int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
In AP mode DFS channel state is changed to DFS_AVAILABLE after successful CAC and remains as such until a radar signal is detected during the In-Service Monitoring. When AP is stopped it is no longer monitoring current channel for radar signals. DFS channel state should be changed to DFS_USABLE when last AP interface is stopped. Starting AP again on that channel will start CAC instead of starting radiation. Signed-off-by: Marek Puzyniak <marek.puzyniak@tieto.com> --- Patch v1: *Initial version. Partially in mac80211 and cfg80211. Patch v2: *Moved all implementation to cfg80211. Patch v3: *Rephrase patch description. Patch v4: *Fix coding style, *Do not check if RADAR flag is set, when dfs channel state was AVAILABLE change it to USABLE, *Handle multiBSSID APs - Change DFS channel state when last AP was stoped. Patch v5: *Fix coding style, *Remove unnecessary and nested wdev_lock. net/wireless/ap.c | 36 ++++++++++++++++++++++++++++++++++++ net/wireless/chan.c | 38 ++++++++++++++++++++++++++++++++++++++ net/wireless/core.h | 11 +++++++++++ 3 files changed, 85 insertions(+)