mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
nl80211: Add set/get for frag/rts threshold and retry limits
Add new nl80211 attributes that can be used with NL80211_CMD_SET_WIPHY and NL80211_CMD_GET_WIPHY to manage fragmentation/RTS threshold and retry limits. Since these values are stored in struct wiphy, remove the local copy from mac80211 where feasible (frag & rts threshold). The retry limits are currently needed in struct ieee80211_conf, but these could be eventually removed since the driver should have access to the values in struct wiphy. Signed-off-by: Jouni Malinen <j@w1.fi> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
9e52b0623c
commit
b9a5f8cab7
@ -46,8 +46,10 @@
|
||||
* to get a list of all present wiphys.
|
||||
* @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
|
||||
* %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
|
||||
* %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or
|
||||
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
|
||||
* %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
|
||||
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
|
||||
* %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
|
||||
* and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
|
||||
* @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
|
||||
* or rename notification. Has attributes %NL80211_ATTR_WIPHY and
|
||||
* %NL80211_ATTR_WIPHY_NAME.
|
||||
@ -337,6 +339,18 @@ enum nl80211_commands {
|
||||
* NL80211_CHAN_HT20 = HT20 only
|
||||
* NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
|
||||
* NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
|
||||
* @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
|
||||
* less than or equal to the RTS threshold; allowed range: 1..255;
|
||||
* dot11ShortRetryLimit; u8
|
||||
* @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is
|
||||
* greater than the RTS threshold; allowed range: 1..255;
|
||||
* dot11ShortLongLimit; u8
|
||||
* @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum
|
||||
* length in octets for frames; allowed range: 256..8000, disable
|
||||
* fragmentation with (u32)-1; dot11FragmentationThreshold; u32
|
||||
* @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
|
||||
* larger than or equal to this use RTS/CTS handshake); allowed range:
|
||||
* 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
|
||||
*
|
||||
* @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
|
||||
* @NL80211_ATTR_IFNAME: network interface name
|
||||
@ -565,6 +579,12 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_FREQ_FIXED,
|
||||
|
||||
|
||||
NL80211_ATTR_WIPHY_RETRY_SHORT,
|
||||
NL80211_ATTR_WIPHY_RETRY_LONG,
|
||||
NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
|
||||
NL80211_ATTR_WIPHY_RTS_THRESHOLD,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
@ -743,6 +743,20 @@ struct cfg80211_ibss_params {
|
||||
bool channel_fixed;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum wiphy_params_flags - set_wiphy_params bitfield values
|
||||
* WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
|
||||
* WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed
|
||||
* WIPHY_PARAM_FRAG_THRESHOLD: wiphy->frag_threshold has changed
|
||||
* WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed
|
||||
*/
|
||||
enum wiphy_params_flags {
|
||||
WIPHY_PARAM_RETRY_SHORT = 1 << 0,
|
||||
WIPHY_PARAM_RETRY_LONG = 1 << 1,
|
||||
WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2,
|
||||
WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_ops - backend description for wireless configuration
|
||||
*
|
||||
@ -823,6 +837,11 @@ struct cfg80211_ibss_params {
|
||||
* cfg80211_ibss_joined(), also call that function when changing BSSID due
|
||||
* to a merge.
|
||||
* @leave_ibss: Leave the IBSS.
|
||||
*
|
||||
* @set_wiphy_params: Notify that wiphy parameters have changed;
|
||||
* @changed bitfield (see &enum wiphy_params_flags) describes which values
|
||||
* have changed. The actual parameter values are available in
|
||||
* struct wiphy. If returning an error, no value should be changed.
|
||||
*/
|
||||
struct cfg80211_ops {
|
||||
int (*suspend)(struct wiphy *wiphy);
|
||||
@ -912,6 +931,8 @@ struct cfg80211_ops {
|
||||
int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct cfg80211_ibss_params *params);
|
||||
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
|
||||
|
||||
int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -945,6 +966,11 @@ struct cfg80211_ops {
|
||||
* @signal_type: signal type reported in &struct cfg80211_bss.
|
||||
* @cipher_suites: supported cipher suites
|
||||
* @n_cipher_suites: number of supported cipher suites
|
||||
* @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
|
||||
* @retry_long: Retry limit for long frames (dot11LongRetryLimit)
|
||||
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
|
||||
* -1 = fragmentation disabled, only odd values >= 256 used
|
||||
* @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
|
||||
*/
|
||||
struct wiphy {
|
||||
/* assign these fields before you register the wiphy */
|
||||
@ -967,6 +993,11 @@ struct wiphy {
|
||||
int n_cipher_suites;
|
||||
const u32 *cipher_suites;
|
||||
|
||||
u8 retry_short;
|
||||
u8 retry_long;
|
||||
u32 frag_threshold;
|
||||
u32 rts_threshold;
|
||||
|
||||
/* If multiple wiphys are registered and you're handed e.g.
|
||||
* a regular netdev with assigned ieee80211_ptr, you won't
|
||||
* know whether it points to a wiphy your driver has registered
|
||||
@ -1345,6 +1376,25 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
|
||||
struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
|
||||
struct iw_freq *freq);
|
||||
|
||||
int cfg80211_wext_siwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra);
|
||||
int cfg80211_wext_giwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra);
|
||||
int cfg80211_wext_siwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra);
|
||||
int cfg80211_wext_giwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra);
|
||||
int cfg80211_wext_siwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra);
|
||||
int cfg80211_wext_giwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra);
|
||||
|
||||
/*
|
||||
* callbacks for asynchronous cfg80211 methods, notification
|
||||
* functions and BSS handling helpers
|
||||
|
@ -1298,6 +1298,32 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
|
||||
return ieee80211_ibss_leave(sdata);
|
||||
}
|
||||
|
||||
static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
|
||||
{
|
||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
|
||||
int err;
|
||||
|
||||
if (local->ops->set_rts_threshold) {
|
||||
err = local->ops->set_rts_threshold(
|
||||
local_to_hw(local), wiphy->rts_threshold);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & WIPHY_PARAM_RETRY_SHORT)
|
||||
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
|
||||
if (changed & WIPHY_PARAM_RETRY_LONG)
|
||||
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
|
||||
if (changed &
|
||||
(WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -1336,4 +1362,5 @@ struct cfg80211_ops mac80211_config_ops = {
|
||||
.disassoc = ieee80211_disassoc,
|
||||
.join_ibss = ieee80211_join_ibss,
|
||||
.leave_ibss = ieee80211_leave_ibss,
|
||||
.set_wiphy_params = ieee80211_set_wiphy_params,
|
||||
};
|
||||
|
@ -52,13 +52,13 @@ static const struct file_operations name## _ops = { \
|
||||
DEBUGFS_READONLY_FILE(frequency, 20, "%d",
|
||||
local->hw.conf.channel->center_freq);
|
||||
DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
|
||||
local->rts_threshold);
|
||||
local->hw.wiphy->rts_threshold);
|
||||
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
|
||||
local->fragmentation_threshold);
|
||||
local->hw.wiphy->frag_threshold);
|
||||
DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
|
||||
local->hw.conf.short_frame_max_tx_count);
|
||||
local->hw.wiphy->retry_short);
|
||||
DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
|
||||
local->hw.conf.long_frame_max_tx_count);
|
||||
local->hw.wiphy->retry_long);
|
||||
DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
|
||||
local->total_ps_buffered);
|
||||
DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
|
||||
|
@ -643,9 +643,6 @@ struct ieee80211_local {
|
||||
|
||||
struct rate_control_ref *rate_ctrl;
|
||||
|
||||
int rts_threshold;
|
||||
int fragmentation_threshold;
|
||||
|
||||
struct crypto_blkcipher *wep_tx_tfm;
|
||||
struct crypto_blkcipher *wep_rx_tfm;
|
||||
u32 wep_iv;
|
||||
|
@ -776,10 +776,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||
/* set up some defaults */
|
||||
local->hw.queues = 1;
|
||||
local->hw.max_rates = 1;
|
||||
local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
|
||||
local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
|
||||
local->hw.conf.long_frame_max_tx_count = 4;
|
||||
local->hw.conf.short_frame_max_tx_count = 7;
|
||||
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
|
||||
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
|
||||
local->hw.conf.radio_enabled = true;
|
||||
|
||||
INIT_LIST_HEAD(&local->interfaces);
|
||||
|
@ -516,7 +516,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
|
||||
len = min_t(int, tx->skb->len + FCS_LEN,
|
||||
tx->local->fragmentation_threshold);
|
||||
tx->local->hw.wiphy->frag_threshold);
|
||||
|
||||
/* set up the tx rate control struct we give the RC algo */
|
||||
txrc.hw = local_to_hw(tx->local);
|
||||
@ -527,8 +527,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
|
||||
|
||||
/* set up RTS protection if desired */
|
||||
if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD &&
|
||||
len > tx->local->rts_threshold) {
|
||||
if (len > tx->local->hw.wiphy->rts_threshold) {
|
||||
txrc.rts = rts = true;
|
||||
}
|
||||
|
||||
@ -770,7 +769,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
||||
struct sk_buff *skb = tx->skb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
int frag_threshold = tx->local->fragmentation_threshold;
|
||||
int frag_threshold = tx->local->hw.wiphy->frag_threshold;
|
||||
int hdrlen;
|
||||
int fragnum;
|
||||
|
||||
@ -1088,7 +1087,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
|
||||
if (tx->flags & IEEE80211_TX_FRAGMENTED) {
|
||||
if ((tx->flags & IEEE80211_TX_UNICAST) &&
|
||||
skb->len + FCS_LEN > local->fragmentation_threshold &&
|
||||
skb->len + FCS_LEN > local->hw.wiphy->frag_threshold &&
|
||||
!(info->flags & IEEE80211_TX_CTL_AMPDU))
|
||||
tx->flags |= IEEE80211_TX_FRAGMENTED;
|
||||
else
|
||||
|
@ -1044,7 +1044,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
|
||||
/* setup RTS threshold */
|
||||
if (local->ops->set_rts_threshold)
|
||||
local->ops->set_rts_threshold(hw, local->rts_threshold);
|
||||
local->ops->set_rts_threshold(hw, hw->wiphy->rts_threshold);
|
||||
|
||||
/* reconfigure hardware */
|
||||
ieee80211_hw_config(local, ~0);
|
||||
|
@ -472,132 +472,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_ioctl_siwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
if (rts->disabled)
|
||||
local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
|
||||
else if (!rts->fixed)
|
||||
/* if the rts value is not fixed, then take default */
|
||||
local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
|
||||
else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
|
||||
return -EINVAL;
|
||||
else
|
||||
local->rts_threshold = rts->value;
|
||||
|
||||
/* If the wlan card performs RTS/CTS in hardware/firmware,
|
||||
* configure it here */
|
||||
|
||||
if (local->ops->set_rts_threshold)
|
||||
local->ops->set_rts_threshold(local_to_hw(local),
|
||||
local->rts_threshold);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_ioctl_giwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
rts->value = local->rts_threshold;
|
||||
rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
|
||||
rts->fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211_ioctl_siwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
if (frag->disabled)
|
||||
local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
|
||||
else if (!frag->fixed)
|
||||
local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
|
||||
else if (frag->value < 256 ||
|
||||
frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
|
||||
return -EINVAL;
|
||||
else {
|
||||
/* Fragment length must be even, so strip LSB. */
|
||||
local->fragmentation_threshold = frag->value & ~0x1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_ioctl_giwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
frag->value = local->fragmentation_threshold;
|
||||
frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD);
|
||||
frag->fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211_ioctl_siwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
if (retry->disabled ||
|
||||
(retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (retry->flags & IW_RETRY_MAX) {
|
||||
local->hw.conf.long_frame_max_tx_count = retry->value;
|
||||
} else if (retry->flags & IW_RETRY_MIN) {
|
||||
local->hw.conf.short_frame_max_tx_count = retry->value;
|
||||
} else {
|
||||
local->hw.conf.long_frame_max_tx_count = retry->value;
|
||||
local->hw.conf.short_frame_max_tx_count = retry->value;
|
||||
}
|
||||
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211_ioctl_giwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
|
||||
retry->disabled = 0;
|
||||
if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
|
||||
/* first return min value, iwconfig will ask max value
|
||||
* later if needed */
|
||||
retry->flags |= IW_RETRY_LIMIT;
|
||||
retry->value = local->hw.conf.short_frame_max_tx_count;
|
||||
if (local->hw.conf.long_frame_max_tx_count !=
|
||||
local->hw.conf.short_frame_max_tx_count)
|
||||
retry->flags |= IW_RETRY_MIN;
|
||||
return 0;
|
||||
}
|
||||
if (retry->flags & IW_RETRY_MAX) {
|
||||
retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
|
||||
retry->value = local->hw.conf.long_frame_max_tx_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ieee80211_ioctl_siwencode(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_point *erq, char *keybuf)
|
||||
@ -1050,14 +924,14 @@ static const iw_handler ieee80211_handler[] =
|
||||
(iw_handler) NULL, /* -- hole -- */
|
||||
(iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
|
||||
(iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
|
||||
(iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
|
||||
(iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
|
||||
(iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
|
||||
(iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
|
||||
(iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
|
||||
(iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
|
||||
(iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
|
||||
(iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
|
||||
(iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
|
||||
(iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
|
||||
(iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
|
||||
(iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
|
||||
(iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
|
||||
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
|
||||
(iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
|
||||
(iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
|
||||
(iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
|
||||
|
@ -273,6 +273,16 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
|
||||
drv->wiphy.dev.class = &ieee80211_class;
|
||||
drv->wiphy.dev.platform_data = drv;
|
||||
|
||||
/*
|
||||
* Initialize wiphy parameters to IEEE 802.11 MIB default values.
|
||||
* Fragmentation and RTS threshold are disabled by default with the
|
||||
* special -1 value.
|
||||
*/
|
||||
drv->wiphy.retry_short = 7;
|
||||
drv->wiphy.retry_long = 4;
|
||||
drv->wiphy.frag_threshold = (u32) -1;
|
||||
drv->wiphy.rts_threshold = (u32) -1;
|
||||
|
||||
return &drv->wiphy;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_new);
|
||||
|
@ -61,6 +61,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
|
||||
[NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
|
||||
[NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
|
||||
|
||||
[NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
|
||||
[NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
|
||||
@ -204,6 +208,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
|
||||
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
|
||||
NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
|
||||
|
||||
NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
|
||||
dev->wiphy.retry_short);
|
||||
NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
|
||||
dev->wiphy.retry_long);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
|
||||
dev->wiphy.frag_threshold);
|
||||
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
|
||||
dev->wiphy.rts_threshold);
|
||||
|
||||
NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
|
||||
dev->wiphy.max_scan_ssids);
|
||||
NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN,
|
||||
@ -416,6 +430,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
||||
struct cfg80211_registered_device *rdev;
|
||||
int result = 0, rem_txq_params = 0;
|
||||
struct nlattr *nl_txq_params;
|
||||
u32 changed;
|
||||
u8 retry_short = 0, retry_long = 0;
|
||||
u32 frag_threshold = 0, rts_threshold = 0;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
@ -530,6 +547,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
||||
goto bad_res;
|
||||
}
|
||||
|
||||
changed = 0;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
|
||||
retry_short = nla_get_u8(
|
||||
info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
|
||||
if (retry_short == 0) {
|
||||
result = -EINVAL;
|
||||
goto bad_res;
|
||||
}
|
||||
changed |= WIPHY_PARAM_RETRY_SHORT;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
|
||||
retry_long = nla_get_u8(
|
||||
info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
|
||||
if (retry_long == 0) {
|
||||
result = -EINVAL;
|
||||
goto bad_res;
|
||||
}
|
||||
changed |= WIPHY_PARAM_RETRY_LONG;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
|
||||
frag_threshold = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
|
||||
if (frag_threshold < 256) {
|
||||
result = -EINVAL;
|
||||
goto bad_res;
|
||||
}
|
||||
if (frag_threshold != (u32) -1) {
|
||||
/*
|
||||
* Fragments (apart from the last one) are required to
|
||||
* have even length. Make the fragmentation code
|
||||
* simpler by stripping LSB should someone try to use
|
||||
* odd threshold value.
|
||||
*/
|
||||
frag_threshold &= ~0x1;
|
||||
}
|
||||
changed |= WIPHY_PARAM_FRAG_THRESHOLD;
|
||||
}
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
|
||||
rts_threshold = nla_get_u32(
|
||||
info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
|
||||
changed |= WIPHY_PARAM_RTS_THRESHOLD;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
u8 old_retry_short, old_retry_long;
|
||||
u32 old_frag_threshold, old_rts_threshold;
|
||||
|
||||
if (!rdev->ops->set_wiphy_params) {
|
||||
result = -EOPNOTSUPP;
|
||||
goto bad_res;
|
||||
}
|
||||
|
||||
old_retry_short = rdev->wiphy.retry_short;
|
||||
old_retry_long = rdev->wiphy.retry_long;
|
||||
old_frag_threshold = rdev->wiphy.frag_threshold;
|
||||
old_rts_threshold = rdev->wiphy.rts_threshold;
|
||||
|
||||
if (changed & WIPHY_PARAM_RETRY_SHORT)
|
||||
rdev->wiphy.retry_short = retry_short;
|
||||
if (changed & WIPHY_PARAM_RETRY_LONG)
|
||||
rdev->wiphy.retry_long = retry_long;
|
||||
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
|
||||
rdev->wiphy.frag_threshold = frag_threshold;
|
||||
if (changed & WIPHY_PARAM_RTS_THRESHOLD)
|
||||
rdev->wiphy.rts_threshold = rts_threshold;
|
||||
|
||||
result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
|
||||
if (result) {
|
||||
rdev->wiphy.retry_short = old_retry_short;
|
||||
rdev->wiphy.retry_long = old_retry_long;
|
||||
rdev->wiphy.frag_threshold = old_frag_threshold;
|
||||
rdev->wiphy.rts_threshold = old_rts_threshold;
|
||||
}
|
||||
}
|
||||
|
||||
bad_res:
|
||||
mutex_unlock(&rdev->mtx);
|
||||
|
@ -314,3 +314,154 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_freq);
|
||||
|
||||
int cfg80211_wext_siwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
u32 orts = wdev->wiphy->rts_threshold;
|
||||
int err;
|
||||
|
||||
if (rts->disabled || !rts->fixed)
|
||||
wdev->wiphy->rts_threshold = (u32) -1;
|
||||
else if (rts->value < 0)
|
||||
return -EINVAL;
|
||||
else
|
||||
wdev->wiphy->rts_threshold = rts->value;
|
||||
|
||||
err = rdev->ops->set_wiphy_params(wdev->wiphy,
|
||||
WIPHY_PARAM_RTS_THRESHOLD);
|
||||
if (err)
|
||||
wdev->wiphy->rts_threshold = orts;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_siwrts);
|
||||
|
||||
int cfg80211_wext_giwrts(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *rts, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
rts->value = wdev->wiphy->rts_threshold;
|
||||
rts->disabled = rts->value == (u32) -1;
|
||||
rts->fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_giwrts);
|
||||
|
||||
int cfg80211_wext_siwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
u32 ofrag = wdev->wiphy->frag_threshold;
|
||||
int err;
|
||||
|
||||
if (frag->disabled || !frag->fixed)
|
||||
wdev->wiphy->frag_threshold = (u32) -1;
|
||||
else if (frag->value < 256)
|
||||
return -EINVAL;
|
||||
else {
|
||||
/* Fragment length must be even, so strip LSB. */
|
||||
wdev->wiphy->frag_threshold = frag->value & ~0x1;
|
||||
}
|
||||
|
||||
err = rdev->ops->set_wiphy_params(wdev->wiphy,
|
||||
WIPHY_PARAM_FRAG_THRESHOLD);
|
||||
if (err)
|
||||
wdev->wiphy->frag_threshold = ofrag;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_siwfrag);
|
||||
|
||||
int cfg80211_wext_giwfrag(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *frag, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
frag->value = wdev->wiphy->frag_threshold;
|
||||
frag->disabled = frag->value == (u32) -1;
|
||||
frag->fixed = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_giwfrag);
|
||||
|
||||
int cfg80211_wext_siwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
u32 changed = 0;
|
||||
u8 olong = wdev->wiphy->retry_long;
|
||||
u8 oshort = wdev->wiphy->retry_short;
|
||||
int err;
|
||||
|
||||
if (retry->disabled ||
|
||||
(retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
|
||||
return -EINVAL;
|
||||
|
||||
if (retry->flags & IW_RETRY_LONG) {
|
||||
wdev->wiphy->retry_long = retry->value;
|
||||
changed |= WIPHY_PARAM_RETRY_LONG;
|
||||
} else if (retry->flags & IW_RETRY_SHORT) {
|
||||
wdev->wiphy->retry_short = retry->value;
|
||||
changed |= WIPHY_PARAM_RETRY_SHORT;
|
||||
} else {
|
||||
wdev->wiphy->retry_short = retry->value;
|
||||
wdev->wiphy->retry_long = retry->value;
|
||||
changed |= WIPHY_PARAM_RETRY_LONG;
|
||||
changed |= WIPHY_PARAM_RETRY_SHORT;
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
return 0;
|
||||
|
||||
err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
|
||||
if (err) {
|
||||
wdev->wiphy->retry_short = oshort;
|
||||
wdev->wiphy->retry_long = olong;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_siwretry);
|
||||
|
||||
int cfg80211_wext_giwretry(struct net_device *dev,
|
||||
struct iw_request_info *info,
|
||||
struct iw_param *retry, char *extra)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
||||
retry->disabled = 0;
|
||||
|
||||
if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
|
||||
/*
|
||||
* First return short value, iwconfig will ask long value
|
||||
* later if needed
|
||||
*/
|
||||
retry->flags |= IW_RETRY_LIMIT;
|
||||
retry->value = wdev->wiphy->retry_short;
|
||||
if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
|
||||
retry->flags |= IW_RETRY_LONG;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (retry->flags & IW_RETRY_LONG) {
|
||||
retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
|
||||
retry->value = wdev->wiphy->retry_long;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_wext_giwretry);
|
||||
|
Loading…
Reference in New Issue
Block a user