cfg80211/mac80211: refactor cfg80211_chandef_dfs_required()

Some interface types don't require DFS (such as STATION, P2P_CLIENT
etc).  In order to centralize these decisions, make
cfg80211_chandef_dfs_required() take the iftype into consideration.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Luciano Coelho 2014-02-18 11:40:36 +02:00 committed by Johannes Berg
parent cb2d956dd3
commit 2beb6dab2d
6 changed files with 104 additions and 62 deletions

View File

@ -446,10 +446,13 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
* cfg80211_chandef_dfs_required - checks if radar detection is required
* @wiphy: the wiphy to validate against
* @chandef: the channel definition to check
* Return: 1 if radar detection is required, 0 if it is not, < 0 on error
* @iftype: the interface type as specified in &enum nl80211_iftype
* Returns:
* 1 if radar detection is required, 0 if it is not, < 0 on error
*/
int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef);
const struct cfg80211_chan_def *chandef,
enum nl80211_iftype);
/**
* ieee80211_chandef_rate_flags - returns rate flags for a channel

View File

@ -228,7 +228,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
enum nl80211_bss_scan_width scan_width;
bool have_higher_than_11mbit;
bool radar_required = false;
bool radar_required;
int err;
sdata_assert_lock(sdata);
@ -284,21 +284,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
&chandef);
&chandef, NL80211_IFTYPE_ADHOC);
if (err < 0) {
sdata_info(sdata,
"Failed to join IBSS, invalid chandef\n");
return;
}
if (err > 0) {
if (!ifibss->userspace_handles_dfs) {
sdata_info(sdata,
"Failed to join IBSS, DFS channel without control program\n");
return;
}
radar_required = true;
if (err > 0 && !ifibss->userspace_handles_dfs) {
sdata_info(sdata,
"Failed to join IBSS, DFS channel without control program\n");
return;
}
radar_required = err;
mutex_lock(&local->mtx);
if (ieee80211_vif_use_channel(sdata, &chandef,
ifibss->fixed_channel ?
@ -777,7 +776,8 @@ static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
* unavailable.
*/
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
&ifibss->chandef);
&ifibss->chandef,
NL80211_IFTYPE_ADHOC);
if (err > 0)
cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef,
GFP_ATOMIC);
@ -876,17 +876,17 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
}
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
&params.chandef);
&params.chandef,
NL80211_IFTYPE_ADHOC);
if (err < 0)
goto disconnect;
if (err) {
if (err > 0 && !ifibss->userspace_handles_dfs) {
/* IBSS-DFS only allowed with a control program */
if (!ifibss->userspace_handles_dfs)
goto disconnect;
params.radar_required = true;
goto disconnect;
}
params.radar_required = err;
if (cfg80211_chandef_identical(&params.chandef,
&sdata->vif.bss_conf.chandef)) {
ibss_dbg(sdata,

View File

@ -903,14 +903,15 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
}
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
&params.chandef);
&params.chandef,
NL80211_IFTYPE_MESH_POINT);
if (err < 0)
return false;
if (err) {
params.radar_required = true;
if (err > 0)
/* TODO: DFS not (yet) supported */
return false;
}
params.radar_required = err;
if (cfg80211_chandef_identical(&params.chandef,
&sdata->vif.bss_conf.chandef)) {

View File

@ -326,28 +326,57 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef)
const struct cfg80211_chan_def *chandef,
enum nl80211_iftype iftype)
{
int width;
int r;
int ret;
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return -EINVAL;
width = cfg80211_chandef_get_width(chandef);
if (width < 0)
return -EINVAL;
switch (iftype) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_MESH_POINT:
width = cfg80211_chandef_get_width(chandef);
if (width < 0)
return -EINVAL;
r = cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq1,
width);
if (r)
return r;
ret = cfg80211_get_chans_dfs_required(wiphy,
chandef->center_freq1,
width);
if (ret < 0)
return ret;
else if (ret > 0)
return BIT(chandef->width);
if (!chandef->center_freq2)
return 0;
if (!chandef->center_freq2)
return 0;
return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
width);
ret = cfg80211_get_chans_dfs_required(wiphy,
chandef->center_freq2,
width);
if (ret < 0)
return ret;
else if (ret > 0)
return BIT(chandef->width);
break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_UNSPECIFIED:
break;
case NUM_NL80211_IFTYPES:
WARN_ON(1);
}
return 0;
}
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
@ -749,7 +778,8 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
!cfg80211_go_permissive_chan(rdev, chandef->chan))
prohibited_flags |= IEEE80211_CHAN_NO_IR;
if (cfg80211_chandef_dfs_required(wiphy, chandef) > 0 &&
if (cfg80211_chandef_dfs_required(wiphy, chandef,
NL80211_IFTYPE_UNSPECIFIED) > 0 &&
cfg80211_chandef_dfs_available(wiphy, chandef)) {
/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
prohibited_flags = IEEE80211_CHAN_DISABLED;
@ -779,6 +809,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
enum cfg80211_chan_mode *chanmode,
u8 *radar_detect)
{
int ret;
*chan = NULL;
*chanmode = CHAN_MODE_UNDEFINED;
@ -821,8 +853,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
*chan = wdev->chandef.chan;
*chanmode = CHAN_MODE_SHARED;
if (cfg80211_chandef_dfs_required(wdev->wiphy,
&wdev->chandef))
ret = cfg80211_chandef_dfs_required(wdev->wiphy,
&wdev->chandef,
wdev->iftype);
WARN_ON(ret < 0);
if (ret > 0)
*radar_detect |= BIT(wdev->chandef.width);
}
return;
@ -831,8 +866,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
*chan = wdev->chandef.chan;
*chanmode = CHAN_MODE_SHARED;
if (cfg80211_chandef_dfs_required(wdev->wiphy,
&wdev->chandef))
ret = cfg80211_chandef_dfs_required(wdev->wiphy,
&wdev->chandef,
wdev->iftype);
WARN_ON(ret < 0);
if (ret > 0)
*radar_detect |= BIT(wdev->chandef.width);
}
return;

View File

@ -179,10 +179,13 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
NL80211_IFTYPE_MESH_POINT))
return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy, &setup->chandef);
err = cfg80211_chandef_dfs_required(wdev->wiphy,
&setup->chandef,
NL80211_IFTYPE_MESH_POINT);
if (err < 0)
return err;
if (err)
if (err > 0)
radar_detect_width = BIT(setup->chandef.width);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,

View File

@ -3275,12 +3275,15 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
wdev->iftype))
return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
err = cfg80211_chandef_dfs_required(wdev->wiphy,
&params.chandef,
NL80211_IFTYPE_AP);
if (err < 0)
return err;
if (err) {
radar_detect_width = BIT(params.chandef.width);
if (err > 0) {
params.radar_required = true;
radar_detect_width = BIT(params.chandef.width);
}
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
@ -5806,7 +5809,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (wdev->cac_started)
return -EBUSY;
err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef);
err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
NL80211_IFTYPE_UNSPECIFIED);
if (err < 0)
return err;
@ -5942,22 +5946,15 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
wdev->iftype))
return -EINVAL;
switch (dev->ieee80211_ptr->iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
err = cfg80211_chandef_dfs_required(wdev->wiphy,
&params.chandef);
if (err < 0)
return err;
if (err) {
radar_detect_width = BIT(params.chandef.width);
params.radar_required = true;
}
break;
default:
break;
err = cfg80211_chandef_dfs_required(wdev->wiphy,
&params.chandef,
wdev->iftype);
if (err < 0)
return err;
if (err > 0) {
radar_detect_width = BIT(params.chandef.width);
params.radar_required = true;
}
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,