diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 163 |
1 files changed, 116 insertions, 47 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9ae1a4760b58..facf233843e0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
78 | enum nl80211_iftype type, u32 *flags, | 78 | enum nl80211_iftype type, u32 *flags, |
79 | struct vif_params *params) | 79 | struct vif_params *params) |
80 | { | 80 | { |
81 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | if (netif_running(dev)) | 84 | if (ieee80211_sdata_running(sdata)) |
85 | return -EBUSY; | 85 | return -EBUSY; |
86 | 86 | ||
87 | if (!nl80211_params_check(type, params)) | 87 | if (!nl80211_params_check(type, params)) |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | 89 | ||
90 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
91 | |||
92 | ret = ieee80211_if_change_type(sdata, type); | 90 | ret = ieee80211_if_change_type(sdata, type); |
93 | if (ret) | 91 | if (ret) |
94 | return ret; | 92 | return ret; |
@@ -150,7 +148,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
150 | rcu_read_lock(); | 148 | rcu_read_lock(); |
151 | 149 | ||
152 | if (mac_addr) { | 150 | if (mac_addr) { |
153 | sta = sta_info_get(sdata->local, mac_addr); | 151 | sta = sta_info_get_bss(sdata, mac_addr); |
154 | if (!sta) { | 152 | if (!sta) { |
155 | ieee80211_key_free(key); | 153 | ieee80211_key_free(key); |
156 | err = -ENOENT; | 154 | err = -ENOENT; |
@@ -181,7 +179,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
181 | if (mac_addr) { | 179 | if (mac_addr) { |
182 | ret = -ENOENT; | 180 | ret = -ENOENT; |
183 | 181 | ||
184 | sta = sta_info_get(sdata->local, mac_addr); | 182 | sta = sta_info_get_bss(sdata, mac_addr); |
185 | if (!sta) | 183 | if (!sta) |
186 | goto out_unlock; | 184 | goto out_unlock; |
187 | 185 | ||
@@ -228,7 +226,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
228 | rcu_read_lock(); | 226 | rcu_read_lock(); |
229 | 227 | ||
230 | if (mac_addr) { | 228 | if (mac_addr) { |
231 | sta = sta_info_get(sdata->local, mac_addr); | 229 | sta = sta_info_get_bss(sdata, mac_addr); |
232 | if (!sta) | 230 | if (!sta) |
233 | goto out; | 231 | goto out; |
234 | 232 | ||
@@ -415,15 +413,13 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
415 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 413 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
416 | u8 *mac, struct station_info *sinfo) | 414 | u8 *mac, struct station_info *sinfo) |
417 | { | 415 | { |
418 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 416 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
419 | struct sta_info *sta; | 417 | struct sta_info *sta; |
420 | int ret = -ENOENT; | 418 | int ret = -ENOENT; |
421 | 419 | ||
422 | rcu_read_lock(); | 420 | rcu_read_lock(); |
423 | 421 | ||
424 | /* XXX: verify sta->dev == dev */ | 422 | sta = sta_info_get_bss(sdata, mac); |
425 | |||
426 | sta = sta_info_get(local, mac); | ||
427 | if (sta) { | 423 | if (sta) { |
428 | ret = 0; | 424 | ret = 0; |
429 | sta_set_sinfo(sta, sinfo); | 425 | sta_set_sinfo(sta, sinfo); |
@@ -732,7 +728,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
732 | } else | 728 | } else |
733 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 729 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
734 | 730 | ||
735 | if (compare_ether_addr(mac, dev->dev_addr) == 0) | 731 | if (compare_ether_addr(mac, sdata->vif.addr) == 0) |
736 | return -EINVAL; | 732 | return -EINVAL; |
737 | 733 | ||
738 | if (is_multicast_ether_addr(mac)) | 734 | if (is_multicast_ether_addr(mac)) |
@@ -779,8 +775,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
779 | if (mac) { | 775 | if (mac) { |
780 | rcu_read_lock(); | 776 | rcu_read_lock(); |
781 | 777 | ||
782 | /* XXX: get sta belonging to dev */ | 778 | sta = sta_info_get_bss(sdata, mac); |
783 | sta = sta_info_get(local, mac); | ||
784 | if (!sta) { | 779 | if (!sta) { |
785 | rcu_read_unlock(); | 780 | rcu_read_unlock(); |
786 | return -ENOENT; | 781 | return -ENOENT; |
@@ -801,14 +796,14 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
801 | u8 *mac, | 796 | u8 *mac, |
802 | struct station_parameters *params) | 797 | struct station_parameters *params) |
803 | { | 798 | { |
799 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
804 | struct ieee80211_local *local = wiphy_priv(wiphy); | 800 | struct ieee80211_local *local = wiphy_priv(wiphy); |
805 | struct sta_info *sta; | 801 | struct sta_info *sta; |
806 | struct ieee80211_sub_if_data *vlansdata; | 802 | struct ieee80211_sub_if_data *vlansdata; |
807 | 803 | ||
808 | rcu_read_lock(); | 804 | rcu_read_lock(); |
809 | 805 | ||
810 | /* XXX: get sta belonging to dev */ | 806 | sta = sta_info_get_bss(sdata, mac); |
811 | sta = sta_info_get(local, mac); | ||
812 | if (!sta) { | 807 | if (!sta) { |
813 | rcu_read_unlock(); | 808 | rcu_read_unlock(); |
814 | return -ENOENT; | 809 | return -ENOENT; |
@@ -847,7 +842,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
847 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 842 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
848 | u8 *dst, u8 *next_hop) | 843 | u8 *dst, u8 *next_hop) |
849 | { | 844 | { |
850 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
851 | struct ieee80211_sub_if_data *sdata; | 845 | struct ieee80211_sub_if_data *sdata; |
852 | struct mesh_path *mpath; | 846 | struct mesh_path *mpath; |
853 | struct sta_info *sta; | 847 | struct sta_info *sta; |
@@ -856,7 +850,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
856 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 850 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
857 | 851 | ||
858 | rcu_read_lock(); | 852 | rcu_read_lock(); |
859 | sta = sta_info_get(local, next_hop); | 853 | sta = sta_info_get(sdata, next_hop); |
860 | if (!sta) { | 854 | if (!sta) { |
861 | rcu_read_unlock(); | 855 | rcu_read_unlock(); |
862 | return -ENOENT; | 856 | return -ENOENT; |
@@ -895,7 +889,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
895 | struct net_device *dev, | 889 | struct net_device *dev, |
896 | u8 *dst, u8 *next_hop) | 890 | u8 *dst, u8 *next_hop) |
897 | { | 891 | { |
898 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
899 | struct ieee80211_sub_if_data *sdata; | 892 | struct ieee80211_sub_if_data *sdata; |
900 | struct mesh_path *mpath; | 893 | struct mesh_path *mpath; |
901 | struct sta_info *sta; | 894 | struct sta_info *sta; |
@@ -904,7 +897,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
904 | 897 | ||
905 | rcu_read_lock(); | 898 | rcu_read_lock(); |
906 | 899 | ||
907 | sta = sta_info_get(local, next_hop); | 900 | sta = sta_info_get(sdata, next_hop); |
908 | if (!sta) { | 901 | if (!sta) { |
909 | rcu_read_unlock(); | 902 | rcu_read_unlock(); |
910 | return -ENOENT; | 903 | return -ENOENT; |
@@ -1092,6 +1085,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1092 | params->use_short_preamble; | 1085 | params->use_short_preamble; |
1093 | changed |= BSS_CHANGED_ERP_PREAMBLE; | 1086 | changed |= BSS_CHANGED_ERP_PREAMBLE; |
1094 | } | 1087 | } |
1088 | |||
1089 | if (!sdata->vif.bss_conf.use_short_slot && | ||
1090 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | ||
1091 | sdata->vif.bss_conf.use_short_slot = true; | ||
1092 | changed |= BSS_CHANGED_ERP_SLOT; | ||
1093 | } | ||
1094 | |||
1095 | if (params->use_short_slot_time >= 0) { | 1095 | if (params->use_short_slot_time >= 0) { |
1096 | sdata->vif.bss_conf.use_short_slot = | 1096 | sdata->vif.bss_conf.use_short_slot = |
1097 | params->use_short_slot_time; | 1097 | params->use_short_slot_time; |
@@ -1135,6 +1135,13 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1135 | p.cw_max = params->cwmax; | 1135 | p.cw_max = params->cwmax; |
1136 | p.cw_min = params->cwmin; | 1136 | p.cw_min = params->cwmin; |
1137 | p.txop = params->txop; | 1137 | p.txop = params->txop; |
1138 | |||
1139 | /* | ||
1140 | * Setting tx queue params disables u-apsd because it's only | ||
1141 | * called in master mode. | ||
1142 | */ | ||
1143 | p.uapsd = false; | ||
1144 | |||
1138 | if (drv_conf_tx(local, params->queue, &p)) { | 1145 | if (drv_conf_tx(local, params->queue, &p)) { |
1139 | printk(KERN_DEBUG "%s: failed to set TX queue " | 1146 | printk(KERN_DEBUG "%s: failed to set TX queue " |
1140 | "parameters for queue %d\n", | 1147 | "parameters for queue %d\n", |
@@ -1237,6 +1244,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1237 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1244 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1238 | int err; | 1245 | int err; |
1239 | 1246 | ||
1247 | if (changed & WIPHY_PARAM_COVERAGE_CLASS) { | ||
1248 | err = drv_set_coverage_class(local, wiphy->coverage_class); | ||
1249 | |||
1250 | if (err) | ||
1251 | return err; | ||
1252 | } | ||
1253 | |||
1240 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 1254 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
1241 | err = drv_set_rts_threshold(local, wiphy->rts_threshold); | 1255 | err = drv_set_rts_threshold(local, wiphy->rts_threshold); |
1242 | 1256 | ||
@@ -1324,6 +1338,50 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | |||
1324 | } | 1338 | } |
1325 | #endif | 1339 | #endif |
1326 | 1340 | ||
1341 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | ||
1342 | enum ieee80211_smps_mode smps_mode) | ||
1343 | { | ||
1344 | const u8 *ap; | ||
1345 | enum ieee80211_smps_mode old_req; | ||
1346 | int err; | ||
1347 | |||
1348 | old_req = sdata->u.mgd.req_smps; | ||
1349 | sdata->u.mgd.req_smps = smps_mode; | ||
1350 | |||
1351 | if (old_req == smps_mode && | ||
1352 | smps_mode != IEEE80211_SMPS_AUTOMATIC) | ||
1353 | return 0; | ||
1354 | |||
1355 | /* | ||
1356 | * If not associated, or current association is not an HT | ||
1357 | * association, there's no need to send an action frame. | ||
1358 | */ | ||
1359 | if (!sdata->u.mgd.associated || | ||
1360 | sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { | ||
1361 | mutex_lock(&sdata->local->iflist_mtx); | ||
1362 | ieee80211_recalc_smps(sdata->local, sdata); | ||
1363 | mutex_unlock(&sdata->local->iflist_mtx); | ||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1367 | ap = sdata->u.mgd.associated->bssid; | ||
1368 | |||
1369 | if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { | ||
1370 | if (sdata->u.mgd.powersave) | ||
1371 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
1372 | else | ||
1373 | smps_mode = IEEE80211_SMPS_OFF; | ||
1374 | } | ||
1375 | |||
1376 | /* send SM PS frame to AP */ | ||
1377 | err = ieee80211_send_smps_action(sdata, smps_mode, | ||
1378 | ap, ap); | ||
1379 | if (err) | ||
1380 | sdata->u.mgd.req_smps = old_req; | ||
1381 | |||
1382 | return err; | ||
1383 | } | ||
1384 | |||
1327 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | 1385 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, |
1328 | bool enabled, int timeout) | 1386 | bool enabled, int timeout) |
1329 | { | 1387 | { |
@@ -1344,6 +1402,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1344 | sdata->u.mgd.powersave = enabled; | 1402 | sdata->u.mgd.powersave = enabled; |
1345 | conf->dynamic_ps_timeout = timeout; | 1403 | conf->dynamic_ps_timeout = timeout; |
1346 | 1404 | ||
1405 | /* no change, but if automatic follow powersave */ | ||
1406 | mutex_lock(&sdata->u.mgd.mtx); | ||
1407 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); | ||
1408 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1409 | |||
1347 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 1410 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
1348 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 1411 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
1349 | 1412 | ||
@@ -1359,39 +1422,43 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1359 | { | 1422 | { |
1360 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1423 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1361 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1424 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1362 | int i, err = -EINVAL; | 1425 | int i; |
1363 | u32 target_rate; | ||
1364 | struct ieee80211_supported_band *sband; | ||
1365 | 1426 | ||
1366 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1427 | /* |
1428 | * This _could_ be supported by providing a hook for | ||
1429 | * drivers for this function, but at this point it | ||
1430 | * doesn't seem worth bothering. | ||
1431 | */ | ||
1432 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
1433 | return -EOPNOTSUPP; | ||
1367 | 1434 | ||
1368 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
1369 | * target_rate = X, rate->fixed = 1 means only rate X | ||
1370 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | ||
1371 | sdata->max_ratectrl_rateidx = -1; | ||
1372 | sdata->force_unicast_rateidx = -1; | ||
1373 | 1435 | ||
1374 | if (mask->fixed) | 1436 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1375 | target_rate = mask->fixed / 100; | 1437 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
1376 | else if (mask->maxrate) | ||
1377 | target_rate = mask->maxrate / 100; | ||
1378 | else | ||
1379 | return 0; | ||
1380 | 1438 | ||
1381 | for (i=0; i< sband->n_bitrates; i++) { | 1439 | return 0; |
1382 | struct ieee80211_rate *brate = &sband->bitrates[i]; | 1440 | } |
1383 | int this_rate = brate->bitrate; | ||
1384 | 1441 | ||
1385 | if (target_rate == this_rate) { | 1442 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
1386 | sdata->max_ratectrl_rateidx = i; | 1443 | struct net_device *dev, |
1387 | if (mask->fixed) | 1444 | struct ieee80211_channel *chan, |
1388 | sdata->force_unicast_rateidx = i; | 1445 | enum nl80211_channel_type channel_type, |
1389 | err = 0; | 1446 | unsigned int duration, |
1390 | break; | 1447 | u64 *cookie) |
1391 | } | 1448 | { |
1392 | } | 1449 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1393 | 1450 | ||
1394 | return err; | 1451 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, |
1452 | duration, cookie); | ||
1453 | } | ||
1454 | |||
1455 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | ||
1456 | struct net_device *dev, | ||
1457 | u64 cookie) | ||
1458 | { | ||
1459 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1460 | |||
1461 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | ||
1395 | } | 1462 | } |
1396 | 1463 | ||
1397 | struct cfg80211_ops mac80211_config_ops = { | 1464 | struct cfg80211_ops mac80211_config_ops = { |
@@ -1440,4 +1507,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1440 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) | 1507 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
1441 | .set_power_mgmt = ieee80211_set_power_mgmt, | 1508 | .set_power_mgmt = ieee80211_set_power_mgmt, |
1442 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1509 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1510 | .remain_on_channel = ieee80211_remain_on_channel, | ||
1511 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | ||
1443 | }; | 1512 | }; |