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

Reply via email to