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:
parent
cb2d956dd3
commit
2beb6dab2d
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
¶ms.chandef);
|
||||
¶ms.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(¶ms.chandef,
|
||||
&sdata->vif.bss_conf.chandef)) {
|
||||
ibss_dbg(sdata,
|
||||
|
|
|
@ -903,14 +903,15 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
|
|||
}
|
||||
|
||||
err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
|
||||
¶ms.chandef);
|
||||
¶ms.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(¶ms.chandef,
|
||||
&sdata->vif.bss_conf.chandef)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ¶ms.chandef);
|
||||
err = cfg80211_chandef_dfs_required(wdev->wiphy,
|
||||
¶ms.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,
|
||||
¶ms.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,
|
||||
¶ms.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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user