diff options
author | Jouni Malinen <j@w1.fi> | 2009-04-20 12:39:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:57:17 -0400 |
commit | b9a5f8cab751d362f7c2d94899ca788c22fcd1ef (patch) | |
tree | e769e2f59ef845cf7c7cc93b64d33eeed49bb9f7 /net | |
parent | 9e52b0623c6eb49c3f23a326c1fb97bdecc49ba1 (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 27 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 8 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/main.c | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 9 | ||||
-rw-r--r-- | net/mac80211/util.c | 2 | ||||
-rw-r--r-- | net/mac80211/wext.c | 138 | ||||
-rw-r--r-- | net/wireless/core.c | 10 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 95 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 151 |
10 files changed, 300 insertions, 149 deletions
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 | ||
1301 | static 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 | |||
1301 | struct cfg80211_ops mac80211_config_ops = { | 1327 | struct 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 = { \ | |||
52 | DEBUGFS_READONLY_FILE(frequency, 20, "%d", | 52 | DEBUGFS_READONLY_FILE(frequency, 20, "%d", |
53 | local->hw.conf.channel->center_freq); | 53 | local->hw.conf.channel->center_freq); |
54 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", | 54 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", |
55 | local->rts_threshold); | 55 | local->hw.wiphy->rts_threshold); |
56 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", | 56 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", |
57 | local->fragmentation_threshold); | 57 | local->hw.wiphy->frag_threshold); |
58 | DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", | 58 | DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", |
59 | local->hw.conf.short_frame_max_tx_count); | 59 | local->hw.wiphy->retry_short); |
60 | DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", | 60 | DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", |
61 | local->hw.conf.long_frame_max_tx_count); | 61 | local->hw.wiphy->retry_long); |
62 | DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", | 62 | DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", |
63 | local->total_ps_buffered); | 63 | local->total_ps_buffered); |
64 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", | 64 | DEBUGFS_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 | ||
475 | static 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 | |||
501 | static 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 | |||
515 | static 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 | |||
536 | static 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 | |||
550 | static 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 | |||
575 | static 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 | |||
601 | static int ieee80211_ioctl_siwencode(struct net_device *dev, | 475 | static 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 | } |
278 | EXPORT_SYMBOL(wiphy_new); | 288 | EXPORT_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 | } |
316 | EXPORT_SYMBOL(cfg80211_wext_freq); | 316 | EXPORT_SYMBOL(cfg80211_wext_freq); |
317 | |||
318 | int 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 | } | ||
341 | EXPORT_SYMBOL(cfg80211_wext_siwrts); | ||
342 | |||
343 | int 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 | } | ||
355 | EXPORT_SYMBOL(cfg80211_wext_giwrts); | ||
356 | |||
357 | int 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 | } | ||
382 | EXPORT_SYMBOL(cfg80211_wext_siwfrag); | ||
383 | |||
384 | int 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 | } | ||
396 | EXPORT_SYMBOL(cfg80211_wext_giwfrag); | ||
397 | |||
398 | int 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 | } | ||
437 | EXPORT_SYMBOL(cfg80211_wext_siwretry); | ||
438 | |||
439 | int 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 | } | ||
467 | EXPORT_SYMBOL(cfg80211_wext_giwretry); | ||