aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2009-04-20 12:39:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:57:17 -0400
commitb9a5f8cab751d362f7c2d94899ca788c22fcd1ef (patch)
treee769e2f59ef845cf7c7cc93b64d33eeed49bb9f7
parent9e52b0623c6eb49c3f23a326c1fb97bdecc49ba1 (diff)
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>
-rw-r--r--include/linux/nl80211.h24
-rw-r--r--include/net/cfg80211.h50
-rw-r--r--net/mac80211/cfg.c27
-rw-r--r--net/mac80211/debugfs.c8
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/tx.c9
-rw-r--r--net/mac80211/util.c2
-rw-r--r--net/mac80211/wext.c138
-rw-r--r--net/wireless/core.c10
-rw-r--r--net/wireless/nl80211.c95
-rw-r--r--net/wireless/wext-compat.c151
12 files changed, 372 insertions, 151 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 25ce3e42bd10..dc9d9ec5d1ae 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -46,8 +46,10 @@
46 * to get a list of all present wiphys. 46 * to get a list of all present wiphys.
47 * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or 47 * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or
48 * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, 48 * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME,
49 * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, and/or 49 * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ,
50 * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. 50 * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT,
51 * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
52 * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD.
51 * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request 53 * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request
52 * or rename notification. Has attributes %NL80211_ATTR_WIPHY and 54 * or rename notification. Has attributes %NL80211_ATTR_WIPHY and
53 * %NL80211_ATTR_WIPHY_NAME. 55 * %NL80211_ATTR_WIPHY_NAME.
@@ -337,6 +339,18 @@ enum nl80211_commands {
337 * NL80211_CHAN_HT20 = HT20 only 339 * NL80211_CHAN_HT20 = HT20 only
338 * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel 340 * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel
339 * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel 341 * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel
342 * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is
343 * less than or equal to the RTS threshold; allowed range: 1..255;
344 * dot11ShortRetryLimit; u8
345 * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is
346 * greater than the RTS threshold; allowed range: 1..255;
347 * dot11ShortLongLimit; u8
348 * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum
349 * length in octets for frames; allowed range: 256..8000, disable
350 * fragmentation with (u32)-1; dot11FragmentationThreshold; u32
351 * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length
352 * larger than or equal to this use RTS/CTS handshake); allowed range:
353 * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32
340 * 354 *
341 * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on 355 * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on
342 * @NL80211_ATTR_IFNAME: network interface name 356 * @NL80211_ATTR_IFNAME: network interface name
@@ -565,6 +579,12 @@ enum nl80211_attrs {
565 579
566 NL80211_ATTR_FREQ_FIXED, 580 NL80211_ATTR_FREQ_FIXED,
567 581
582
583 NL80211_ATTR_WIPHY_RETRY_SHORT,
584 NL80211_ATTR_WIPHY_RETRY_LONG,
585 NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
586 NL80211_ATTR_WIPHY_RTS_THRESHOLD,
587
568 /* add attributes here, update the policy in nl80211.c */ 588 /* add attributes here, update the policy in nl80211.c */
569 589
570 __NL80211_ATTR_AFTER_LAST, 590 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 601eac64b02d..54bc69c83691 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -744,6 +744,20 @@ struct cfg80211_ibss_params {
744}; 744};
745 745
746/** 746/**
747 * enum wiphy_params_flags - set_wiphy_params bitfield values
748 * WIPHY_PARAM_RETRY_SHORT: wiphy->retry_short has changed
749 * WIPHY_PARAM_RETRY_LONG: wiphy->retry_long has changed
750 * WIPHY_PARAM_FRAG_THRESHOLD: wiphy->frag_threshold has changed
751 * WIPHY_PARAM_RTS_THRESHOLD: wiphy->rts_threshold has changed
752 */
753enum wiphy_params_flags {
754 WIPHY_PARAM_RETRY_SHORT = 1 << 0,
755 WIPHY_PARAM_RETRY_LONG = 1 << 1,
756 WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2,
757 WIPHY_PARAM_RTS_THRESHOLD = 1 << 3,
758};
759
760/**
747 * struct cfg80211_ops - backend description for wireless configuration 761 * struct cfg80211_ops - backend description for wireless configuration
748 * 762 *
749 * This struct is registered by fullmac card drivers and/or wireless stacks 763 * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -823,6 +837,11 @@ struct cfg80211_ibss_params {
823 * cfg80211_ibss_joined(), also call that function when changing BSSID due 837 * cfg80211_ibss_joined(), also call that function when changing BSSID due
824 * to a merge. 838 * to a merge.
825 * @leave_ibss: Leave the IBSS. 839 * @leave_ibss: Leave the IBSS.
840 *
841 * @set_wiphy_params: Notify that wiphy parameters have changed;
842 * @changed bitfield (see &enum wiphy_params_flags) describes which values
843 * have changed. The actual parameter values are available in
844 * struct wiphy. If returning an error, no value should be changed.
826 */ 845 */
827struct cfg80211_ops { 846struct cfg80211_ops {
828 int (*suspend)(struct wiphy *wiphy); 847 int (*suspend)(struct wiphy *wiphy);
@@ -912,6 +931,8 @@ struct cfg80211_ops {
912 int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev, 931 int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
913 struct cfg80211_ibss_params *params); 932 struct cfg80211_ibss_params *params);
914 int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev); 933 int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
934
935 int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
915}; 936};
916 937
917/* 938/*
@@ -945,6 +966,11 @@ struct cfg80211_ops {
945 * @signal_type: signal type reported in &struct cfg80211_bss. 966 * @signal_type: signal type reported in &struct cfg80211_bss.
946 * @cipher_suites: supported cipher suites 967 * @cipher_suites: supported cipher suites
947 * @n_cipher_suites: number of supported cipher suites 968 * @n_cipher_suites: number of supported cipher suites
969 * @retry_short: Retry limit for short frames (dot11ShortRetryLimit)
970 * @retry_long: Retry limit for long frames (dot11LongRetryLimit)
971 * @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
972 * -1 = fragmentation disabled, only odd values >= 256 used
973 * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
948 */ 974 */
949struct wiphy { 975struct wiphy {
950 /* assign these fields before you register the wiphy */ 976 /* assign these fields before you register the wiphy */
@@ -967,6 +993,11 @@ struct wiphy {
967 int n_cipher_suites; 993 int n_cipher_suites;
968 const u32 *cipher_suites; 994 const u32 *cipher_suites;
969 995
996 u8 retry_short;
997 u8 retry_long;
998 u32 frag_threshold;
999 u32 rts_threshold;
1000
970 /* If multiple wiphys are registered and you're handed e.g. 1001 /* If multiple wiphys are registered and you're handed e.g.
971 * a regular netdev with assigned ieee80211_ptr, you won't 1002 * a regular netdev with assigned ieee80211_ptr, you won't
972 * know whether it points to a wiphy your driver has registered 1003 * know whether it points to a wiphy your driver has registered
@@ -1345,6 +1376,25 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev,
1345struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 1376struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
1346 struct iw_freq *freq); 1377 struct iw_freq *freq);
1347 1378
1379int cfg80211_wext_siwrts(struct net_device *dev,
1380 struct iw_request_info *info,
1381 struct iw_param *rts, char *extra);
1382int cfg80211_wext_giwrts(struct net_device *dev,
1383 struct iw_request_info *info,
1384 struct iw_param *rts, char *extra);
1385int cfg80211_wext_siwfrag(struct net_device *dev,
1386 struct iw_request_info *info,
1387 struct iw_param *frag, char *extra);
1388int cfg80211_wext_giwfrag(struct net_device *dev,
1389 struct iw_request_info *info,
1390 struct iw_param *frag, char *extra);
1391int cfg80211_wext_siwretry(struct net_device *dev,
1392 struct iw_request_info *info,
1393 struct iw_param *retry, char *extra);
1394int cfg80211_wext_giwretry(struct net_device *dev,
1395 struct iw_request_info *info,
1396 struct iw_param *retry, char *extra);
1397
1348/* 1398/*
1349 * callbacks for asynchronous cfg80211 methods, notification 1399 * callbacks for asynchronous cfg80211 methods, notification
1350 * functions and BSS handling helpers 1400 * functions and BSS handling helpers
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 14013dc64474..5e1c230744b5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1298,6 +1298,32 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1298 return ieee80211_ibss_leave(sdata); 1298 return ieee80211_ibss_leave(sdata);
1299} 1299}
1300 1300
1301static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1302{
1303 struct ieee80211_local *local = wiphy_priv(wiphy);
1304
1305 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1306 int err;
1307
1308 if (local->ops->set_rts_threshold) {
1309 err = local->ops->set_rts_threshold(
1310 local_to_hw(local), wiphy->rts_threshold);
1311 if (err)
1312 return err;
1313 }
1314 }
1315
1316 if (changed & WIPHY_PARAM_RETRY_SHORT)
1317 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
1318 if (changed & WIPHY_PARAM_RETRY_LONG)
1319 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
1320 if (changed &
1321 (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
1322 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
1323
1324 return 0;
1325}
1326
1301struct cfg80211_ops mac80211_config_ops = { 1327struct cfg80211_ops mac80211_config_ops = {
1302 .add_virtual_intf = ieee80211_add_iface, 1328 .add_virtual_intf = ieee80211_add_iface,
1303 .del_virtual_intf = ieee80211_del_iface, 1329 .del_virtual_intf = ieee80211_del_iface,
@@ -1336,4 +1362,5 @@ struct cfg80211_ops mac80211_config_ops = {
1336 .disassoc = ieee80211_disassoc, 1362 .disassoc = ieee80211_disassoc,
1337 .join_ibss = ieee80211_join_ibss, 1363 .join_ibss = ieee80211_join_ibss,
1338 .leave_ibss = ieee80211_leave_ibss, 1364 .leave_ibss = ieee80211_leave_ibss,
1365 .set_wiphy_params = ieee80211_set_wiphy_params,
1339}; 1366};
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 210b9b6fecd2..5001328be46b 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -52,13 +52,13 @@ static const struct file_operations name## _ops = { \
52DEBUGFS_READONLY_FILE(frequency, 20, "%d", 52DEBUGFS_READONLY_FILE(frequency, 20, "%d",
53 local->hw.conf.channel->center_freq); 53 local->hw.conf.channel->center_freq);
54DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", 54DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
55 local->rts_threshold); 55 local->hw.wiphy->rts_threshold);
56DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", 56DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
57 local->fragmentation_threshold); 57 local->hw.wiphy->frag_threshold);
58DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", 58DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
59 local->hw.conf.short_frame_max_tx_count); 59 local->hw.wiphy->retry_short);
60DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", 60DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
61 local->hw.conf.long_frame_max_tx_count); 61 local->hw.wiphy->retry_long);
62DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", 62DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
63 local->total_ps_buffered); 63 local->total_ps_buffered);
64DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", 64DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 92a573bf1035..dba78d89a10c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -643,9 +643,6 @@ struct ieee80211_local {
643 643
644 struct rate_control_ref *rate_ctrl; 644 struct rate_control_ref *rate_ctrl;
645 645
646 int rts_threshold;
647 int fragmentation_threshold;
648
649 struct crypto_blkcipher *wep_tx_tfm; 646 struct crypto_blkcipher *wep_tx_tfm;
650 struct crypto_blkcipher *wep_rx_tfm; 647 struct crypto_blkcipher *wep_rx_tfm;
651 u32 wep_iv; 648 u32 wep_iv;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index d26fc399285e..5320e08434ac 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -776,10 +776,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
776 /* set up some defaults */ 776 /* set up some defaults */
777 local->hw.queues = 1; 777 local->hw.queues = 1;
778 local->hw.max_rates = 1; 778 local->hw.max_rates = 1;
779 local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; 779 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
780 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; 780 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
781 local->hw.conf.long_frame_max_tx_count = 4;
782 local->hw.conf.short_frame_max_tx_count = 7;
783 local->hw.conf.radio_enabled = true; 781 local->hw.conf.radio_enabled = true;
784 782
785 INIT_LIST_HEAD(&local->interfaces); 783 INIT_LIST_HEAD(&local->interfaces);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c53d77db3e4f..9ab49826c15a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -516,7 +516,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
516 sband = tx->local->hw.wiphy->bands[tx->channel->band]; 516 sband = tx->local->hw.wiphy->bands[tx->channel->band];
517 517
518 len = min_t(int, tx->skb->len + FCS_LEN, 518 len = min_t(int, tx->skb->len + FCS_LEN,
519 tx->local->fragmentation_threshold); 519 tx->local->hw.wiphy->frag_threshold);
520 520
521 /* set up the tx rate control struct we give the RC algo */ 521 /* set up the tx rate control struct we give the RC algo */
522 txrc.hw = local_to_hw(tx->local); 522 txrc.hw = local_to_hw(tx->local);
@@ -527,8 +527,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
527 txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; 527 txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
528 528
529 /* set up RTS protection if desired */ 529 /* set up RTS protection if desired */
530 if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && 530 if (len > tx->local->hw.wiphy->rts_threshold) {
531 len > tx->local->rts_threshold) {
532 txrc.rts = rts = true; 531 txrc.rts = rts = true;
533 } 532 }
534 533
@@ -770,7 +769,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
770 struct sk_buff *skb = tx->skb; 769 struct sk_buff *skb = tx->skb;
771 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 770 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
772 struct ieee80211_hdr *hdr = (void *)skb->data; 771 struct ieee80211_hdr *hdr = (void *)skb->data;
773 int frag_threshold = tx->local->fragmentation_threshold; 772 int frag_threshold = tx->local->hw.wiphy->frag_threshold;
774 int hdrlen; 773 int hdrlen;
775 int fragnum; 774 int fragnum;
776 775
@@ -1088,7 +1087,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
1088 1087
1089 if (tx->flags & IEEE80211_TX_FRAGMENTED) { 1088 if (tx->flags & IEEE80211_TX_FRAGMENTED) {
1090 if ((tx->flags & IEEE80211_TX_UNICAST) && 1089 if ((tx->flags & IEEE80211_TX_UNICAST) &&
1091 skb->len + FCS_LEN > local->fragmentation_threshold && 1090 skb->len + FCS_LEN > local->hw.wiphy->frag_threshold &&
1092 !(info->flags & IEEE80211_TX_CTL_AMPDU)) 1091 !(info->flags & IEEE80211_TX_CTL_AMPDU))
1093 tx->flags |= IEEE80211_TX_FRAGMENTED; 1092 tx->flags |= IEEE80211_TX_FRAGMENTED;
1094 else 1093 else
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3dd490fa4b68..11244212f41d 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1044,7 +1044,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1044 1044
1045 /* setup RTS threshold */ 1045 /* setup RTS threshold */
1046 if (local->ops->set_rts_threshold) 1046 if (local->ops->set_rts_threshold)
1047 local->ops->set_rts_threshold(hw, local->rts_threshold); 1047 local->ops->set_rts_threshold(hw, hw->wiphy->rts_threshold);
1048 1048
1049 /* reconfigure hardware */ 1049 /* reconfigure hardware */
1050 ieee80211_hw_config(local, ~0); 1050 ieee80211_hw_config(local, ~0);
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index eb63fc148019..1eb6d8642a77 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -472,132 +472,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
472 return 0; 472 return 0;
473} 473}
474 474
475static int ieee80211_ioctl_siwrts(struct net_device *dev,
476 struct iw_request_info *info,
477 struct iw_param *rts, char *extra)
478{
479 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
480
481 if (rts->disabled)
482 local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
483 else if (!rts->fixed)
484 /* if the rts value is not fixed, then take default */
485 local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
486 else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
487 return -EINVAL;
488 else
489 local->rts_threshold = rts->value;
490
491 /* If the wlan card performs RTS/CTS in hardware/firmware,
492 * configure it here */
493
494 if (local->ops->set_rts_threshold)
495 local->ops->set_rts_threshold(local_to_hw(local),
496 local->rts_threshold);
497
498 return 0;
499}
500
501static int ieee80211_ioctl_giwrts(struct net_device *dev,
502 struct iw_request_info *info,
503 struct iw_param *rts, char *extra)
504{
505 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
506
507 rts->value = local->rts_threshold;
508 rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
509 rts->fixed = 1;
510
511 return 0;
512}
513
514
515static int ieee80211_ioctl_siwfrag(struct net_device *dev,
516 struct iw_request_info *info,
517 struct iw_param *frag, char *extra)
518{
519 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
520
521 if (frag->disabled)
522 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
523 else if (!frag->fixed)
524 local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
525 else if (frag->value < 256 ||
526 frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
527 return -EINVAL;
528 else {
529 /* Fragment length must be even, so strip LSB. */
530 local->fragmentation_threshold = frag->value & ~0x1;
531 }
532
533 return 0;
534}
535
536static int ieee80211_ioctl_giwfrag(struct net_device *dev,
537 struct iw_request_info *info,
538 struct iw_param *frag, char *extra)
539{
540 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
541
542 frag->value = local->fragmentation_threshold;
543 frag->disabled = (frag->value >= IEEE80211_MAX_FRAG_THRESHOLD);
544 frag->fixed = 1;
545
546 return 0;
547}
548
549
550static int ieee80211_ioctl_siwretry(struct net_device *dev,
551 struct iw_request_info *info,
552 struct iw_param *retry, char *extra)
553{
554 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
555
556 if (retry->disabled ||
557 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
558 return -EINVAL;
559
560 if (retry->flags & IW_RETRY_MAX) {
561 local->hw.conf.long_frame_max_tx_count = retry->value;
562 } else if (retry->flags & IW_RETRY_MIN) {
563 local->hw.conf.short_frame_max_tx_count = retry->value;
564 } else {
565 local->hw.conf.long_frame_max_tx_count = retry->value;
566 local->hw.conf.short_frame_max_tx_count = retry->value;
567 }
568
569 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
570
571 return 0;
572}
573
574
575static int ieee80211_ioctl_giwretry(struct net_device *dev,
576 struct iw_request_info *info,
577 struct iw_param *retry, char *extra)
578{
579 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
580
581 retry->disabled = 0;
582 if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
583 /* first return min value, iwconfig will ask max value
584 * later if needed */
585 retry->flags |= IW_RETRY_LIMIT;
586 retry->value = local->hw.conf.short_frame_max_tx_count;
587 if (local->hw.conf.long_frame_max_tx_count !=
588 local->hw.conf.short_frame_max_tx_count)
589 retry->flags |= IW_RETRY_MIN;
590 return 0;
591 }
592 if (retry->flags & IW_RETRY_MAX) {
593 retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
594 retry->value = local->hw.conf.long_frame_max_tx_count;
595 }
596
597 return 0;
598}
599
600
601static int ieee80211_ioctl_siwencode(struct net_device *dev, 475static int ieee80211_ioctl_siwencode(struct net_device *dev,
602 struct iw_request_info *info, 476 struct iw_request_info *info,
603 struct iw_point *erq, char *keybuf) 477 struct iw_point *erq, char *keybuf)
@@ -1050,14 +924,14 @@ static const iw_handler ieee80211_handler[] =
1050 (iw_handler) NULL, /* -- hole -- */ 924 (iw_handler) NULL, /* -- hole -- */
1051 (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */ 925 (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
1052 (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */ 926 (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
1053 (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */ 927 (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
1054 (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */ 928 (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
1055 (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */ 929 (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
1056 (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */ 930 (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
1057 (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */ 931 (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
1058 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */ 932 (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
1059 (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */ 933 (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
1060 (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ 934 (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
1061 (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ 935 (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
1062 (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ 936 (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
1063 (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ 937 (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 827a56263551..f256b4f7e833 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -273,6 +273,16 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
273 drv->wiphy.dev.class = &ieee80211_class; 273 drv->wiphy.dev.class = &ieee80211_class;
274 drv->wiphy.dev.platform_data = drv; 274 drv->wiphy.dev.platform_data = drv;
275 275
276 /*
277 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
278 * Fragmentation and RTS threshold are disabled by default with the
279 * special -1 value.
280 */
281 drv->wiphy.retry_short = 7;
282 drv->wiphy.retry_long = 4;
283 drv->wiphy.frag_threshold = (u32) -1;
284 drv->wiphy.rts_threshold = (u32) -1;
285
276 return &drv->wiphy; 286 return &drv->wiphy;
277} 287}
278EXPORT_SYMBOL(wiphy_new); 288EXPORT_SYMBOL(wiphy_new);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 16f86356ac97..5a9a5c6c71db 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -61,6 +61,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, 62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, 63 [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 },
64 [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 },
65 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
66 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
67 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
64 68
65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 69 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 70 [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,
204 208
205 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); 209 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
206 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 210 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
211
212 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
213 dev->wiphy.retry_short);
214 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
215 dev->wiphy.retry_long);
216 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
217 dev->wiphy.frag_threshold);
218 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
219 dev->wiphy.rts_threshold);
220
207 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 221 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
208 dev->wiphy.max_scan_ssids); 222 dev->wiphy.max_scan_ssids);
209 NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, 223 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)
416 struct cfg80211_registered_device *rdev; 430 struct cfg80211_registered_device *rdev;
417 int result = 0, rem_txq_params = 0; 431 int result = 0, rem_txq_params = 0;
418 struct nlattr *nl_txq_params; 432 struct nlattr *nl_txq_params;
433 u32 changed;
434 u8 retry_short = 0, retry_long = 0;
435 u32 frag_threshold = 0, rts_threshold = 0;
419 436
420 rtnl_lock(); 437 rtnl_lock();
421 438
@@ -530,6 +547,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
530 goto bad_res; 547 goto bad_res;
531 } 548 }
532 549
550 changed = 0;
551
552 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
553 retry_short = nla_get_u8(
554 info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
555 if (retry_short == 0) {
556 result = -EINVAL;
557 goto bad_res;
558 }
559 changed |= WIPHY_PARAM_RETRY_SHORT;
560 }
561
562 if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
563 retry_long = nla_get_u8(
564 info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
565 if (retry_long == 0) {
566 result = -EINVAL;
567 goto bad_res;
568 }
569 changed |= WIPHY_PARAM_RETRY_LONG;
570 }
571
572 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
573 frag_threshold = nla_get_u32(
574 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
575 if (frag_threshold < 256) {
576 result = -EINVAL;
577 goto bad_res;
578 }
579 if (frag_threshold != (u32) -1) {
580 /*
581 * Fragments (apart from the last one) are required to
582 * have even length. Make the fragmentation code
583 * simpler by stripping LSB should someone try to use
584 * odd threshold value.
585 */
586 frag_threshold &= ~0x1;
587 }
588 changed |= WIPHY_PARAM_FRAG_THRESHOLD;
589 }
590
591 if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
592 rts_threshold = nla_get_u32(
593 info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
594 changed |= WIPHY_PARAM_RTS_THRESHOLD;
595 }
596
597 if (changed) {
598 u8 old_retry_short, old_retry_long;
599 u32 old_frag_threshold, old_rts_threshold;
600
601 if (!rdev->ops->set_wiphy_params) {
602 result = -EOPNOTSUPP;
603 goto bad_res;
604 }
605
606 old_retry_short = rdev->wiphy.retry_short;
607 old_retry_long = rdev->wiphy.retry_long;
608 old_frag_threshold = rdev->wiphy.frag_threshold;
609 old_rts_threshold = rdev->wiphy.rts_threshold;
610
611 if (changed & WIPHY_PARAM_RETRY_SHORT)
612 rdev->wiphy.retry_short = retry_short;
613 if (changed & WIPHY_PARAM_RETRY_LONG)
614 rdev->wiphy.retry_long = retry_long;
615 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
616 rdev->wiphy.frag_threshold = frag_threshold;
617 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
618 rdev->wiphy.rts_threshold = rts_threshold;
619
620 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
621 if (result) {
622 rdev->wiphy.retry_short = old_retry_short;
623 rdev->wiphy.retry_long = old_retry_long;
624 rdev->wiphy.frag_threshold = old_frag_threshold;
625 rdev->wiphy.rts_threshold = old_rts_threshold;
626 }
627 }
533 628
534 bad_res: 629 bad_res:
535 mutex_unlock(&rdev->mtx); 630 mutex_unlock(&rdev->mtx);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 4e054ea9c0a0..3279e7f038dc 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -314,3 +314,154 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
314 314
315} 315}
316EXPORT_SYMBOL(cfg80211_wext_freq); 316EXPORT_SYMBOL(cfg80211_wext_freq);
317
318int cfg80211_wext_siwrts(struct net_device *dev,
319 struct iw_request_info *info,
320 struct iw_param *rts, char *extra)
321{
322 struct wireless_dev *wdev = dev->ieee80211_ptr;
323 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
324 u32 orts = wdev->wiphy->rts_threshold;
325 int err;
326
327 if (rts->disabled || !rts->fixed)
328 wdev->wiphy->rts_threshold = (u32) -1;
329 else if (rts->value < 0)
330 return -EINVAL;
331 else
332 wdev->wiphy->rts_threshold = rts->value;
333
334 err = rdev->ops->set_wiphy_params(wdev->wiphy,
335 WIPHY_PARAM_RTS_THRESHOLD);
336 if (err)
337 wdev->wiphy->rts_threshold = orts;
338
339 return err;
340}
341EXPORT_SYMBOL(cfg80211_wext_siwrts);
342
343int cfg80211_wext_giwrts(struct net_device *dev,
344 struct iw_request_info *info,
345 struct iw_param *rts, char *extra)
346{
347 struct wireless_dev *wdev = dev->ieee80211_ptr;
348
349 rts->value = wdev->wiphy->rts_threshold;
350 rts->disabled = rts->value == (u32) -1;
351 rts->fixed = 1;
352
353 return 0;
354}
355EXPORT_SYMBOL(cfg80211_wext_giwrts);
356
357int cfg80211_wext_siwfrag(struct net_device *dev,
358 struct iw_request_info *info,
359 struct iw_param *frag, char *extra)
360{
361 struct wireless_dev *wdev = dev->ieee80211_ptr;
362 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
363 u32 ofrag = wdev->wiphy->frag_threshold;
364 int err;
365
366 if (frag->disabled || !frag->fixed)
367 wdev->wiphy->frag_threshold = (u32) -1;
368 else if (frag->value < 256)
369 return -EINVAL;
370 else {
371 /* Fragment length must be even, so strip LSB. */
372 wdev->wiphy->frag_threshold = frag->value & ~0x1;
373 }
374
375 err = rdev->ops->set_wiphy_params(wdev->wiphy,
376 WIPHY_PARAM_FRAG_THRESHOLD);
377 if (err)
378 wdev->wiphy->frag_threshold = ofrag;
379
380 return err;
381}
382EXPORT_SYMBOL(cfg80211_wext_siwfrag);
383
384int cfg80211_wext_giwfrag(struct net_device *dev,
385 struct iw_request_info *info,
386 struct iw_param *frag, char *extra)
387{
388 struct wireless_dev *wdev = dev->ieee80211_ptr;
389
390 frag->value = wdev->wiphy->frag_threshold;
391 frag->disabled = frag->value == (u32) -1;
392 frag->fixed = 1;
393
394 return 0;
395}
396EXPORT_SYMBOL(cfg80211_wext_giwfrag);
397
398int cfg80211_wext_siwretry(struct net_device *dev,
399 struct iw_request_info *info,
400 struct iw_param *retry, char *extra)
401{
402 struct wireless_dev *wdev = dev->ieee80211_ptr;
403 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
404 u32 changed = 0;
405 u8 olong = wdev->wiphy->retry_long;
406 u8 oshort = wdev->wiphy->retry_short;
407 int err;
408
409 if (retry->disabled ||
410 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
411 return -EINVAL;
412
413 if (retry->flags & IW_RETRY_LONG) {
414 wdev->wiphy->retry_long = retry->value;
415 changed |= WIPHY_PARAM_RETRY_LONG;
416 } else if (retry->flags & IW_RETRY_SHORT) {
417 wdev->wiphy->retry_short = retry->value;
418 changed |= WIPHY_PARAM_RETRY_SHORT;
419 } else {
420 wdev->wiphy->retry_short = retry->value;
421 wdev->wiphy->retry_long = retry->value;
422 changed |= WIPHY_PARAM_RETRY_LONG;
423 changed |= WIPHY_PARAM_RETRY_SHORT;
424 }
425
426 if (!changed)
427 return 0;
428
429 err = rdev->ops->set_wiphy_params(wdev->wiphy, changed);
430 if (err) {
431 wdev->wiphy->retry_short = oshort;
432 wdev->wiphy->retry_long = olong;
433 }
434
435 return err;
436}
437EXPORT_SYMBOL(cfg80211_wext_siwretry);
438
439int cfg80211_wext_giwretry(struct net_device *dev,
440 struct iw_request_info *info,
441 struct iw_param *retry, char *extra)
442{
443 struct wireless_dev *wdev = dev->ieee80211_ptr;
444
445 retry->disabled = 0;
446
447 if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) {
448 /*
449 * First return short value, iwconfig will ask long value
450 * later if needed
451 */
452 retry->flags |= IW_RETRY_LIMIT;
453 retry->value = wdev->wiphy->retry_short;
454 if (wdev->wiphy->retry_long != wdev->wiphy->retry_short)
455 retry->flags |= IW_RETRY_LONG;
456
457 return 0;
458 }
459
460 if (retry->flags & IW_RETRY_LONG) {
461 retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
462 retry->value = wdev->wiphy->retry_long;
463 }
464
465 return 0;
466}
467EXPORT_SYMBOL(cfg80211_wext_giwretry);