aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c194
1 files changed, 174 insertions, 20 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 855126a3039d..9d4e4d846ec1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,13 +17,6 @@
17#include "rate.h" 17#include "rate.h"
18#include "mesh.h" 18#include "mesh.h"
19 19
20struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy)
21{
22 struct ieee80211_local *local = wiphy_priv(wiphy);
23 return &local->hw;
24}
25EXPORT_SYMBOL(wiphy_to_hw);
26
27static bool nl80211_type_check(enum nl80211_iftype type) 20static bool nl80211_type_check(enum nl80211_iftype type)
28{ 21{
29 switch (type) { 22 switch (type) {
@@ -33,6 +26,8 @@ static bool nl80211_type_check(enum nl80211_iftype type)
33#ifdef CONFIG_MAC80211_MESH 26#ifdef CONFIG_MAC80211_MESH
34 case NL80211_IFTYPE_MESH_POINT: 27 case NL80211_IFTYPE_MESH_POINT:
35#endif 28#endif
29 case NL80211_IFTYPE_AP:
30 case NL80211_IFTYPE_AP_VLAN:
36 case NL80211_IFTYPE_WDS: 31 case NL80211_IFTYPE_WDS:
37 return true; 32 return true;
38 default: 33 default:
@@ -315,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
315 310
316 sinfo->filled = STATION_INFO_INACTIVE_TIME | 311 sinfo->filled = STATION_INFO_INACTIVE_TIME |
317 STATION_INFO_RX_BYTES | 312 STATION_INFO_RX_BYTES |
318 STATION_INFO_TX_BYTES; 313 STATION_INFO_TX_BYTES |
314 STATION_INFO_TX_BITRATE;
319 315
320 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); 316 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
321 sinfo->rx_bytes = sta->rx_bytes; 317 sinfo->rx_bytes = sta->rx_bytes;
322 sinfo->tx_bytes = sta->tx_bytes; 318 sinfo->tx_bytes = sta->tx_bytes;
323 319
320 if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
321 sinfo->filled |= STATION_INFO_SIGNAL;
322 sinfo->signal = (s8)sta->last_signal;
323 }
324
325 sinfo->txrate.flags = 0;
326 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
327 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
328 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
329 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
330 if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
331 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
332
333 if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
334 struct ieee80211_supported_band *sband;
335 sband = sta->local->hw.wiphy->bands[
336 sta->local->hw.conf.channel->band];
337 sinfo->txrate.legacy =
338 sband->bitrates[sta->last_tx_rate.idx].bitrate;
339 } else
340 sinfo->txrate.mcs = sta->last_tx_rate.idx;
341
324 if (ieee80211_vif_is_mesh(&sdata->vif)) { 342 if (ieee80211_vif_is_mesh(&sdata->vif)) {
325#ifdef CONFIG_MAC80211_MESH 343#ifdef CONFIG_MAC80211_MESH
326 sinfo->filled |= STATION_INFO_LLID | 344 sinfo->filled |= STATION_INFO_LLID |
@@ -401,8 +419,10 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
401 */ 419 */
402 if (params->interval) { 420 if (params->interval) {
403 sdata->local->hw.conf.beacon_int = params->interval; 421 sdata->local->hw.conf.beacon_int = params->interval;
404 if (ieee80211_hw_config(sdata->local)) 422 err = ieee80211_hw_config(sdata->local,
405 return -EINVAL; 423 IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
424 if (err < 0)
425 return err;
406 /* 426 /*
407 * We updated some parameter so if below bails out 427 * We updated some parameter so if below bails out
408 * it's not an error. 428 * it's not an error.
@@ -589,6 +609,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
589 struct ieee80211_supported_band *sband; 609 struct ieee80211_supported_band *sband;
590 struct ieee80211_sub_if_data *sdata = sta->sdata; 610 struct ieee80211_sub_if_data *sdata = sta->sdata;
591 611
612 sband = local->hw.wiphy->bands[local->oper_channel->band];
613
592 /* 614 /*
593 * FIXME: updating the flags is racy when this function is 615 * FIXME: updating the flags is racy when this function is
594 * called from ieee80211_change_station(), this will 616 * called from ieee80211_change_station(), this will
@@ -629,7 +651,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
629 651
630 if (params->supported_rates) { 652 if (params->supported_rates) {
631 rates = 0; 653 rates = 0;
632 sband = local->hw.wiphy->bands[local->oper_channel->band];
633 654
634 for (i = 0; i < params->supported_rates_len; i++) { 655 for (i = 0; i < params->supported_rates_len; i++) {
635 int rate = (params->supported_rates[i] & 0x7f) * 5; 656 int rate = (params->supported_rates[i] & 0x7f) * 5;
@@ -641,10 +662,10 @@ static void sta_apply_parameters(struct ieee80211_local *local,
641 sta->sta.supp_rates[local->oper_channel->band] = rates; 662 sta->sta.supp_rates[local->oper_channel->band] = rates;
642 } 663 }
643 664
644 if (params->ht_capa) { 665 if (params->ht_capa)
645 ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, 666 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
646 &sta->sta.ht_info); 667 params->ht_capa,
647 } 668 &sta->sta.ht_cap);
648 669
649 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { 670 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
650 switch (params->plink_action) { 671 switch (params->plink_action) {
@@ -665,6 +686,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
665 struct sta_info *sta; 686 struct sta_info *sta;
666 struct ieee80211_sub_if_data *sdata; 687 struct ieee80211_sub_if_data *sdata;
667 int err; 688 int err;
689 int layer2_update;
668 690
669 /* Prevent a race with changing the rate control algorithm */ 691 /* Prevent a race with changing the rate control algorithm */
670 if (!netif_running(dev)) 692 if (!netif_running(dev))
@@ -695,17 +717,25 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
695 717
696 rate_control_rate_init(sta); 718 rate_control_rate_init(sta);
697 719
720 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
721 sdata->vif.type == NL80211_IFTYPE_AP;
722
698 rcu_read_lock(); 723 rcu_read_lock();
699 724
700 err = sta_info_insert(sta); 725 err = sta_info_insert(sta);
701 if (err) { 726 if (err) {
702 /* STA has been freed */ 727 /* STA has been freed */
728 if (err == -EEXIST && layer2_update) {
729 /* Need to update layer 2 devices on reassociation */
730 sta = sta_info_get(local, mac);
731 if (sta)
732 ieee80211_send_layer2_update(sta);
733 }
703 rcu_read_unlock(); 734 rcu_read_unlock();
704 return err; 735 return err;
705 } 736 }
706 737
707 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 738 if (layer2_update)
708 sdata->vif.type == NL80211_IFTYPE_AP)
709 ieee80211_send_layer2_update(sta); 739 ieee80211_send_layer2_update(sta);
710 740
711 rcu_read_unlock(); 741 rcu_read_unlock();
@@ -957,6 +987,72 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
957 rcu_read_unlock(); 987 rcu_read_unlock();
958 return 0; 988 return 0;
959} 989}
990
991static int ieee80211_get_mesh_params(struct wiphy *wiphy,
992 struct net_device *dev,
993 struct mesh_config *conf)
994{
995 struct ieee80211_sub_if_data *sdata;
996 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
997
998 if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
999 return -ENOTSUPP;
1000 memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config));
1001 return 0;
1002}
1003
1004static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
1005{
1006 return (mask >> (parm-1)) & 0x1;
1007}
1008
1009static int ieee80211_set_mesh_params(struct wiphy *wiphy,
1010 struct net_device *dev,
1011 const struct mesh_config *nconf, u32 mask)
1012{
1013 struct mesh_config *conf;
1014 struct ieee80211_sub_if_data *sdata;
1015 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1016
1017 if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
1018 return -ENOTSUPP;
1019
1020 /* Set the config options which we are interested in setting */
1021 conf = &(sdata->u.mesh.mshcfg);
1022 if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask))
1023 conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout;
1024 if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask))
1025 conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout;
1026 if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask))
1027 conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout;
1028 if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask))
1029 conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks;
1030 if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask))
1031 conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
1032 if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
1033 conf->dot11MeshTTL = nconf->dot11MeshTTL;
1034 if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
1035 conf->auto_open_plinks = nconf->auto_open_plinks;
1036 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
1037 conf->dot11MeshHWMPmaxPREQretries =
1038 nconf->dot11MeshHWMPmaxPREQretries;
1039 if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
1040 conf->path_refresh_time = nconf->path_refresh_time;
1041 if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
1042 conf->min_discovery_timeout = nconf->min_discovery_timeout;
1043 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
1044 conf->dot11MeshHWMPactivePathTimeout =
1045 nconf->dot11MeshHWMPactivePathTimeout;
1046 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
1047 conf->dot11MeshHWMPpreqMinInterval =
1048 nconf->dot11MeshHWMPpreqMinInterval;
1049 if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
1050 mask))
1051 conf->dot11MeshHWMPnetDiameterTraversalTime =
1052 nconf->dot11MeshHWMPnetDiameterTraversalTime;
1053 return 0;
1054}
1055
960#endif 1056#endif
961 1057
962static int ieee80211_change_bss(struct wiphy *wiphy, 1058static int ieee80211_change_bss(struct wiphy *wiphy,
@@ -972,25 +1068,79 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
972 return -EINVAL; 1068 return -EINVAL;
973 1069
974 if (params->use_cts_prot >= 0) { 1070 if (params->use_cts_prot >= 0) {
975 sdata->bss_conf.use_cts_prot = params->use_cts_prot; 1071 sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
976 changed |= BSS_CHANGED_ERP_CTS_PROT; 1072 changed |= BSS_CHANGED_ERP_CTS_PROT;
977 } 1073 }
978 if (params->use_short_preamble >= 0) { 1074 if (params->use_short_preamble >= 0) {
979 sdata->bss_conf.use_short_preamble = 1075 sdata->vif.bss_conf.use_short_preamble =
980 params->use_short_preamble; 1076 params->use_short_preamble;
981 changed |= BSS_CHANGED_ERP_PREAMBLE; 1077 changed |= BSS_CHANGED_ERP_PREAMBLE;
982 } 1078 }
983 if (params->use_short_slot_time >= 0) { 1079 if (params->use_short_slot_time >= 0) {
984 sdata->bss_conf.use_short_slot = 1080 sdata->vif.bss_conf.use_short_slot =
985 params->use_short_slot_time; 1081 params->use_short_slot_time;
986 changed |= BSS_CHANGED_ERP_SLOT; 1082 changed |= BSS_CHANGED_ERP_SLOT;
987 } 1083 }
988 1084
1085 if (params->basic_rates) {
1086 int i, j;
1087 u32 rates = 0;
1088 struct ieee80211_local *local = wiphy_priv(wiphy);
1089 struct ieee80211_supported_band *sband =
1090 wiphy->bands[local->oper_channel->band];
1091
1092 for (i = 0; i < params->basic_rates_len; i++) {
1093 int rate = (params->basic_rates[i] & 0x7f) * 5;
1094 for (j = 0; j < sband->n_bitrates; j++) {
1095 if (sband->bitrates[j].bitrate == rate)
1096 rates |= BIT(j);
1097 }
1098 }
1099 sdata->vif.bss_conf.basic_rates = rates;
1100 changed |= BSS_CHANGED_BASIC_RATES;
1101 }
1102
989 ieee80211_bss_info_change_notify(sdata, changed); 1103 ieee80211_bss_info_change_notify(sdata, changed);
990 1104
991 return 0; 1105 return 0;
992} 1106}
993 1107
1108static int ieee80211_set_txq_params(struct wiphy *wiphy,
1109 struct ieee80211_txq_params *params)
1110{
1111 struct ieee80211_local *local = wiphy_priv(wiphy);
1112 struct ieee80211_tx_queue_params p;
1113
1114 if (!local->ops->conf_tx)
1115 return -EOPNOTSUPP;
1116
1117 memset(&p, 0, sizeof(p));
1118 p.aifs = params->aifs;
1119 p.cw_max = params->cwmax;
1120 p.cw_min = params->cwmin;
1121 p.txop = params->txop;
1122 if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) {
1123 printk(KERN_DEBUG "%s: failed to set TX queue "
1124 "parameters for queue %d\n", local->mdev->name,
1125 params->queue);
1126 return -EINVAL;
1127 }
1128
1129 return 0;
1130}
1131
1132static int ieee80211_set_channel(struct wiphy *wiphy,
1133 struct ieee80211_channel *chan,
1134 enum nl80211_channel_type channel_type)
1135{
1136 struct ieee80211_local *local = wiphy_priv(wiphy);
1137
1138 local->oper_channel = chan;
1139 local->oper_channel_type = channel_type;
1140
1141 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1142}
1143
994struct cfg80211_ops mac80211_config_ops = { 1144struct cfg80211_ops mac80211_config_ops = {
995 .add_virtual_intf = ieee80211_add_iface, 1145 .add_virtual_intf = ieee80211_add_iface,
996 .del_virtual_intf = ieee80211_del_iface, 1146 .del_virtual_intf = ieee80211_del_iface,
@@ -1013,6 +1163,10 @@ struct cfg80211_ops mac80211_config_ops = {
1013 .change_mpath = ieee80211_change_mpath, 1163 .change_mpath = ieee80211_change_mpath,
1014 .get_mpath = ieee80211_get_mpath, 1164 .get_mpath = ieee80211_get_mpath,
1015 .dump_mpath = ieee80211_dump_mpath, 1165 .dump_mpath = ieee80211_dump_mpath,
1166 .set_mesh_params = ieee80211_set_mesh_params,
1167 .get_mesh_params = ieee80211_get_mesh_params,
1016#endif 1168#endif
1017 .change_bss = ieee80211_change_bss, 1169 .change_bss = ieee80211_change_bss,
1170 .set_txq_params = ieee80211_set_txq_params,
1171 .set_channel = ieee80211_set_channel,
1018}; 1172};