diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 235 |
1 files changed, 157 insertions, 78 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a6893602f87a..1a89c80e6407 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -175,7 +175,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
175 | * add it to the device after the station. | 175 | * add it to the device after the station. |
176 | */ | 176 | */ |
177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { | 177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { |
178 | ieee80211_key_free(sdata->local, key); | 178 | ieee80211_key_free_unused(key); |
179 | err = -ENOENT; | 179 | err = -ENOENT; |
180 | goto out_unlock; | 180 | goto out_unlock; |
181 | } | 181 | } |
@@ -214,8 +214,6 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
214 | } | 214 | } |
215 | 215 | ||
216 | err = ieee80211_key_link(key, sdata, sta); | 216 | err = ieee80211_key_link(key, sdata, sta); |
217 | if (err) | ||
218 | ieee80211_key_free(sdata->local, key); | ||
219 | 217 | ||
220 | out_unlock: | 218 | out_unlock: |
221 | mutex_unlock(&sdata->local->sta_mtx); | 219 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -254,7 +252,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
254 | goto out_unlock; | 252 | goto out_unlock; |
255 | } | 253 | } |
256 | 254 | ||
257 | __ieee80211_key_free(key); | 255 | ieee80211_key_free(key, true); |
258 | 256 | ||
259 | ret = 0; | 257 | ret = 0; |
260 | out_unlock: | 258 | out_unlock: |
@@ -445,12 +443,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
445 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 443 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
446 | struct ieee80211_local *local = sdata->local; | 444 | struct ieee80211_local *local = sdata->local; |
447 | struct timespec uptime; | 445 | struct timespec uptime; |
446 | u64 packets = 0; | ||
447 | int ac; | ||
448 | 448 | ||
449 | sinfo->generation = sdata->local->sta_generation; | 449 | sinfo->generation = sdata->local->sta_generation; |
450 | 450 | ||
451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 451 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
452 | STATION_INFO_RX_BYTES | | 452 | STATION_INFO_RX_BYTES64 | |
453 | STATION_INFO_TX_BYTES | | 453 | STATION_INFO_TX_BYTES64 | |
454 | STATION_INFO_RX_PACKETS | | 454 | STATION_INFO_RX_PACKETS | |
455 | STATION_INFO_TX_PACKETS | | 455 | STATION_INFO_TX_PACKETS | |
456 | STATION_INFO_TX_RETRIES | | 456 | STATION_INFO_TX_RETRIES | |
@@ -467,10 +467,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | 467 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
468 | 468 | ||
469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 469 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
470 | sinfo->tx_bytes = 0; | ||
471 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
472 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
473 | packets += sta->tx_packets[ac]; | ||
474 | } | ||
475 | sinfo->tx_packets = packets; | ||
470 | sinfo->rx_bytes = sta->rx_bytes; | 476 | sinfo->rx_bytes = sta->rx_bytes; |
471 | sinfo->tx_bytes = sta->tx_bytes; | ||
472 | sinfo->rx_packets = sta->rx_packets; | 477 | sinfo->rx_packets = sta->rx_packets; |
473 | sinfo->tx_packets = sta->tx_packets; | ||
474 | sinfo->tx_retries = sta->tx_retry_count; | 478 | sinfo->tx_retries = sta->tx_retry_count; |
475 | sinfo->tx_failed = sta->tx_retry_failed; | 479 | sinfo->tx_failed = sta->tx_retry_failed; |
476 | sinfo->rx_dropped_misc = sta->rx_dropped; | 480 | sinfo->rx_dropped_misc = sta->rx_dropped; |
@@ -598,8 +602,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
598 | data[i++] += sta->rx_fragments; \ | 602 | data[i++] += sta->rx_fragments; \ |
599 | data[i++] += sta->rx_dropped; \ | 603 | data[i++] += sta->rx_dropped; \ |
600 | \ | 604 | \ |
601 | data[i++] += sta->tx_packets; \ | 605 | data[i++] += sinfo.tx_packets; \ |
602 | data[i++] += sta->tx_bytes; \ | 606 | data[i++] += sinfo.tx_bytes; \ |
603 | data[i++] += sta->tx_fragments; \ | 607 | data[i++] += sta->tx_fragments; \ |
604 | data[i++] += sta->tx_filtered_count; \ | 608 | data[i++] += sta->tx_filtered_count; \ |
605 | data[i++] += sta->tx_retry_failed; \ | 609 | data[i++] += sta->tx_retry_failed; \ |
@@ -621,13 +625,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
621 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | 625 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) |
622 | goto do_survey; | 626 | goto do_survey; |
623 | 627 | ||
628 | sinfo.filled = 0; | ||
629 | sta_set_sinfo(sta, &sinfo); | ||
630 | |||
624 | i = 0; | 631 | i = 0; |
625 | ADD_STA_STATS(sta); | 632 | ADD_STA_STATS(sta); |
626 | 633 | ||
627 | data[i++] = sta->sta_state; | 634 | data[i++] = sta->sta_state; |
628 | 635 | ||
629 | sinfo.filled = 0; | ||
630 | sta_set_sinfo(sta, &sinfo); | ||
631 | 636 | ||
632 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | 637 | if (sinfo.filled & STATION_INFO_TX_BITRATE) |
633 | data[i] = 100000 * | 638 | data[i] = 100000 * |
@@ -800,8 +805,7 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
800 | IEEE80211_CHANCTX_EXCLUSIVE); | 805 | IEEE80211_CHANCTX_EXCLUSIVE); |
801 | } | 806 | } |
802 | } else if (local->open_count == local->monitors) { | 807 | } else if (local->open_count == local->monitors) { |
803 | local->_oper_channel = chandef->chan; | 808 | local->_oper_chandef = *chandef; |
804 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); | ||
805 | ieee80211_hw_config(local, 0); | 809 | ieee80211_hw_config(local, 0); |
806 | } | 810 | } |
807 | 811 | ||
@@ -960,8 +964,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
960 | sdata->vif.bss_conf.hidden_ssid = | 964 | sdata->vif.bss_conf.hidden_ssid = |
961 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); | 965 | (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); |
962 | 966 | ||
963 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | 967 | memset(&sdata->vif.bss_conf.p2p_noa_attr, 0, |
964 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | 968 | sizeof(sdata->vif.bss_conf.p2p_noa_attr)); |
969 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow = | ||
970 | params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
971 | if (params->p2p_opp_ps) | ||
972 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= | ||
973 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
965 | 974 | ||
966 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); | 975 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); |
967 | if (err < 0) | 976 | if (err < 0) |
@@ -1034,12 +1043,17 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1034 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1043 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
1035 | sta_info_flush_defer(vlan); | 1044 | sta_info_flush_defer(vlan); |
1036 | sta_info_flush_defer(sdata); | 1045 | sta_info_flush_defer(sdata); |
1046 | synchronize_net(); | ||
1037 | rcu_barrier(); | 1047 | rcu_barrier(); |
1038 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1048 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) { |
1039 | sta_info_flush_cleanup(vlan); | 1049 | sta_info_flush_cleanup(vlan); |
1050 | ieee80211_free_keys(vlan); | ||
1051 | } | ||
1040 | sta_info_flush_cleanup(sdata); | 1052 | sta_info_flush_cleanup(sdata); |
1053 | ieee80211_free_keys(sdata); | ||
1041 | 1054 | ||
1042 | sdata->vif.bss_conf.enable_beacon = false; | 1055 | sdata->vif.bss_conf.enable_beacon = false; |
1056 | sdata->vif.bss_conf.ssid_len = 0; | ||
1043 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 1057 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
1044 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1058 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1045 | 1059 | ||
@@ -1177,6 +1191,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1177 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1191 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1178 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | 1192 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1179 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | 1193 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1194 | } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1195 | /* | ||
1196 | * TDLS -- everything follows authorized, but | ||
1197 | * only becoming authorized is possible, not | ||
1198 | * going back | ||
1199 | */ | ||
1200 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1201 | set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1202 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1203 | mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1204 | BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1205 | } | ||
1180 | } | 1206 | } |
1181 | 1207 | ||
1182 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1208 | ret = sta_apply_auth_flags(local, sta, mask, set); |
@@ -1261,7 +1287,8 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1261 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1287 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1262 | #ifdef CONFIG_MAC80211_MESH | 1288 | #ifdef CONFIG_MAC80211_MESH |
1263 | u32 changed = 0; | 1289 | u32 changed = 0; |
1264 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { | 1290 | |
1291 | if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) { | ||
1265 | switch (params->plink_state) { | 1292 | switch (params->plink_state) { |
1266 | case NL80211_PLINK_ESTAB: | 1293 | case NL80211_PLINK_ESTAB: |
1267 | if (sta->plink_state != NL80211_PLINK_ESTAB) | 1294 | if (sta->plink_state != NL80211_PLINK_ESTAB) |
@@ -1292,15 +1319,18 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1292 | /* nothing */ | 1319 | /* nothing */ |
1293 | break; | 1320 | break; |
1294 | } | 1321 | } |
1295 | } else { | 1322 | } |
1296 | switch (params->plink_action) { | 1323 | |
1297 | case PLINK_ACTION_OPEN: | 1324 | switch (params->plink_action) { |
1298 | changed |= mesh_plink_open(sta); | 1325 | case NL80211_PLINK_ACTION_NO_ACTION: |
1299 | break; | 1326 | /* nothing */ |
1300 | case PLINK_ACTION_BLOCK: | 1327 | break; |
1301 | changed |= mesh_plink_block(sta); | 1328 | case NL80211_PLINK_ACTION_OPEN: |
1302 | break; | 1329 | changed |= mesh_plink_open(sta); |
1303 | } | 1330 | break; |
1331 | case NL80211_PLINK_ACTION_BLOCK: | ||
1332 | changed |= mesh_plink_block(sta); | ||
1333 | break; | ||
1304 | } | 1334 | } |
1305 | 1335 | ||
1306 | if (params->local_pm) | 1336 | if (params->local_pm) |
@@ -1346,8 +1376,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1346 | * defaults -- if userspace wants something else we'll | 1376 | * defaults -- if userspace wants something else we'll |
1347 | * change it accordingly in sta_apply_parameters() | 1377 | * change it accordingly in sta_apply_parameters() |
1348 | */ | 1378 | */ |
1349 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1379 | if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) { |
1350 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1380 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1381 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | ||
1382 | } | ||
1351 | 1383 | ||
1352 | err = sta_apply_parameters(local, sta, params); | 1384 | err = sta_apply_parameters(local, sta, params); |
1353 | if (err) { | 1385 | if (err) { |
@@ -1356,8 +1388,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1356 | } | 1388 | } |
1357 | 1389 | ||
1358 | /* | 1390 | /* |
1359 | * for TDLS, rate control should be initialized only when supported | 1391 | * for TDLS, rate control should be initialized only when |
1360 | * rates are known. | 1392 | * rates are known and station is marked authorized |
1361 | */ | 1393 | */ |
1362 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 1394 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
1363 | rate_control_rate_init(sta); | 1395 | rate_control_rate_init(sta); |
@@ -1394,50 +1426,67 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1394 | } | 1426 | } |
1395 | 1427 | ||
1396 | static int ieee80211_change_station(struct wiphy *wiphy, | 1428 | static int ieee80211_change_station(struct wiphy *wiphy, |
1397 | struct net_device *dev, | 1429 | struct net_device *dev, u8 *mac, |
1398 | u8 *mac, | ||
1399 | struct station_parameters *params) | 1430 | struct station_parameters *params) |
1400 | { | 1431 | { |
1401 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1432 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1402 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1433 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1403 | struct sta_info *sta; | 1434 | struct sta_info *sta; |
1404 | struct ieee80211_sub_if_data *vlansdata; | 1435 | struct ieee80211_sub_if_data *vlansdata; |
1436 | enum cfg80211_station_type statype; | ||
1405 | int err; | 1437 | int err; |
1406 | 1438 | ||
1407 | mutex_lock(&local->sta_mtx); | 1439 | mutex_lock(&local->sta_mtx); |
1408 | 1440 | ||
1409 | sta = sta_info_get_bss(sdata, mac); | 1441 | sta = sta_info_get_bss(sdata, mac); |
1410 | if (!sta) { | 1442 | if (!sta) { |
1411 | mutex_unlock(&local->sta_mtx); | 1443 | err = -ENOENT; |
1412 | return -ENOENT; | 1444 | goto out_err; |
1413 | } | 1445 | } |
1414 | 1446 | ||
1415 | /* in station mode, some updates are only valid with TDLS */ | 1447 | switch (sdata->vif.type) { |
1416 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1448 | case NL80211_IFTYPE_MESH_POINT: |
1417 | (params->supported_rates || params->ht_capa || params->vht_capa || | 1449 | if (sdata->u.mesh.user_mpm) |
1418 | params->sta_modify_mask || | 1450 | statype = CFG80211_STA_MESH_PEER_USER; |
1419 | (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && | 1451 | else |
1420 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | 1452 | statype = CFG80211_STA_MESH_PEER_KERNEL; |
1421 | mutex_unlock(&local->sta_mtx); | 1453 | break; |
1422 | return -EINVAL; | 1454 | case NL80211_IFTYPE_ADHOC: |
1455 | statype = CFG80211_STA_IBSS; | ||
1456 | break; | ||
1457 | case NL80211_IFTYPE_STATION: | ||
1458 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1459 | statype = CFG80211_STA_AP_STA; | ||
1460 | break; | ||
1461 | } | ||
1462 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1463 | statype = CFG80211_STA_TDLS_PEER_ACTIVE; | ||
1464 | else | ||
1465 | statype = CFG80211_STA_TDLS_PEER_SETUP; | ||
1466 | break; | ||
1467 | case NL80211_IFTYPE_AP: | ||
1468 | case NL80211_IFTYPE_AP_VLAN: | ||
1469 | statype = CFG80211_STA_AP_CLIENT; | ||
1470 | break; | ||
1471 | default: | ||
1472 | err = -EOPNOTSUPP; | ||
1473 | goto out_err; | ||
1423 | } | 1474 | } |
1424 | 1475 | ||
1476 | err = cfg80211_check_station_change(wiphy, params, statype); | ||
1477 | if (err) | ||
1478 | goto out_err; | ||
1479 | |||
1425 | if (params->vlan && params->vlan != sta->sdata->dev) { | 1480 | if (params->vlan && params->vlan != sta->sdata->dev) { |
1426 | bool prev_4addr = false; | 1481 | bool prev_4addr = false; |
1427 | bool new_4addr = false; | 1482 | bool new_4addr = false; |
1428 | 1483 | ||
1429 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 1484 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
1430 | 1485 | ||
1431 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
1432 | vlansdata->vif.type != NL80211_IFTYPE_AP) { | ||
1433 | mutex_unlock(&local->sta_mtx); | ||
1434 | return -EINVAL; | ||
1435 | } | ||
1436 | |||
1437 | if (params->vlan->ieee80211_ptr->use_4addr) { | 1486 | if (params->vlan->ieee80211_ptr->use_4addr) { |
1438 | if (vlansdata->u.vlan.sta) { | 1487 | if (vlansdata->u.vlan.sta) { |
1439 | mutex_unlock(&local->sta_mtx); | 1488 | err = -EBUSY; |
1440 | return -EBUSY; | 1489 | goto out_err; |
1441 | } | 1490 | } |
1442 | 1491 | ||
1443 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 1492 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
@@ -1464,12 +1513,12 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1464 | } | 1513 | } |
1465 | 1514 | ||
1466 | err = sta_apply_parameters(local, sta, params); | 1515 | err = sta_apply_parameters(local, sta, params); |
1467 | if (err) { | 1516 | if (err) |
1468 | mutex_unlock(&local->sta_mtx); | 1517 | goto out_err; |
1469 | return err; | ||
1470 | } | ||
1471 | 1518 | ||
1472 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && params->supported_rates) | 1519 | /* When peer becomes authorized, init rate control as well */ |
1520 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && | ||
1521 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1473 | rate_control_rate_init(sta); | 1522 | rate_control_rate_init(sta); |
1474 | 1523 | ||
1475 | mutex_unlock(&local->sta_mtx); | 1524 | mutex_unlock(&local->sta_mtx); |
@@ -1479,7 +1528,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1479 | ieee80211_recalc_ps(local, -1); | 1528 | ieee80211_recalc_ps(local, -1); |
1480 | ieee80211_recalc_ps_vif(sdata); | 1529 | ieee80211_recalc_ps_vif(sdata); |
1481 | } | 1530 | } |
1531 | |||
1482 | return 0; | 1532 | return 0; |
1533 | out_err: | ||
1534 | mutex_unlock(&local->sta_mtx); | ||
1535 | return err; | ||
1483 | } | 1536 | } |
1484 | 1537 | ||
1485 | #ifdef CONFIG_MAC80211_MESH | 1538 | #ifdef CONFIG_MAC80211_MESH |
@@ -1489,7 +1542,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1489 | struct ieee80211_sub_if_data *sdata; | 1542 | struct ieee80211_sub_if_data *sdata; |
1490 | struct mesh_path *mpath; | 1543 | struct mesh_path *mpath; |
1491 | struct sta_info *sta; | 1544 | struct sta_info *sta; |
1492 | int err; | ||
1493 | 1545 | ||
1494 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1546 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1495 | 1547 | ||
@@ -1500,17 +1552,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1500 | return -ENOENT; | 1552 | return -ENOENT; |
1501 | } | 1553 | } |
1502 | 1554 | ||
1503 | err = mesh_path_add(sdata, dst); | 1555 | mpath = mesh_path_add(sdata, dst); |
1504 | if (err) { | 1556 | if (IS_ERR(mpath)) { |
1505 | rcu_read_unlock(); | 1557 | rcu_read_unlock(); |
1506 | return err; | 1558 | return PTR_ERR(mpath); |
1507 | } | 1559 | } |
1508 | 1560 | ||
1509 | mpath = mesh_path_lookup(sdata, dst); | ||
1510 | if (!mpath) { | ||
1511 | rcu_read_unlock(); | ||
1512 | return -ENXIO; | ||
1513 | } | ||
1514 | mesh_path_fix_nexthop(mpath, sta); | 1561 | mesh_path_fix_nexthop(mpath, sta); |
1515 | 1562 | ||
1516 | rcu_read_unlock(); | 1563 | rcu_read_unlock(); |
@@ -1687,6 +1734,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1687 | ifmsh->mesh_sp_id = setup->sync_method; | 1734 | ifmsh->mesh_sp_id = setup->sync_method; |
1688 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1735 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1689 | ifmsh->mesh_pm_id = setup->path_metric; | 1736 | ifmsh->mesh_pm_id = setup->path_metric; |
1737 | ifmsh->user_mpm = setup->user_mpm; | ||
1690 | ifmsh->security = IEEE80211_MESH_SEC_NONE; | 1738 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1691 | if (setup->is_authenticated) | 1739 | if (setup->is_authenticated) |
1692 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; | 1740 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; |
@@ -1730,8 +1778,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1730 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1778 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1731 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | 1779 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) |
1732 | conf->element_ttl = nconf->element_ttl; | 1780 | conf->element_ttl = nconf->element_ttl; |
1733 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1781 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) { |
1782 | if (ifmsh->user_mpm) | ||
1783 | return -EBUSY; | ||
1734 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1784 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1785 | } | ||
1735 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) | 1786 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) |
1736 | conf->dot11MeshNbrOffsetMaxNeighbor = | 1787 | conf->dot11MeshNbrOffsetMaxNeighbor = |
1737 | nconf->dot11MeshNbrOffsetMaxNeighbor; | 1788 | nconf->dot11MeshNbrOffsetMaxNeighbor; |
@@ -1910,12 +1961,20 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1910 | } | 1961 | } |
1911 | 1962 | ||
1912 | if (params->p2p_ctwindow >= 0) { | 1963 | if (params->p2p_ctwindow >= 0) { |
1913 | sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow; | 1964 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= |
1965 | ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
1966 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= | ||
1967 | params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK; | ||
1914 | changed |= BSS_CHANGED_P2P_PS; | 1968 | changed |= BSS_CHANGED_P2P_PS; |
1915 | } | 1969 | } |
1916 | 1970 | ||
1917 | if (params->p2p_opp_ps >= 0) { | 1971 | if (params->p2p_opp_ps > 0) { |
1918 | sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps; | 1972 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= |
1973 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
1974 | changed |= BSS_CHANGED_P2P_PS; | ||
1975 | } else if (params->p2p_opp_ps == 0) { | ||
1976 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &= | ||
1977 | ~IEEE80211_P2P_OPPPS_ENABLE_BIT; | ||
1919 | changed |= BSS_CHANGED_P2P_PS; | 1978 | changed |= BSS_CHANGED_P2P_PS; |
1920 | } | 1979 | } |
1921 | 1980 | ||
@@ -2359,9 +2418,22 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2359 | } | 2418 | } |
2360 | 2419 | ||
2361 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 2420 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
2421 | struct ieee80211_supported_band *sband = wiphy->bands[i]; | ||
2422 | int j; | ||
2423 | |||
2362 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 2424 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
2363 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, | 2425 | memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].mcs, |
2364 | sizeof(mask->control[i].mcs)); | 2426 | sizeof(mask->control[i].mcs)); |
2427 | |||
2428 | sdata->rc_has_mcs_mask[i] = false; | ||
2429 | if (!sband) | ||
2430 | continue; | ||
2431 | |||
2432 | for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) | ||
2433 | if (~sdata->rc_rateidx_mcs_mask[i][j]) { | ||
2434 | sdata->rc_has_mcs_mask[i] = true; | ||
2435 | break; | ||
2436 | } | ||
2365 | } | 2437 | } |
2366 | 2438 | ||
2367 | return 0; | 2439 | return 0; |
@@ -2371,7 +2443,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2371 | struct ieee80211_sub_if_data *sdata, | 2443 | struct ieee80211_sub_if_data *sdata, |
2372 | struct ieee80211_channel *channel, | 2444 | struct ieee80211_channel *channel, |
2373 | unsigned int duration, u64 *cookie, | 2445 | unsigned int duration, u64 *cookie, |
2374 | struct sk_buff *txskb) | 2446 | struct sk_buff *txskb, |
2447 | enum ieee80211_roc_type type) | ||
2375 | { | 2448 | { |
2376 | struct ieee80211_roc_work *roc, *tmp; | 2449 | struct ieee80211_roc_work *roc, *tmp; |
2377 | bool queued = false; | 2450 | bool queued = false; |
@@ -2390,6 +2463,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2390 | roc->duration = duration; | 2463 | roc->duration = duration; |
2391 | roc->req_duration = duration; | 2464 | roc->req_duration = duration; |
2392 | roc->frame = txskb; | 2465 | roc->frame = txskb; |
2466 | roc->type = type; | ||
2393 | roc->mgmt_tx_cookie = (unsigned long)txskb; | 2467 | roc->mgmt_tx_cookie = (unsigned long)txskb; |
2394 | roc->sdata = sdata; | 2468 | roc->sdata = sdata; |
2395 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); | 2469 | INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); |
@@ -2420,7 +2494,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2420 | if (!duration) | 2494 | if (!duration) |
2421 | duration = 10; | 2495 | duration = 10; |
2422 | 2496 | ||
2423 | ret = drv_remain_on_channel(local, sdata, channel, duration); | 2497 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
2424 | if (ret) { | 2498 | if (ret) { |
2425 | kfree(roc); | 2499 | kfree(roc); |
2426 | return ret; | 2500 | return ret; |
@@ -2439,10 +2513,13 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2439 | * | 2513 | * |
2440 | * If it hasn't started yet, just increase the duration | 2514 | * If it hasn't started yet, just increase the duration |
2441 | * and add the new one to the list of dependents. | 2515 | * and add the new one to the list of dependents. |
2516 | * If the type of the new ROC has higher priority, modify the | ||
2517 | * type of the previous one to match that of the new one. | ||
2442 | */ | 2518 | */ |
2443 | if (!tmp->started) { | 2519 | if (!tmp->started) { |
2444 | list_add_tail(&roc->list, &tmp->dependents); | 2520 | list_add_tail(&roc->list, &tmp->dependents); |
2445 | tmp->duration = max(tmp->duration, roc->duration); | 2521 | tmp->duration = max(tmp->duration, roc->duration); |
2522 | tmp->type = max(tmp->type, roc->type); | ||
2446 | queued = true; | 2523 | queued = true; |
2447 | break; | 2524 | break; |
2448 | } | 2525 | } |
@@ -2454,16 +2531,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2454 | /* | 2531 | /* |
2455 | * In the offloaded ROC case, if it hasn't begun, add | 2532 | * In the offloaded ROC case, if it hasn't begun, add |
2456 | * this new one to the dependent list to be handled | 2533 | * this new one to the dependent list to be handled |
2457 | * when the the master one begins. If it has begun, | 2534 | * when the master one begins. If it has begun, |
2458 | * check that there's still a minimum time left and | 2535 | * check that there's still a minimum time left and |
2459 | * if so, start this one, transmitting the frame, but | 2536 | * if so, start this one, transmitting the frame, but |
2460 | * add it to the list directly after this one with a | 2537 | * add it to the list directly after this one with |
2461 | * a reduced time so we'll ask the driver to execute | 2538 | * a reduced time so we'll ask the driver to execute |
2462 | * it right after finishing the previous one, in the | 2539 | * it right after finishing the previous one, in the |
2463 | * hope that it'll also be executed right afterwards, | 2540 | * hope that it'll also be executed right afterwards, |
2464 | * effectively extending the old one. | 2541 | * effectively extending the old one. |
2465 | * If there's no minimum time left, just add it to the | 2542 | * If there's no minimum time left, just add it to the |
2466 | * normal list. | 2543 | * normal list. |
2544 | * TODO: the ROC type is ignored here, assuming that it | ||
2545 | * is better to immediately use the current ROC. | ||
2467 | */ | 2546 | */ |
2468 | if (!tmp->hw_begun) { | 2547 | if (!tmp->hw_begun) { |
2469 | list_add_tail(&roc->list, &tmp->dependents); | 2548 | list_add_tail(&roc->list, &tmp->dependents); |
@@ -2557,7 +2636,8 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2557 | 2636 | ||
2558 | mutex_lock(&local->mtx); | 2637 | mutex_lock(&local->mtx); |
2559 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2638 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2560 | duration, cookie, NULL); | 2639 | duration, cookie, NULL, |
2640 | IEEE80211_ROC_TYPE_NORMAL); | ||
2561 | mutex_unlock(&local->mtx); | 2641 | mutex_unlock(&local->mtx); |
2562 | 2642 | ||
2563 | return ret; | 2643 | return ret; |
@@ -2792,7 +2872,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2792 | 2872 | ||
2793 | /* This will handle all kinds of coalescing and immediate TX */ | 2873 | /* This will handle all kinds of coalescing and immediate TX */ |
2794 | ret = ieee80211_start_roc_work(local, sdata, chan, | 2874 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2795 | wait, cookie, skb); | 2875 | wait, cookie, skb, |
2876 | IEEE80211_ROC_TYPE_MGMT_TX); | ||
2796 | if (ret) | 2877 | if (ret) |
2797 | kfree_skb(skb); | 2878 | kfree_skb(skb); |
2798 | out_unlock: | 2879 | out_unlock: |
@@ -3302,9 +3383,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3302 | if (local->use_chanctx) | 3383 | if (local->use_chanctx) |
3303 | *chandef = local->monitor_chandef; | 3384 | *chandef = local->monitor_chandef; |
3304 | else | 3385 | else |
3305 | cfg80211_chandef_create(chandef, | 3386 | *chandef = local->_oper_chandef; |
3306 | local->_oper_channel, | ||
3307 | local->_oper_channel_type); | ||
3308 | ret = 0; | 3387 | ret = 0; |
3309 | } | 3388 | } |
3310 | rcu_read_unlock(); | 3389 | rcu_read_unlock(); |