cfg80211: rework chandef checking and export it
Some of the chandef checking that we do in cfg80211 to check if a channel is supported or not is also needed in mac80211, so rework that a bit and export the functions that are needed. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
@@ -58,6 +58,8 @@
|
|||||||
* structures here describe these capabilities in detail.
|
* structures here describe these capabilities in detail.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct wiphy;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* wireless hardware capability structures
|
* wireless hardware capability structures
|
||||||
*/
|
*/
|
||||||
@@ -387,6 +389,22 @@ const struct cfg80211_chan_def *
|
|||||||
cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
|
cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
|
||||||
const struct cfg80211_chan_def *chandef2);
|
const struct cfg80211_chan_def *chandef2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_chandef_valid - check if a channel definition is valid
|
||||||
|
* @chandef: the channel definition to check
|
||||||
|
*/
|
||||||
|
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_chandef_usable - check if secondary channels can be used
|
||||||
|
* @wiphy: the wiphy to validate against
|
||||||
|
* @chandef: the channel definition to check
|
||||||
|
* @prohibited_flags: the regulatory chanenl flags that must not be set
|
||||||
|
*/
|
||||||
|
bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
||||||
|
const struct cfg80211_chan_def *chandef,
|
||||||
|
u32 prohibited_flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum survey_info_flags - survey information flags
|
* enum survey_info_flags - survey information flags
|
||||||
*
|
*
|
||||||
@@ -1045,9 +1063,6 @@ struct ieee80211_txq_params {
|
|||||||
u8 aifs;
|
u8 aifs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* from net/wireless.h */
|
|
||||||
struct wiphy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: Scanning and BSS list handling
|
* DOC: Scanning and BSS list handling
|
||||||
*
|
*
|
||||||
|
@@ -44,7 +44,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_chandef_create);
|
EXPORT_SYMBOL(cfg80211_chandef_create);
|
||||||
|
|
||||||
bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
|
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
u32 control_freq;
|
u32 control_freq;
|
||||||
|
|
||||||
@@ -105,6 +105,7 @@ bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(cfg80211_chandef_valid);
|
||||||
|
|
||||||
static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
|
static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
|
||||||
int *pri40, int *pri80)
|
int *pri40, int *pri80)
|
||||||
@@ -187,9 +188,9 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_chandef_compatible);
|
EXPORT_SYMBOL(cfg80211_chandef_compatible);
|
||||||
|
|
||||||
bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
||||||
u32 center_freq, u32 bandwidth,
|
u32 center_freq, u32 bandwidth,
|
||||||
u32 prohibited_flags)
|
u32 prohibited_flags)
|
||||||
{
|
{
|
||||||
struct ieee80211_channel *c;
|
struct ieee80211_channel *c;
|
||||||
u32 freq;
|
u32 freq;
|
||||||
@@ -205,55 +206,88 @@ bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cfg80211_check_beacon_chans(struct wiphy *wiphy,
|
bool cfg80211_chandef_usable(struct wiphy *wiphy,
|
||||||
u32 center_freq, u32 bw)
|
const struct cfg80211_chan_def *chandef,
|
||||||
|
u32 prohibited_flags)
|
||||||
{
|
{
|
||||||
return cfg80211_secondary_chans_ok(wiphy, center_freq, bw,
|
struct ieee80211_sta_ht_cap *ht_cap;
|
||||||
IEEE80211_CHAN_DISABLED |
|
struct ieee80211_sta_vht_cap *vht_cap;
|
||||||
IEEE80211_CHAN_PASSIVE_SCAN |
|
u32 width, control_freq;
|
||||||
IEEE80211_CHAN_NO_IBSS |
|
|
||||||
IEEE80211_CHAN_RADAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
||||||
struct cfg80211_chan_def *chandef)
|
|
||||||
{
|
|
||||||
u32 width;
|
|
||||||
bool res;
|
|
||||||
|
|
||||||
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
|
||||||
|
|
||||||
if (WARN_ON(!cfg80211_chan_def_valid(chandef))) {
|
|
||||||
trace_cfg80211_return_bool(false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap;
|
||||||
|
vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap;
|
||||||
|
|
||||||
|
control_freq = chandef->chan->center_freq;
|
||||||
|
|
||||||
switch (chandef->width) {
|
switch (chandef->width) {
|
||||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
|
||||||
case NL80211_CHAN_WIDTH_20:
|
case NL80211_CHAN_WIDTH_20:
|
||||||
|
if (!ht_cap->ht_supported)
|
||||||
|
return false;
|
||||||
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
width = 20;
|
width = 20;
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_40:
|
case NL80211_CHAN_WIDTH_40:
|
||||||
width = 40;
|
width = 40;
|
||||||
|
if (!ht_cap->ht_supported)
|
||||||
|
return false;
|
||||||
|
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
||||||
|
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
|
||||||
|
return false;
|
||||||
|
if (chandef->center_freq1 < control_freq &&
|
||||||
|
chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
||||||
|
return false;
|
||||||
|
if (chandef->center_freq1 > control_freq &&
|
||||||
|
chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_80:
|
|
||||||
case NL80211_CHAN_WIDTH_80P80:
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
|
||||||
|
return false;
|
||||||
|
case NL80211_CHAN_WIDTH_80:
|
||||||
|
if (!vht_cap->vht_supported)
|
||||||
|
return false;
|
||||||
width = 80;
|
width = 80;
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_160:
|
case NL80211_CHAN_WIDTH_160:
|
||||||
|
if (!vht_cap->vht_supported)
|
||||||
|
return false;
|
||||||
|
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
|
||||||
|
return false;
|
||||||
width = 160;
|
width = 160;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
trace_cfg80211_return_bool(false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width);
|
/* TODO: missing regulatory check on 80/160 bandwidth */
|
||||||
|
|
||||||
if (res && chandef->center_freq2)
|
if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
|
||||||
res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2,
|
width, prohibited_flags))
|
||||||
width);
|
return false;
|
||||||
|
|
||||||
|
if (!chandef->center_freq2)
|
||||||
|
return true;
|
||||||
|
return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2,
|
||||||
|
width, prohibited_flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(cfg80211_chandef_usable);
|
||||||
|
|
||||||
|
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
|
||||||
|
struct cfg80211_chan_def *chandef)
|
||||||
|
{
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
trace_cfg80211_reg_can_beacon(wiphy, chandef);
|
||||||
|
|
||||||
|
res = cfg80211_chandef_usable(wiphy, chandef,
|
||||||
|
IEEE80211_CHAN_DISABLED |
|
||||||
|
IEEE80211_CHAN_PASSIVE_SCAN |
|
||||||
|
IEEE80211_CHAN_NO_IBSS |
|
||||||
|
IEEE80211_CHAN_RADAR);
|
||||||
|
|
||||||
trace_cfg80211_return_bool(res);
|
trace_cfg80211_return_bool(res);
|
||||||
return res;
|
return res;
|
||||||
|
@@ -483,12 +483,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
|||||||
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||||
enum nl80211_iftype iftype, int num);
|
enum nl80211_iftype iftype, int num);
|
||||||
|
|
||||||
bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef);
|
|
||||||
|
|
||||||
bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
|
||||||
u32 center_freq, u32 bandwidth,
|
|
||||||
u32 prohibited_flags);
|
|
||||||
|
|
||||||
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
||||||
|
|
||||||
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
||||||
|
@@ -1420,63 +1420,33 @@ static int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
|
|||||||
ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap;
|
ht_cap = &rdev->wiphy.bands[chandef->chan->band]->ht_cap;
|
||||||
vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
|
vht_cap = &rdev->wiphy.bands[chandef->chan->band]->vht_cap;
|
||||||
|
|
||||||
if (!cfg80211_chan_def_valid(chandef))
|
if (!cfg80211_chandef_valid(chandef))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (chandef->width) {
|
switch (chandef->width) {
|
||||||
case NL80211_CHAN_WIDTH_20:
|
case NL80211_CHAN_WIDTH_20:
|
||||||
if (!ht_cap->ht_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
case NL80211_CHAN_WIDTH_20_NOHT:
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
width = 20;
|
width = 20;
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_40:
|
case NL80211_CHAN_WIDTH_40:
|
||||||
width = 40;
|
width = 40;
|
||||||
/* quick early regulatory check */
|
|
||||||
if (chandef->center_freq1 < control_freq &&
|
|
||||||
chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
|
|
||||||
return -EINVAL;
|
|
||||||
if (chandef->center_freq1 > control_freq &&
|
|
||||||
chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!ht_cap->ht_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
|
|
||||||
ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_80:
|
case NL80211_CHAN_WIDTH_80:
|
||||||
width = 80;
|
width = 80;
|
||||||
if (!vht_cap->vht_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_80P80:
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
width = 80;
|
width = 80;
|
||||||
if (!vht_cap->vht_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
break;
|
||||||
case NL80211_CHAN_WIDTH_160:
|
case NL80211_CHAN_WIDTH_160:
|
||||||
width = 160;
|
width = 160;
|
||||||
if (!vht_cap->vht_supported)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
|
|
||||||
return -EINVAL;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq1,
|
if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
|
||||||
width, IEEE80211_CHAN_DISABLED))
|
IEEE80211_CHAN_DISABLED))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (chandef->center_freq2 &&
|
|
||||||
!cfg80211_secondary_chans_ok(&rdev->wiphy, chandef->center_freq2,
|
|
||||||
width, IEEE80211_CHAN_DISABLED))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* TODO: missing regulatory check on bandwidth */
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1841,7 +1811,7 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
|
|||||||
static int nl80211_send_chandef(struct sk_buff *msg,
|
static int nl80211_send_chandef(struct sk_buff *msg,
|
||||||
struct cfg80211_chan_def *chandef)
|
struct cfg80211_chan_def *chandef)
|
||||||
{
|
{
|
||||||
WARN_ON(!cfg80211_chan_def_valid(chandef));
|
WARN_ON(!cfg80211_chandef_valid(chandef));
|
||||||
|
|
||||||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
|
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
|
||||||
chandef->chan->center_freq))
|
chandef->chan->center_freq))
|
||||||
|
Reference in New Issue
Block a user