diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 85ac364f4636..c2a2dcbfdf01 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -353,6 +353,7 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
353 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 353 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
354 | { | 354 | { |
355 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 355 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
356 | struct ieee80211_local *local = sdata->local; | ||
356 | struct timespec uptime; | 357 | struct timespec uptime; |
357 | 358 | ||
358 | sinfo->generation = sdata->local->sta_generation; | 359 | sinfo->generation = sdata->local->sta_generation; |
@@ -388,7 +389,9 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
388 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | 389 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || |
389 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | 390 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { |
390 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | 391 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
391 | sinfo->signal = (s8)sta->last_signal; | 392 | if (!local->ops->get_rssi || |
393 | drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal)) | ||
394 | sinfo->signal = (s8)sta->last_signal; | ||
392 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | 395 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); |
393 | } | 396 | } |
394 | 397 | ||
@@ -517,7 +520,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
517 | * network device. | 520 | * network device. |
518 | */ | 521 | */ |
519 | 522 | ||
520 | rcu_read_lock(); | 523 | mutex_lock(&local->sta_mtx); |
521 | 524 | ||
522 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 525 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
523 | sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); | 526 | sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); |
@@ -546,7 +549,7 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
546 | data[i] = (u8)sinfo.signal_avg; | 549 | data[i] = (u8)sinfo.signal_avg; |
547 | i++; | 550 | i++; |
548 | } else { | 551 | } else { |
549 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 552 | list_for_each_entry(sta, &local->sta_list, list) { |
550 | /* Make sure this station belongs to the proper dev */ | 553 | /* Make sure this station belongs to the proper dev */ |
551 | if (sta->sdata->dev != dev) | 554 | if (sta->sdata->dev != dev) |
552 | continue; | 555 | continue; |
@@ -603,7 +606,7 @@ do_survey: | |||
603 | else | 606 | else |
604 | data[i++] = -1LL; | 607 | data[i++] = -1LL; |
605 | 608 | ||
606 | rcu_read_unlock(); | 609 | mutex_unlock(&local->sta_mtx); |
607 | 610 | ||
608 | if (WARN_ON(i != STA_STATS_LEN)) | 611 | if (WARN_ON(i != STA_STATS_LEN)) |
609 | return; | 612 | return; |
@@ -629,10 +632,11 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
629 | int idx, u8 *mac, struct station_info *sinfo) | 632 | int idx, u8 *mac, struct station_info *sinfo) |
630 | { | 633 | { |
631 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 634 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
635 | struct ieee80211_local *local = sdata->local; | ||
632 | struct sta_info *sta; | 636 | struct sta_info *sta; |
633 | int ret = -ENOENT; | 637 | int ret = -ENOENT; |
634 | 638 | ||
635 | rcu_read_lock(); | 639 | mutex_lock(&local->sta_mtx); |
636 | 640 | ||
637 | sta = sta_info_get_by_idx(sdata, idx); | 641 | sta = sta_info_get_by_idx(sdata, idx); |
638 | if (sta) { | 642 | if (sta) { |
@@ -641,7 +645,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
641 | sta_set_sinfo(sta, sinfo); | 645 | sta_set_sinfo(sta, sinfo); |
642 | } | 646 | } |
643 | 647 | ||
644 | rcu_read_unlock(); | 648 | mutex_unlock(&local->sta_mtx); |
645 | 649 | ||
646 | return ret; | 650 | return ret; |
647 | } | 651 | } |
@@ -658,10 +662,11 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
658 | u8 *mac, struct station_info *sinfo) | 662 | u8 *mac, struct station_info *sinfo) |
659 | { | 663 | { |
660 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 664 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
665 | struct ieee80211_local *local = sdata->local; | ||
661 | struct sta_info *sta; | 666 | struct sta_info *sta; |
662 | int ret = -ENOENT; | 667 | int ret = -ENOENT; |
663 | 668 | ||
664 | rcu_read_lock(); | 669 | mutex_lock(&local->sta_mtx); |
665 | 670 | ||
666 | sta = sta_info_get_bss(sdata, mac); | 671 | sta = sta_info_get_bss(sdata, mac); |
667 | if (sta) { | 672 | if (sta) { |
@@ -669,7 +674,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
669 | sta_set_sinfo(sta, sinfo); | 674 | sta_set_sinfo(sta, sinfo); |
670 | } | 675 | } |
671 | 676 | ||
672 | rcu_read_unlock(); | 677 | mutex_unlock(&local->sta_mtx); |
673 | 678 | ||
674 | return ret; | 679 | return ret; |
675 | } | 680 | } |
@@ -689,7 +694,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
689 | case CHAN_MODE_HOPPING: | 694 | case CHAN_MODE_HOPPING: |
690 | return -EBUSY; | 695 | return -EBUSY; |
691 | case CHAN_MODE_FIXED: | 696 | case CHAN_MODE_FIXED: |
692 | if (local->oper_channel != chan) | 697 | if (local->oper_channel != chan || |
698 | (!sdata && local->_oper_channel_type != channel_type)) | ||
693 | return -EBUSY; | 699 | return -EBUSY; |
694 | if (!sdata && local->_oper_channel_type == channel_type) | 700 | if (!sdata && local->_oper_channel_type == channel_type) |
695 | return 0; | 701 | return 0; |
@@ -1529,7 +1535,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1529 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) | 1535 | if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask)) |
1530 | conf->dot11MeshTTL = nconf->dot11MeshTTL; | 1536 | conf->dot11MeshTTL = nconf->dot11MeshTTL; |
1531 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) | 1537 | if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask)) |
1532 | conf->dot11MeshTTL = nconf->element_ttl; | 1538 | conf->element_ttl = nconf->element_ttl; |
1533 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1539 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) |
1534 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1540 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1535 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) | 1541 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) |
@@ -1564,17 +1570,16 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1564 | * announcements, so require this ifmsh to also be a root node | 1570 | * announcements, so require this ifmsh to also be a root node |
1565 | * */ | 1571 | * */ |
1566 | if (nconf->dot11MeshGateAnnouncementProtocol && | 1572 | if (nconf->dot11MeshGateAnnouncementProtocol && |
1567 | !conf->dot11MeshHWMPRootMode) { | 1573 | !(conf->dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)) { |
1568 | conf->dot11MeshHWMPRootMode = 1; | 1574 | conf->dot11MeshHWMPRootMode = IEEE80211_PROACTIVE_RANN; |
1569 | ieee80211_mesh_root_setup(ifmsh); | 1575 | ieee80211_mesh_root_setup(ifmsh); |
1570 | } | 1576 | } |
1571 | conf->dot11MeshGateAnnouncementProtocol = | 1577 | conf->dot11MeshGateAnnouncementProtocol = |
1572 | nconf->dot11MeshGateAnnouncementProtocol; | 1578 | nconf->dot11MeshGateAnnouncementProtocol; |
1573 | } | 1579 | } |
1574 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { | 1580 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) |
1575 | conf->dot11MeshHWMPRannInterval = | 1581 | conf->dot11MeshHWMPRannInterval = |
1576 | nconf->dot11MeshHWMPRannInterval; | 1582 | nconf->dot11MeshHWMPRannInterval; |
1577 | } | ||
1578 | if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) | 1583 | if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask)) |
1579 | conf->dot11MeshForwarding = nconf->dot11MeshForwarding; | 1584 | conf->dot11MeshForwarding = nconf->dot11MeshForwarding; |
1580 | if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) { | 1585 | if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) { |
@@ -1590,6 +1595,15 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1590 | sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode; | 1595 | sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode; |
1591 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | 1596 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); |
1592 | } | 1597 | } |
1598 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask)) | ||
1599 | conf->dot11MeshHWMPactivePathToRootTimeout = | ||
1600 | nconf->dot11MeshHWMPactivePathToRootTimeout; | ||
1601 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask)) | ||
1602 | conf->dot11MeshHWMProotInterval = | ||
1603 | nconf->dot11MeshHWMProotInterval; | ||
1604 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask)) | ||
1605 | conf->dot11MeshHWMPconfirmationInterval = | ||
1606 | nconf->dot11MeshHWMPconfirmationInterval; | ||
1593 | return 0; | 1607 | return 0; |
1594 | } | 1608 | } |
1595 | 1609 | ||
@@ -2309,6 +2323,21 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2309 | 2323 | ||
2310 | mutex_lock(&local->mtx); | 2324 | mutex_lock(&local->mtx); |
2311 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { | 2325 | list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { |
2326 | struct ieee80211_roc_work *dep, *tmp2; | ||
2327 | |||
2328 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { | ||
2329 | if (!mgmt_tx && (unsigned long)dep != cookie) | ||
2330 | continue; | ||
2331 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) | ||
2332 | continue; | ||
2333 | /* found dependent item -- just remove it */ | ||
2334 | list_del(&dep->list); | ||
2335 | mutex_unlock(&local->mtx); | ||
2336 | |||
2337 | ieee80211_roc_notify_destroy(dep); | ||
2338 | return 0; | ||
2339 | } | ||
2340 | |||
2312 | if (!mgmt_tx && (unsigned long)roc != cookie) | 2341 | if (!mgmt_tx && (unsigned long)roc != cookie) |
2313 | continue; | 2342 | continue; |
2314 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | 2343 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) |
@@ -2323,6 +2352,13 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2323 | return -ENOENT; | 2352 | return -ENOENT; |
2324 | } | 2353 | } |
2325 | 2354 | ||
2355 | /* | ||
2356 | * We found the item to cancel, so do that. Note that it | ||
2357 | * may have dependents, which we also cancel (and send | ||
2358 | * the expired signal for.) Not doing so would be quite | ||
2359 | * tricky here, but we may need to fix it later. | ||
2360 | */ | ||
2361 | |||
2326 | if (local->ops->remain_on_channel) { | 2362 | if (local->ops->remain_on_channel) { |
2327 | if (found->started) { | 2363 | if (found->started) { |
2328 | ret = drv_cancel_remain_on_channel(local); | 2364 | ret = drv_cancel_remain_on_channel(local); |
@@ -2334,8 +2370,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2334 | 2370 | ||
2335 | list_del(&found->list); | 2371 | list_del(&found->list); |
2336 | 2372 | ||
2337 | ieee80211_run_deferred_scan(local); | 2373 | if (found->started) |
2338 | ieee80211_start_next_roc(local); | 2374 | ieee80211_start_next_roc(local); |
2339 | mutex_unlock(&local->mtx); | 2375 | mutex_unlock(&local->mtx); |
2340 | 2376 | ||
2341 | ieee80211_roc_notify_destroy(found); | 2377 | ieee80211_roc_notify_destroy(found); |
@@ -2489,16 +2525,30 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | |||
2489 | u16 frame_type, bool reg) | 2525 | u16 frame_type, bool reg) |
2490 | { | 2526 | { |
2491 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2527 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2528 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2492 | 2529 | ||
2493 | if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) | 2530 | switch (frame_type) { |
2494 | return; | 2531 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH: |
2532 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
2533 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
2495 | 2534 | ||
2496 | if (reg) | 2535 | if (reg) |
2497 | local->probe_req_reg++; | 2536 | ifibss->auth_frame_registrations++; |
2498 | else | 2537 | else |
2499 | local->probe_req_reg--; | 2538 | ifibss->auth_frame_registrations--; |
2539 | } | ||
2540 | break; | ||
2541 | case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ: | ||
2542 | if (reg) | ||
2543 | local->probe_req_reg++; | ||
2544 | else | ||
2545 | local->probe_req_reg--; | ||
2500 | 2546 | ||
2501 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 2547 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); |
2548 | break; | ||
2549 | default: | ||
2550 | break; | ||
2551 | } | ||
2502 | } | 2552 | } |
2503 | 2553 | ||
2504 | static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) | 2554 | static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) |
@@ -2724,9 +2774,8 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2724 | !sdata->u.mgd.associated) | 2774 | !sdata->u.mgd.associated) |
2725 | return -EINVAL; | 2775 | return -EINVAL; |
2726 | 2776 | ||
2727 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2777 | tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", |
2728 | pr_debug("TDLS mgmt action %d peer %pM\n", action_code, peer); | 2778 | action_code, peer); |
2729 | #endif | ||
2730 | 2779 | ||
2731 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 2780 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
2732 | max(sizeof(struct ieee80211_mgmt), | 2781 | max(sizeof(struct ieee80211_mgmt), |
@@ -2835,9 +2884,7 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
2835 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2884 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2836 | return -EINVAL; | 2885 | return -EINVAL; |
2837 | 2886 | ||
2838 | #ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG | 2887 | tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); |
2839 | pr_debug("TDLS oper %d peer %pM\n", oper, peer); | ||
2840 | #endif | ||
2841 | 2888 | ||
2842 | switch (oper) { | 2889 | switch (oper) { |
2843 | case NL80211_TDLS_ENABLE_LINK: | 2890 | case NL80211_TDLS_ENABLE_LINK: |