On Thursday 26 January 2017 03:04 PM, Johannes Berg wrote:
>
>> + /* Should we apply the grace period during beaconing
>> interface
>> + * shutdown also?
>> + */
>> + cfg80211_sched_dfs_chan_update(rdev);
>
> It might make some sense, say if hostapd crashes and you restart it
> automatically or something?
Sure. Initially it looked tricky to handle this. But I guess we can store
the DFS channel and the time stamp (rdev specific) when the beaconing interface
is brought down. cfg80211_dfs_channels_update_work() can use these information
and apply the grace period before setting the DFS channel state back to
'usable'.
>
>> return err;
>> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
>> index 5497d022..090309a 100644
>> --- a/net/wireless/chan.c
>> +++ b/net/wireless/chan.c
>> @@ -456,6 +456,102 @@ bool cfg80211_chandef_dfs_usable(struct wiphy
>> *wiphy,
>> return (r1 + r2 > 0);
>> }
>>
>> +static bool cfg80211_5ghz_sub_chan(struct cfg80211_chan_def
>> *chandef,
>> + struct ieee80211_channel *chan)
>
> This could use some explanation, and I don't see anything that's really
> 5 GHz specific in here, so why that in the function name?
Sure.
>
>> + u32 start_freq_seg0 = 0, end_freq_seg0 = 0;
>> + u32 start_freq_seg1 = 0, end_freq_seg1 = 0;
>> +
>> + if (chandef->chan->center_freq == chan->center_freq)
>> + return true;
>> +
>> + switch (chandef->width) {
>> + case NL80211_CHAN_WIDTH_40:
>> + start_freq_seg0 = chandef->center_freq1 - 20;
>> + end_freq_seg0 = chandef->center_freq1 + 20;
>> + break;
>> + case NL80211_CHAN_WIDTH_80P80:
>> + start_freq_seg1 = chandef->center_freq2 - 40;
>> + end_freq_seg1 = chandef->center_freq2 + 40;
>> + /* fall through */
>> + case NL80211_CHAN_WIDTH_80:
>> + start_freq_seg0 = chandef->center_freq1 - 40;
>> + end_freq_seg0 = chandef->center_freq1 + 40;
>> + break;
>> + case NL80211_CHAN_WIDTH_160:
>> + start_freq_seg0 = chandef->center_freq1 - 80;
>> + end_freq_seg0 = chandef->center_freq1 + 80;
>> + break;
>> + case NL80211_CHAN_WIDTH_20_NOHT:
>> + case NL80211_CHAN_WIDTH_20:
>> + case NL80211_CHAN_WIDTH_5:
>> + case NL80211_CHAN_WIDTH_10:
>> + break;
>> + }
>> +
>> + if (chan->center_freq > start_freq_seg0 &&
>> + chan->center_freq < end_freq_seg0)
>> + return true;
>> +
>> + return chan->center_freq > start_freq_seg1 &&
>> + chan->center_freq < end_freq_seg1;
>> +}
>
> It's also written pretty oddly... The 5/10/20 cases could return
> immediately, the start/end could be replaced by width, and the
> initializations wouldn't be needed at all ... I think we can do better
> here.
Sure, I'll improve this function.
>
>> +bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
>> + struct ieee80211_channel
>> *chan)
>
> Again, nothing 5 GHz specific.
Ok.
>
>> + struct wireless_dev *wdev;
>> +
>> + ASSERT_RTNL();
>> +
>> + if (!(chan->flags & IEEE80211_CHAN_RADAR))
>> + return false;
>> +
>> + list_for_each_entry(wdev, &wiphy->wdev_list, list) {
>> + if (!cfg80211_beaconing_iface_active(wdev))
>> + continue;
>> +
>> + if (cfg80211_5ghz_sub_chan(&wdev->chandef, chan))
>> + return true;
>> + }
>> +
>> + return false;
>> +}
>>
>> static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
>> u32 center_freq,
>> diff --git a/net/wireless/core.h b/net/wireless/core.h
>> index 58ca206..327fe95 100644
>> --- a/net/wireless/core.h
>> +++ b/net/wireless/core.h
>> @@ -459,6 +459,13 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
>> cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
>> const struct cfg80211_chan_def
>> *chandef);
>>
>> +void cfg80211_sched_dfs_chan_update(struct
>> cfg80211_registered_device *rdev);
>> +
>> +bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
>> + struct ieee80211_channel
>> *chan);
>> +
>> +bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev);
>> +
>> static inline unsigned int elapsed_jiffies_msecs(unsigned long
>> start)
>> {
>> unsigned long end = jiffies;
>> diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
>> index 364f900..10bf040 100644
>> --- a/net/wireless/ibss.c
>> +++ b/net/wireless/ibss.c
>> @@ -190,6 +190,7 @@ static void __cfg80211_clear_ibss(struct
>> net_device *dev, bool nowext)
>> if (!nowext)
>> wdev->wext.ibss.ssid_len = 0;
>> #endif
>> + cfg80211_sched_dfs_chan_update(rdev);
>> }
>>
>> void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
>> diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
>> index 2d8518a..ec0b1c2 100644
>> --- a/net/wireless/mesh.c
>> +++ b/net/wireless/mesh.c
>> @@ -262,6 +262,7 @@ int __cfg80211_leave_mesh(struct
>> cfg80211_registered_device *rdev,
>> wdev->beacon_interval = 0;
>> memset(&wdev->chandef, 0, sizeof(wdev->chandef));
>> rdev_set_qos_map(rdev, dev, NULL);
>> + cfg80211_sched_dfs_chan_update(rdev);
>> }
>>
>> return err;
>> diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
>> index 22b3d99..3c7e155 100644
>> --- a/net/wireless/mlme.c
>> +++ b/net/wireless/mlme.c
>> @@ -745,6 +745,12 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev,
>> int freq, int sig_mbm,
>> }
>> EXPORT_SYMBOL(cfg80211_rx_mgmt);
>>
>> +void cfg80211_sched_dfs_chan_update(struct
>> cfg80211_registered_device *rdev)
>> +{
>> + cancel_delayed_work(&rdev->dfs_update_channels_wk);
>> + queue_delayed_work(cfg80211_wq, &rdev-
>>> dfs_update_channels_wk, 0);
>> +}
>
> This uses 0.
>
>> @@ -820,9 +844,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
>> */
>> cfg80211_set_dfs_state(wiphy, chandef,
>> NL80211_DFS_UNAVAILABLE);
>>
>> - timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
>> - queue_delayed_work(cfg80211_wq, &rdev-
>>> dfs_update_channels_wk,
>> - timeout);
>> + cfg80211_sched_dfs_chan_update(rdev);
>
> But this didn't - why does that change?
Since cfg80211_dfs_channels_update_work() can be scheduled multiple times to
run at
different point of time (2 secs - to expire cac for non-ETSI, 30 * 60 secs - to
clear
NOL), cfg80211_sched_dfs_chan_update(rdev) is added to make sure the worker can
also
be fired at nearer time stamp when it is already pending to run at after a
relatively
later point of time. cfg80211_dfs_channels_update_work() uses the time stamp of
channel
DFS state (dfs_state_entered) to set the next DFS state and/or re-schedule the
worker
later.
>
>> +unsigned long regulatory_get_pre_cac_timeout(struct wiphy *wiphy)
>> +{
>> + if (!regulatory_pre_cac_allowed(wiphy))
>> + return REG_PRE_CAC_EXPIRY_GRACE_MS;
>> +
>> + /*
>> + * Return the maximum pre-CAC timeout when pre-CAC is
>> allowed
>> + * in the current dfs domain (ETSI).
>> + */
>> + return -1;
>> +}
>
> Don't ever return -1, that's -EPERM and not really what you want
> anyway.
>
Sure, since the return time is unsigned long I chose to use -1. I'll remove
this function as mentioned in below comment.
> In fact, this doesn't even make sense, since the only caller already
> checks regulatory_pre_cac_allowed() before calling this.
Sure. I originally thought a helper like this would be used multiple places.
But it is not the case now and being used in single place.
Thanks,
Vasanth