diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 248 | ||||
-rw-r--r-- | net/mac80211/chan.c | 152 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 70 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 74 | ||||
-rw-r--r-- | net/mac80211/iface.c | 28 | ||||
-rw-r--r-- | net/mac80211/main.c | 43 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 41 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 10 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 129 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 3 | ||||
-rw-r--r-- | net/mac80211/pm.c | 2 | ||||
-rw-r--r-- | net/mac80211/rate.h | 12 | ||||
-rw-r--r-- | net/mac80211/scan.c | 4 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 12 | ||||
-rw-r--r-- | net/mac80211/tx.c | 183 | ||||
-rw-r--r-- | net/mac80211/util.c | 41 |
16 files changed, 586 insertions, 466 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 70a5d262815f..09c90627fd19 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -372,10 +372,11 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | |||
372 | 372 | ||
373 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) | 373 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) |
374 | { | 374 | { |
375 | enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); | ||
376 | |||
375 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | 377 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { |
376 | struct ieee80211_supported_band *sband; | 378 | struct ieee80211_supported_band *sband; |
377 | sband = sta->local->hw.wiphy->bands[ | 379 | sband = sta->local->hw.wiphy->bands[band]; |
378 | sta->local->oper_channel->band]; | ||
379 | rate->legacy = sband->bitrates[idx].bitrate; | 380 | rate->legacy = sband->bitrates[idx].bitrate; |
380 | } else | 381 | } else |
381 | rate->mcs = idx; | 382 | rate->mcs = idx; |
@@ -532,6 +533,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
532 | u64 *data) | 533 | u64 *data) |
533 | { | 534 | { |
534 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 535 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
536 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
537 | struct ieee80211_channel *channel; | ||
535 | struct sta_info *sta; | 538 | struct sta_info *sta; |
536 | struct ieee80211_local *local = sdata->local; | 539 | struct ieee80211_local *local = sdata->local; |
537 | struct station_info sinfo; | 540 | struct station_info sinfo; |
@@ -607,19 +610,26 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, | |||
607 | do_survey: | 610 | do_survey: |
608 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; | 611 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; |
609 | /* Get survey stats for current channel */ | 612 | /* Get survey stats for current channel */ |
610 | q = 0; | 613 | survey.filled = 0; |
611 | while (true) { | ||
612 | survey.filled = 0; | ||
613 | if (drv_get_survey(local, q, &survey) != 0) { | ||
614 | survey.filled = 0; | ||
615 | break; | ||
616 | } | ||
617 | 614 | ||
618 | if (survey.channel && | 615 | rcu_read_lock(); |
619 | (local->oper_channel->center_freq == | 616 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
620 | survey.channel->center_freq)) | 617 | if (chanctx_conf) |
621 | break; | 618 | channel = chanctx_conf->channel; |
622 | q++; | 619 | else |
620 | channel = NULL; | ||
621 | rcu_read_unlock(); | ||
622 | |||
623 | if (channel) { | ||
624 | q = 0; | ||
625 | do { | ||
626 | survey.filled = 0; | ||
627 | if (drv_get_survey(local, q, &survey) != 0) { | ||
628 | survey.filled = 0; | ||
629 | break; | ||
630 | } | ||
631 | q++; | ||
632 | } while (channel != survey.channel); | ||
623 | } | 633 | } |
624 | 634 | ||
625 | if (survey.filled) | 635 | if (survey.filled) |
@@ -724,47 +734,42 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
724 | return ret; | 734 | return ret; |
725 | } | 735 | } |
726 | 736 | ||
727 | static int ieee80211_set_channel(struct wiphy *wiphy, | 737 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, |
728 | struct net_device *netdev, | 738 | struct ieee80211_channel *chan, |
729 | struct ieee80211_channel *chan, | 739 | enum nl80211_channel_type channel_type) |
730 | enum nl80211_channel_type channel_type) | ||
731 | { | 740 | { |
732 | struct ieee80211_local *local = wiphy_priv(wiphy); | 741 | struct ieee80211_local *local = wiphy_priv(wiphy); |
733 | struct ieee80211_sub_if_data *sdata = NULL; | 742 | struct ieee80211_sub_if_data *sdata; |
734 | 743 | int ret = 0; | |
735 | if (netdev) | ||
736 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
737 | |||
738 | switch (ieee80211_get_channel_mode(local, NULL)) { | ||
739 | case CHAN_MODE_HOPPING: | ||
740 | return -EBUSY; | ||
741 | case CHAN_MODE_FIXED: | ||
742 | if (local->oper_channel != chan || | ||
743 | (!sdata && local->_oper_channel_type != channel_type)) | ||
744 | return -EBUSY; | ||
745 | if (!sdata && local->_oper_channel_type == channel_type) | ||
746 | return 0; | ||
747 | break; | ||
748 | case CHAN_MODE_UNDEFINED: | ||
749 | break; | ||
750 | } | ||
751 | |||
752 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | ||
753 | return -EBUSY; | ||
754 | 744 | ||
755 | local->oper_channel = chan; | 745 | if (local->monitor_channel == chan && |
746 | local->monitor_channel_type == channel_type) | ||
747 | return 0; | ||
756 | 748 | ||
757 | /* auto-detects changes */ | 749 | mutex_lock(&local->iflist_mtx); |
758 | ieee80211_hw_config(local, 0); | 750 | if (local->use_chanctx) { |
751 | sdata = rcu_dereference_protected( | ||
752 | local->monitor_sdata, | ||
753 | lockdep_is_held(&local->iflist_mtx)); | ||
754 | if (sdata) { | ||
755 | ieee80211_vif_release_channel(sdata); | ||
756 | ret = ieee80211_vif_use_channel( | ||
757 | sdata, chan, channel_type, | ||
758 | IEEE80211_CHANCTX_EXCLUSIVE); | ||
759 | } | ||
760 | } else if (local->open_count == local->monitors) { | ||
761 | local->_oper_channel = chan; | ||
762 | local->_oper_channel_type = channel_type; | ||
763 | ieee80211_hw_config(local, 0); | ||
764 | } | ||
759 | 765 | ||
760 | return 0; | 766 | if (ret == 0) { |
761 | } | 767 | local->monitor_channel = chan; |
768 | local->monitor_channel_type = channel_type; | ||
769 | } | ||
770 | mutex_unlock(&local->iflist_mtx); | ||
762 | 771 | ||
763 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | 772 | return ret; |
764 | struct ieee80211_channel *chan, | ||
765 | enum nl80211_channel_type channel_type) | ||
766 | { | ||
767 | return ieee80211_set_channel(wiphy, NULL, chan, channel_type); | ||
768 | } | 773 | } |
769 | 774 | ||
770 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 775 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
@@ -879,8 +884,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
879 | if (old) | 884 | if (old) |
880 | return -EALREADY; | 885 | return -EALREADY; |
881 | 886 | ||
882 | err = ieee80211_set_channel(wiphy, dev, params->channel, | 887 | err = ieee80211_vif_use_channel(sdata, params->channel, |
883 | params->channel_type); | 888 | params->channel_type, |
889 | IEEE80211_CHANCTX_SHARED); | ||
884 | if (err) | 890 | if (err) |
885 | return err; | 891 | return err; |
886 | 892 | ||
@@ -963,6 +969,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
963 | sta_info_flush(sdata->local, sdata); | 969 | sta_info_flush(sdata->local, sdata); |
964 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 970 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
965 | 971 | ||
972 | ieee80211_vif_release_channel(sdata); | ||
973 | |||
966 | return 0; | 974 | return 0; |
967 | } | 975 | } |
968 | 976 | ||
@@ -1019,9 +1027,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1019 | int i, j; | 1027 | int i, j; |
1020 | struct ieee80211_supported_band *sband; | 1028 | struct ieee80211_supported_band *sband; |
1021 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1029 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1030 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
1022 | u32 mask, set; | 1031 | u32 mask, set; |
1023 | 1032 | ||
1024 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 1033 | sband = local->hw.wiphy->bands[band]; |
1025 | 1034 | ||
1026 | mask = params->sta_flags_mask; | 1035 | mask = params->sta_flags_mask; |
1027 | set = params->sta_flags_set; | 1036 | set = params->sta_flags_set; |
@@ -1136,7 +1145,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1136 | rates |= BIT(j); | 1145 | rates |= BIT(j); |
1137 | } | 1146 | } |
1138 | } | 1147 | } |
1139 | sta->sta.supp_rates[local->oper_channel->band] = rates; | 1148 | sta->sta.supp_rates[band] = rates; |
1140 | } | 1149 | } |
1141 | 1150 | ||
1142 | if (params->ht_capa) | 1151 | if (params->ht_capa) |
@@ -1664,8 +1673,9 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1664 | if (err) | 1673 | if (err) |
1665 | return err; | 1674 | return err; |
1666 | 1675 | ||
1667 | err = ieee80211_set_channel(wiphy, dev, setup->channel, | 1676 | err = ieee80211_vif_use_channel(sdata, setup->channel, |
1668 | setup->channel_type); | 1677 | setup->channel_type, |
1678 | IEEE80211_CHANCTX_SHARED); | ||
1669 | if (err) | 1679 | if (err) |
1670 | return err; | 1680 | return err; |
1671 | 1681 | ||
@@ -1679,6 +1689,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) | |||
1679 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1689 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1680 | 1690 | ||
1681 | ieee80211_stop_mesh(sdata); | 1691 | ieee80211_stop_mesh(sdata); |
1692 | ieee80211_vif_release_channel(sdata); | ||
1682 | 1693 | ||
1683 | return 0; | 1694 | return 0; |
1684 | } | 1695 | } |
@@ -1688,10 +1699,14 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1688 | struct net_device *dev, | 1699 | struct net_device *dev, |
1689 | struct bss_parameters *params) | 1700 | struct bss_parameters *params) |
1690 | { | 1701 | { |
1691 | struct ieee80211_sub_if_data *sdata; | 1702 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1703 | enum ieee80211_band band; | ||
1692 | u32 changed = 0; | 1704 | u32 changed = 0; |
1693 | 1705 | ||
1694 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1706 | if (!rtnl_dereference(sdata->u.ap.beacon)) |
1707 | return -ENOENT; | ||
1708 | |||
1709 | band = ieee80211_get_sdata_band(sdata); | ||
1695 | 1710 | ||
1696 | if (params->use_cts_prot >= 0) { | 1711 | if (params->use_cts_prot >= 0) { |
1697 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; | 1712 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
@@ -1704,7 +1719,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1704 | } | 1719 | } |
1705 | 1720 | ||
1706 | if (!sdata->vif.bss_conf.use_short_slot && | 1721 | if (!sdata->vif.bss_conf.use_short_slot && |
1707 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { | 1722 | band == IEEE80211_BAND_5GHZ) { |
1708 | sdata->vif.bss_conf.use_short_slot = true; | 1723 | sdata->vif.bss_conf.use_short_slot = true; |
1709 | changed |= BSS_CHANGED_ERP_SLOT; | 1724 | changed |= BSS_CHANGED_ERP_SLOT; |
1710 | } | 1725 | } |
@@ -1718,9 +1733,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1718 | if (params->basic_rates) { | 1733 | if (params->basic_rates) { |
1719 | int i, j; | 1734 | int i, j; |
1720 | u32 rates = 0; | 1735 | u32 rates = 0; |
1721 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1736 | struct ieee80211_supported_band *sband = wiphy->bands[band]; |
1722 | struct ieee80211_supported_band *sband = | ||
1723 | wiphy->bands[local->oper_channel->band]; | ||
1724 | 1737 | ||
1725 | for (i = 0; i < params->basic_rates_len; i++) { | 1738 | for (i = 0; i < params->basic_rates_len; i++) { |
1726 | int rate = (params->basic_rates[i] & 0x7f) * 5; | 1739 | int rate = (params->basic_rates[i] & 0x7f) * 5; |
@@ -1872,20 +1885,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | |||
1872 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, | 1885 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, |
1873 | struct cfg80211_assoc_request *req) | 1886 | struct cfg80211_assoc_request *req) |
1874 | { | 1887 | { |
1875 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1876 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1877 | |||
1878 | switch (ieee80211_get_channel_mode(local, sdata)) { | ||
1879 | case CHAN_MODE_HOPPING: | ||
1880 | return -EBUSY; | ||
1881 | case CHAN_MODE_FIXED: | ||
1882 | if (local->oper_channel == req->bss->channel) | ||
1883 | break; | ||
1884 | return -EBUSY; | ||
1885 | case CHAN_MODE_UNDEFINED: | ||
1886 | break; | ||
1887 | } | ||
1888 | |||
1889 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); | 1888 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); |
1890 | } | 1889 | } |
1891 | 1890 | ||
@@ -1904,30 +1903,12 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | |||
1904 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | 1903 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, |
1905 | struct cfg80211_ibss_params *params) | 1904 | struct cfg80211_ibss_params *params) |
1906 | { | 1905 | { |
1907 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1906 | return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params); |
1908 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1909 | |||
1910 | switch (ieee80211_get_channel_mode(local, sdata)) { | ||
1911 | case CHAN_MODE_HOPPING: | ||
1912 | return -EBUSY; | ||
1913 | case CHAN_MODE_FIXED: | ||
1914 | if (!params->channel_fixed) | ||
1915 | return -EBUSY; | ||
1916 | if (local->oper_channel == params->channel) | ||
1917 | break; | ||
1918 | return -EBUSY; | ||
1919 | case CHAN_MODE_UNDEFINED: | ||
1920 | break; | ||
1921 | } | ||
1922 | |||
1923 | return ieee80211_ibss_join(sdata, params); | ||
1924 | } | 1907 | } |
1925 | 1908 | ||
1926 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | 1909 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) |
1927 | { | 1910 | { |
1928 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1911 | return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); |
1929 | |||
1930 | return ieee80211_ibss_leave(sdata); | ||
1931 | } | 1912 | } |
1932 | 1913 | ||
1933 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 1914 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
@@ -1971,9 +1952,13 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, | |||
1971 | enum nl80211_tx_power_setting type, int mbm) | 1952 | enum nl80211_tx_power_setting type, int mbm) |
1972 | { | 1953 | { |
1973 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1954 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1974 | struct ieee80211_channel *chan = local->oper_channel; | 1955 | struct ieee80211_channel *chan = local->_oper_channel; |
1975 | u32 changes = 0; | 1956 | u32 changes = 0; |
1976 | 1957 | ||
1958 | /* FIXME */ | ||
1959 | if (local->use_chanctx) | ||
1960 | return -EOPNOTSUPP; | ||
1961 | |||
1977 | switch (type) { | 1962 | switch (type) { |
1978 | case NL80211_TX_POWER_AUTOMATIC: | 1963 | case NL80211_TX_POWER_AUTOMATIC: |
1979 | local->user_power_level = -1; | 1964 | local->user_power_level = -1; |
@@ -2518,10 +2503,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2518 | 2503 | ||
2519 | /* Check if the operating channel is the requested channel */ | 2504 | /* Check if the operating channel is the requested channel */ |
2520 | if (!need_offchan) { | 2505 | if (!need_offchan) { |
2521 | need_offchan = chan != local->oper_channel; | 2506 | struct ieee80211_chanctx_conf *chanctx_conf; |
2522 | if (channel_type_valid && | 2507 | |
2523 | channel_type != local->_oper_channel_type) | 2508 | rcu_read_lock(); |
2509 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2510 | |||
2511 | if (chanctx_conf) { | ||
2512 | need_offchan = chan != chanctx_conf->channel; | ||
2513 | if (channel_type_valid && | ||
2514 | channel_type != chanctx_conf->channel_type) | ||
2515 | need_offchan = true; | ||
2516 | } else { | ||
2524 | need_offchan = true; | 2517 | need_offchan = true; |
2518 | } | ||
2519 | rcu_read_unlock(); | ||
2525 | } | 2520 | } |
2526 | 2521 | ||
2527 | if (need_offchan && !offchan) { | 2522 | if (need_offchan && !offchan) { |
@@ -2670,7 +2665,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | |||
2670 | u16 capab; | 2665 | u16 capab; |
2671 | 2666 | ||
2672 | capab = 0; | 2667 | capab = 0; |
2673 | if (local->oper_channel->band != IEEE80211_BAND_2GHZ) | 2668 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) |
2674 | return capab; | 2669 | return capab; |
2675 | 2670 | ||
2676 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | 2671 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) |
@@ -2702,7 +2697,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2702 | u16 status_code, struct sk_buff *skb) | 2697 | u16 status_code, struct sk_buff *skb) |
2703 | { | 2698 | { |
2704 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2699 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2705 | struct ieee80211_local *local = sdata->local; | 2700 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
2706 | struct ieee80211_tdls_data *tf; | 2701 | struct ieee80211_tdls_data *tf; |
2707 | 2702 | ||
2708 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2703 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2722,10 +2717,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2722 | tf->u.setup_req.capability = | 2717 | tf->u.setup_req.capability = |
2723 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2718 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2724 | 2719 | ||
2725 | ieee80211_add_srates_ie(sdata, skb, false, | 2720 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2726 | local->oper_channel->band); | 2721 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2727 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2728 | local->oper_channel->band); | ||
2729 | ieee80211_tdls_add_ext_capab(skb); | 2722 | ieee80211_tdls_add_ext_capab(skb); |
2730 | break; | 2723 | break; |
2731 | case WLAN_TDLS_SETUP_RESPONSE: | 2724 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2738,10 +2731,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2738 | tf->u.setup_resp.capability = | 2731 | tf->u.setup_resp.capability = |
2739 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2732 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2740 | 2733 | ||
2741 | ieee80211_add_srates_ie(sdata, skb, false, | 2734 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2742 | local->oper_channel->band); | 2735 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2743 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2744 | local->oper_channel->band); | ||
2745 | ieee80211_tdls_add_ext_capab(skb); | 2736 | ieee80211_tdls_add_ext_capab(skb); |
2746 | break; | 2737 | break; |
2747 | case WLAN_TDLS_SETUP_CONFIRM: | 2738 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2779,7 +2770,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2779 | u16 status_code, struct sk_buff *skb) | 2770 | u16 status_code, struct sk_buff *skb) |
2780 | { | 2771 | { |
2781 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2772 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2782 | struct ieee80211_local *local = sdata->local; | 2773 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
2783 | struct ieee80211_mgmt *mgmt; | 2774 | struct ieee80211_mgmt *mgmt; |
2784 | 2775 | ||
2785 | mgmt = (void *)skb_put(skb, 24); | 2776 | mgmt = (void *)skb_put(skb, 24); |
@@ -2802,10 +2793,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2802 | mgmt->u.action.u.tdls_discover_resp.capability = | 2793 | mgmt->u.action.u.tdls_discover_resp.capability = |
2803 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2794 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2804 | 2795 | ||
2805 | ieee80211_add_srates_ie(sdata, skb, false, | 2796 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2806 | local->oper_channel->band); | 2797 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2807 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2808 | local->oper_channel->band); | ||
2809 | ieee80211_tdls_add_ext_capab(skb); | 2798 | ieee80211_tdls_add_ext_capab(skb); |
2810 | break; | 2799 | break; |
2811 | default: | 2800 | default: |
@@ -2985,12 +2974,19 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
2985 | bool qos; | 2974 | bool qos; |
2986 | struct ieee80211_tx_info *info; | 2975 | struct ieee80211_tx_info *info; |
2987 | struct sta_info *sta; | 2976 | struct sta_info *sta; |
2977 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2978 | enum ieee80211_band band; | ||
2988 | 2979 | ||
2989 | rcu_read_lock(); | 2980 | rcu_read_lock(); |
2981 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2982 | if (WARN_ON(!chanctx_conf)) { | ||
2983 | rcu_read_unlock(); | ||
2984 | return -EINVAL; | ||
2985 | } | ||
2986 | band = chanctx_conf->channel->band; | ||
2990 | sta = sta_info_get(sdata, peer); | 2987 | sta = sta_info_get(sdata, peer); |
2991 | if (sta) { | 2988 | if (sta) { |
2992 | qos = test_sta_flag(sta, WLAN_STA_WME); | 2989 | qos = test_sta_flag(sta, WLAN_STA_WME); |
2993 | rcu_read_unlock(); | ||
2994 | } else { | 2990 | } else { |
2995 | rcu_read_unlock(); | 2991 | rcu_read_unlock(); |
2996 | return -ENOLINK; | 2992 | return -ENOLINK; |
@@ -3008,8 +3004,10 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3008 | } | 3004 | } |
3009 | 3005 | ||
3010 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); | 3006 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); |
3011 | if (!skb) | 3007 | if (!skb) { |
3008 | rcu_read_unlock(); | ||
3012 | return -ENOMEM; | 3009 | return -ENOMEM; |
3010 | } | ||
3013 | 3011 | ||
3014 | skb->dev = dev; | 3012 | skb->dev = dev; |
3015 | 3013 | ||
@@ -3034,8 +3032,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3034 | nullfunc->qos_ctrl = cpu_to_le16(7); | 3032 | nullfunc->qos_ctrl = cpu_to_le16(7); |
3035 | 3033 | ||
3036 | local_bh_disable(); | 3034 | local_bh_disable(); |
3037 | ieee80211_xmit(sdata, skb); | 3035 | ieee80211_xmit(sdata, skb, band); |
3038 | local_bh_enable(); | 3036 | local_bh_enable(); |
3037 | rcu_read_unlock(); | ||
3039 | 3038 | ||
3040 | *cookie = (unsigned long) skb; | 3039 | *cookie = (unsigned long) skb; |
3041 | return 0; | 3040 | return 0; |
@@ -3045,10 +3044,19 @@ static struct ieee80211_channel * | |||
3045 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | 3044 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, |
3046 | enum nl80211_channel_type *type) | 3045 | enum nl80211_channel_type *type) |
3047 | { | 3046 | { |
3048 | struct ieee80211_local *local = wiphy_priv(wiphy); | 3047 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3048 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3049 | struct ieee80211_channel *chan = NULL; | ||
3050 | |||
3051 | rcu_read_lock(); | ||
3052 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3053 | if (chanctx_conf) { | ||
3054 | *type = chanctx_conf->channel_type; | ||
3055 | chan = chanctx_conf->channel; | ||
3056 | } | ||
3057 | rcu_read_unlock(); | ||
3049 | 3058 | ||
3050 | *type = local->_oper_channel_type; | 3059 | return chan; |
3051 | return local->oper_channel; | ||
3052 | } | 3060 | } |
3053 | 3061 | ||
3054 | #ifdef CONFIG_PM | 3062 | #ifdef CONFIG_PM |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 1a8dee42e546..41e1aa69f7aa 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -7,106 +7,6 @@ | |||
7 | #include "ieee80211_i.h" | 7 | #include "ieee80211_i.h" |
8 | #include "driver-ops.h" | 8 | #include "driver-ops.h" |
9 | 9 | ||
10 | static enum ieee80211_chan_mode | ||
11 | __ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
12 | struct ieee80211_sub_if_data *ignore) | ||
13 | { | ||
14 | struct ieee80211_sub_if_data *sdata; | ||
15 | |||
16 | lockdep_assert_held(&local->iflist_mtx); | ||
17 | |||
18 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
19 | if (sdata == ignore) | ||
20 | continue; | ||
21 | |||
22 | if (!ieee80211_sdata_running(sdata)) | ||
23 | continue; | ||
24 | |||
25 | switch (sdata->vif.type) { | ||
26 | case NL80211_IFTYPE_MONITOR: | ||
27 | continue; | ||
28 | case NL80211_IFTYPE_STATION: | ||
29 | if (!sdata->u.mgd.associated) | ||
30 | continue; | ||
31 | break; | ||
32 | case NL80211_IFTYPE_ADHOC: | ||
33 | if (!sdata->u.ibss.ssid_len) | ||
34 | continue; | ||
35 | if (!sdata->u.ibss.fixed_channel) | ||
36 | return CHAN_MODE_HOPPING; | ||
37 | break; | ||
38 | case NL80211_IFTYPE_AP_VLAN: | ||
39 | /* will also have _AP interface */ | ||
40 | continue; | ||
41 | case NL80211_IFTYPE_AP: | ||
42 | if (!sdata->u.ap.beacon) | ||
43 | continue; | ||
44 | break; | ||
45 | case NL80211_IFTYPE_MESH_POINT: | ||
46 | if (!sdata->wdev.mesh_id_len) | ||
47 | continue; | ||
48 | break; | ||
49 | default: | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | return CHAN_MODE_FIXED; | ||
54 | } | ||
55 | |||
56 | return CHAN_MODE_UNDEFINED; | ||
57 | } | ||
58 | |||
59 | enum ieee80211_chan_mode | ||
60 | ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
61 | struct ieee80211_sub_if_data *ignore) | ||
62 | { | ||
63 | enum ieee80211_chan_mode mode; | ||
64 | |||
65 | mutex_lock(&local->iflist_mtx); | ||
66 | mode = __ieee80211_get_channel_mode(local, ignore); | ||
67 | mutex_unlock(&local->iflist_mtx); | ||
68 | |||
69 | return mode; | ||
70 | } | ||
71 | |||
72 | static enum nl80211_channel_type | ||
73 | ieee80211_get_superchan(struct ieee80211_local *local, | ||
74 | struct ieee80211_sub_if_data *sdata) | ||
75 | { | ||
76 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; | ||
77 | struct ieee80211_sub_if_data *tmp; | ||
78 | |||
79 | mutex_lock(&local->iflist_mtx); | ||
80 | list_for_each_entry(tmp, &local->interfaces, list) { | ||
81 | if (tmp == sdata) | ||
82 | continue; | ||
83 | |||
84 | if (!ieee80211_sdata_running(tmp)) | ||
85 | continue; | ||
86 | |||
87 | switch (tmp->vif.bss_conf.channel_type) { | ||
88 | case NL80211_CHAN_NO_HT: | ||
89 | case NL80211_CHAN_HT20: | ||
90 | if (superchan > tmp->vif.bss_conf.channel_type) | ||
91 | break; | ||
92 | |||
93 | superchan = tmp->vif.bss_conf.channel_type; | ||
94 | break; | ||
95 | case NL80211_CHAN_HT40PLUS: | ||
96 | WARN_ON(superchan == NL80211_CHAN_HT40MINUS); | ||
97 | superchan = NL80211_CHAN_HT40PLUS; | ||
98 | break; | ||
99 | case NL80211_CHAN_HT40MINUS: | ||
100 | WARN_ON(superchan == NL80211_CHAN_HT40PLUS); | ||
101 | superchan = NL80211_CHAN_HT40MINUS; | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | mutex_unlock(&local->iflist_mtx); | ||
106 | |||
107 | return superchan; | ||
108 | } | ||
109 | |||
110 | static bool | 10 | static bool |
111 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | 11 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, |
112 | enum nl80211_channel_type chantype2, | 12 | enum nl80211_channel_type chantype2, |
@@ -149,26 +49,6 @@ ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | |||
149 | return true; | 49 | return true; |
150 | } | 50 | } |
151 | 51 | ||
152 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
153 | struct ieee80211_sub_if_data *sdata, | ||
154 | enum nl80211_channel_type chantype) | ||
155 | { | ||
156 | enum nl80211_channel_type superchan; | ||
157 | enum nl80211_channel_type compatchan; | ||
158 | |||
159 | superchan = ieee80211_get_superchan(local, sdata); | ||
160 | if (!ieee80211_channel_types_are_compatible(superchan, chantype, | ||
161 | &compatchan)) | ||
162 | return false; | ||
163 | |||
164 | local->_oper_channel_type = compatchan; | ||
165 | |||
166 | if (sdata) | ||
167 | sdata->vif.bss_conf.channel_type = chantype; | ||
168 | |||
169 | return true; | ||
170 | } | ||
171 | |||
172 | static void ieee80211_change_chantype(struct ieee80211_local *local, | 52 | static void ieee80211_change_chantype(struct ieee80211_local *local, |
173 | struct ieee80211_chanctx *ctx, | 53 | struct ieee80211_chanctx *ctx, |
174 | enum nl80211_channel_type chantype) | 54 | enum nl80211_channel_type chantype) |
@@ -178,6 +58,11 @@ static void ieee80211_change_chantype(struct ieee80211_local *local, | |||
178 | 58 | ||
179 | ctx->conf.channel_type = chantype; | 59 | ctx->conf.channel_type = chantype; |
180 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); | 60 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); |
61 | |||
62 | if (!local->use_chanctx) { | ||
63 | local->_oper_channel_type = chantype; | ||
64 | ieee80211_hw_config(local, 0); | ||
65 | } | ||
181 | } | 66 | } |
182 | 67 | ||
183 | static struct ieee80211_chanctx * | 68 | static struct ieee80211_chanctx * |
@@ -235,10 +120,16 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
235 | ctx->conf.channel_type = channel_type; | 120 | ctx->conf.channel_type = channel_type; |
236 | ctx->mode = mode; | 121 | ctx->mode = mode; |
237 | 122 | ||
238 | err = drv_add_chanctx(local, ctx); | 123 | if (!local->use_chanctx) { |
239 | if (err) { | 124 | local->_oper_channel_type = channel_type; |
240 | kfree(ctx); | 125 | local->_oper_channel = channel; |
241 | return ERR_PTR(err); | 126 | ieee80211_hw_config(local, 0); |
127 | } else { | ||
128 | err = drv_add_chanctx(local, ctx); | ||
129 | if (err) { | ||
130 | kfree(ctx); | ||
131 | return ERR_PTR(err); | ||
132 | } | ||
242 | } | 133 | } |
243 | 134 | ||
244 | list_add(&ctx->list, &local->chanctx_list); | 135 | list_add(&ctx->list, &local->chanctx_list); |
@@ -253,7 +144,12 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
253 | 144 | ||
254 | WARN_ON_ONCE(ctx->refcount != 0); | 145 | WARN_ON_ONCE(ctx->refcount != 0); |
255 | 146 | ||
256 | drv_remove_chanctx(local, ctx); | 147 | if (!local->use_chanctx) { |
148 | local->_oper_channel_type = NL80211_CHAN_NO_HT; | ||
149 | ieee80211_hw_config(local, 0); | ||
150 | } else { | ||
151 | drv_remove_chanctx(local, ctx); | ||
152 | } | ||
257 | 153 | ||
258 | list_del(&ctx->list); | 154 | list_del(&ctx->list); |
259 | kfree_rcu(ctx, rcu_head); | 155 | kfree_rcu(ctx, rcu_head); |
@@ -359,6 +255,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
359 | struct ieee80211_chanctx *ctx; | 255 | struct ieee80211_chanctx *ctx; |
360 | int ret; | 256 | int ret; |
361 | 257 | ||
258 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); | ||
259 | |||
362 | mutex_lock(&local->chanctx_mtx); | 260 | mutex_lock(&local->chanctx_mtx); |
363 | __ieee80211_vif_release_channel(sdata); | 261 | __ieee80211_vif_release_channel(sdata); |
364 | 262 | ||
@@ -370,6 +268,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
370 | goto out; | 268 | goto out; |
371 | } | 269 | } |
372 | 270 | ||
271 | sdata->vif.bss_conf.channel_type = channel_type; | ||
272 | |||
373 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); | 273 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); |
374 | if (ret) { | 274 | if (ret) { |
375 | /* if assign fails refcount stays the same */ | 275 | /* if assign fails refcount stays the same */ |
@@ -385,6 +285,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
385 | 285 | ||
386 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | 286 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) |
387 | { | 287 | { |
288 | WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); | ||
289 | |||
388 | mutex_lock(&sdata->local->chanctx_mtx); | 290 | mutex_lock(&sdata->local->chanctx_mtx); |
389 | __ieee80211_vif_release_channel(sdata); | 291 | __ieee80211_vif_release_channel(sdata); |
390 | mutex_unlock(&sdata->local->chanctx_mtx); | 292 | mutex_unlock(&sdata->local->chanctx_mtx); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5f3620f0bc0a..34d9235117d9 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "rate.h" | 26 | #include "rate.h" |
27 | 27 | ||
28 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) | 28 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) |
29 | #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) | ||
30 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) | 29 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) |
31 | 30 | ||
32 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) | 31 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) |
@@ -76,21 +75,22 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
76 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); | 75 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IBSS); |
77 | } | 76 | } |
78 | 77 | ||
79 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | ||
80 | |||
81 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 78 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
82 | 79 | ||
83 | local->oper_channel = chan; | ||
84 | channel_type = ifibss->channel_type; | 80 | channel_type = ifibss->channel_type; |
85 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | 81 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) |
86 | channel_type = NL80211_CHAN_HT20; | 82 | channel_type = NL80211_CHAN_HT20; |
87 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 83 | |
88 | /* can only fail due to HT40+/- mismatch */ | 84 | ieee80211_vif_release_channel(sdata); |
89 | channel_type = NL80211_CHAN_HT20; | 85 | if (ieee80211_vif_use_channel(sdata, chan, channel_type, |
90 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | 86 | ifibss->fixed_channel ? |
91 | NL80211_CHAN_HT20)); | 87 | IEEE80211_CHANCTX_SHARED : |
88 | IEEE80211_CHANCTX_EXCLUSIVE)) { | ||
89 | sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | ||
90 | return; | ||
92 | } | 91 | } |
93 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 92 | |
93 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | ||
94 | 94 | ||
95 | sband = local->hw.wiphy->bands[chan->band]; | 95 | sband = local->hw.wiphy->bands[chan->band]; |
96 | 96 | ||
@@ -294,7 +294,8 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
295 | struct ieee80211_local *local = sdata->local; | 295 | struct ieee80211_local *local = sdata->local; |
296 | struct sta_info *sta; | 296 | struct sta_info *sta; |
297 | int band = local->oper_channel->band; | 297 | struct ieee80211_chanctx_conf *chanctx_conf; |
298 | int band; | ||
298 | 299 | ||
299 | /* | 300 | /* |
300 | * XXX: Consider removing the least recently used entry and | 301 | * XXX: Consider removing the least recently used entry and |
@@ -317,6 +318,13 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
317 | return NULL; | 318 | return NULL; |
318 | } | 319 | } |
319 | 320 | ||
321 | rcu_read_lock(); | ||
322 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
323 | if (WARN_ON_ONCE(!chanctx_conf)) | ||
324 | return NULL; | ||
325 | band = chanctx_conf->channel->band; | ||
326 | rcu_read_unlock(); | ||
327 | |||
320 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | 328 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); |
321 | if (!sta) { | 329 | if (!sta) { |
322 | rcu_read_lock(); | 330 | rcu_read_lock(); |
@@ -517,7 +525,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
517 | goto put_bss; | 525 | goto put_bss; |
518 | 526 | ||
519 | /* different channel */ | 527 | /* different channel */ |
520 | if (cbss->channel != local->oper_channel) | 528 | if (sdata->u.ibss.fixed_channel && |
529 | sdata->u.ibss.channel != cbss->channel) | ||
521 | goto put_bss; | 530 | goto put_bss; |
522 | 531 | ||
523 | /* different SSID */ | 532 | /* different SSID */ |
@@ -592,7 +601,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
592 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 601 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
593 | struct ieee80211_local *local = sdata->local; | 602 | struct ieee80211_local *local = sdata->local; |
594 | struct sta_info *sta; | 603 | struct sta_info *sta; |
595 | int band = local->oper_channel->band; | 604 | struct ieee80211_chanctx_conf *chanctx_conf; |
605 | int band; | ||
596 | 606 | ||
597 | /* | 607 | /* |
598 | * XXX: Consider removing the least recently used entry and | 608 | * XXX: Consider removing the least recently used entry and |
@@ -610,6 +620,15 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
610 | if (!ether_addr_equal(bssid, sdata->u.ibss.bssid)) | 620 | if (!ether_addr_equal(bssid, sdata->u.ibss.bssid)) |
611 | return; | 621 | return; |
612 | 622 | ||
623 | rcu_read_lock(); | ||
624 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
625 | if (WARN_ON_ONCE(!chanctx_conf)) { | ||
626 | rcu_read_unlock(); | ||
627 | return; | ||
628 | } | ||
629 | band = chanctx_conf->channel->band; | ||
630 | rcu_read_unlock(); | ||
631 | |||
613 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 632 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
614 | if (!sta) | 633 | if (!sta) |
615 | return; | 634 | return; |
@@ -784,18 +803,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
784 | int interval = IEEE80211_SCAN_INTERVAL; | 803 | int interval = IEEE80211_SCAN_INTERVAL; |
785 | 804 | ||
786 | if (time_after(jiffies, ifibss->ibss_join_req + | 805 | if (time_after(jiffies, ifibss->ibss_join_req + |
787 | IEEE80211_IBSS_JOIN_TIMEOUT)) { | 806 | IEEE80211_IBSS_JOIN_TIMEOUT)) |
788 | if (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)) { | 807 | ieee80211_sta_create_ibss(sdata); |
789 | ieee80211_sta_create_ibss(sdata); | ||
790 | return; | ||
791 | } | ||
792 | sdata_info(sdata, "IBSS not allowed on %d MHz\n", | ||
793 | local->oper_channel->center_freq); | ||
794 | |||
795 | /* No IBSS found - decrease scan interval and continue | ||
796 | * scanning. */ | ||
797 | interval = IEEE80211_SCAN_INTERVAL_SLOW; | ||
798 | } | ||
799 | 808 | ||
800 | mod_timer(&ifibss->timer, | 809 | mod_timer(&ifibss->timer, |
801 | round_jiffies(jiffies + interval)); | 810 | round_jiffies(jiffies + interval)); |
@@ -1086,17 +1095,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1086 | sdata->u.ibss.channel_type = params->channel_type; | 1095 | sdata->u.ibss.channel_type = params->channel_type; |
1087 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 1096 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
1088 | 1097 | ||
1089 | /* fix ourselves to that channel now already */ | ||
1090 | if (params->channel_fixed) { | ||
1091 | sdata->local->oper_channel = params->channel; | ||
1092 | if (!ieee80211_set_channel_type(sdata->local, sdata, | ||
1093 | params->channel_type)) { | ||
1094 | mutex_unlock(&sdata->u.ibss.mtx); | ||
1095 | kfree_skb(skb); | ||
1096 | return -EINVAL; | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | if (params->ie) { | 1098 | if (params->ie) { |
1101 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, | 1099 | sdata->u.ibss.ie = kmemdup(params->ie, params->ie_len, |
1102 | GFP_KERNEL); | 1100 | GFP_KERNEL); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8fa00adcb8c0..6660118b46b3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -773,6 +773,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
773 | return container_of(p, struct ieee80211_sub_if_data, vif); | 773 | return container_of(p, struct ieee80211_sub_if_data, vif); |
774 | } | 774 | } |
775 | 775 | ||
776 | static inline enum ieee80211_band | ||
777 | ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) | ||
778 | { | ||
779 | enum ieee80211_band band = IEEE80211_BAND_2GHZ; | ||
780 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
781 | |||
782 | rcu_read_lock(); | ||
783 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
784 | if (!WARN_ON(!chanctx_conf)) | ||
785 | band = chanctx_conf->channel->band; | ||
786 | rcu_read_unlock(); | ||
787 | |||
788 | return band; | ||
789 | } | ||
790 | |||
776 | enum sdata_queue_type { | 791 | enum sdata_queue_type { |
777 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 792 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
778 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 793 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
@@ -1006,8 +1021,10 @@ struct ieee80211_local { | |||
1006 | enum mac80211_scan_state next_scan_state; | 1021 | enum mac80211_scan_state next_scan_state; |
1007 | struct delayed_work scan_work; | 1022 | struct delayed_work scan_work; |
1008 | struct ieee80211_sub_if_data __rcu *scan_sdata; | 1023 | struct ieee80211_sub_if_data __rcu *scan_sdata; |
1024 | struct ieee80211_channel *csa_channel; | ||
1025 | /* For backward compatibility only -- do not use */ | ||
1026 | struct ieee80211_channel *_oper_channel; | ||
1009 | enum nl80211_channel_type _oper_channel_type; | 1027 | enum nl80211_channel_type _oper_channel_type; |
1010 | struct ieee80211_channel *oper_channel, *csa_channel; | ||
1011 | 1028 | ||
1012 | /* Temporary remain-on-channel for off-channel operations */ | 1029 | /* Temporary remain-on-channel for off-channel operations */ |
1013 | struct ieee80211_channel *tmp_channel; | 1030 | struct ieee80211_channel *tmp_channel; |
@@ -1121,6 +1138,8 @@ struct ieee80211_local { | |||
1121 | 1138 | ||
1122 | /* virtual monitor interface */ | 1139 | /* virtual monitor interface */ |
1123 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1140 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
1141 | struct ieee80211_channel *monitor_channel; | ||
1142 | enum nl80211_channel_type monitor_channel_type; | ||
1124 | }; | 1143 | }; |
1125 | 1144 | ||
1126 | static inline struct ieee80211_sub_if_data * | 1145 | static inline struct ieee80211_sub_if_data * |
@@ -1423,11 +1442,42 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke | |||
1423 | gfp_t gfp); | 1442 | gfp_t gfp); |
1424 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | 1443 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
1425 | bool bss_notify); | 1444 | bool bss_notify); |
1426 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); | 1445 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
1446 | enum ieee80211_band band); | ||
1447 | |||
1448 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | ||
1449 | struct sk_buff *skb, int tid, | ||
1450 | enum ieee80211_band band); | ||
1451 | |||
1452 | static inline void | ||
1453 | ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, | ||
1454 | struct sk_buff *skb, int tid, | ||
1455 | enum ieee80211_band band) | ||
1456 | { | ||
1457 | rcu_read_lock(); | ||
1458 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, band); | ||
1459 | rcu_read_unlock(); | ||
1460 | } | ||
1427 | 1461 | ||
1428 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | 1462 | static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
1429 | struct sk_buff *skb, int tid); | 1463 | struct sk_buff *skb, int tid) |
1430 | static void inline ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | 1464 | { |
1465 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1466 | |||
1467 | rcu_read_lock(); | ||
1468 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1469 | if (WARN_ON(!chanctx_conf)) { | ||
1470 | rcu_read_unlock(); | ||
1471 | kfree_skb(skb); | ||
1472 | return; | ||
1473 | } | ||
1474 | |||
1475 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, | ||
1476 | chanctx_conf->channel->band); | ||
1477 | rcu_read_unlock(); | ||
1478 | } | ||
1479 | |||
1480 | static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | ||
1431 | struct sk_buff *skb) | 1481 | struct sk_buff *skb) |
1432 | { | 1482 | { |
1433 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ | 1483 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ |
@@ -1494,7 +1544,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1494 | const u8 *ssid, size_t ssid_len, | 1544 | const u8 *ssid, size_t ssid_len, |
1495 | const u8 *ie, size_t ie_len, | 1545 | const u8 *ie, size_t ie_len, |
1496 | u32 ratemask, bool directed, bool no_cck, | 1546 | u32 ratemask, bool directed, bool no_cck, |
1497 | struct ieee80211_channel *channel); | 1547 | struct ieee80211_channel *channel, bool scan); |
1498 | 1548 | ||
1499 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1549 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1500 | const size_t supp_rates_len, | 1550 | const size_t supp_rates_len, |
@@ -1525,18 +1575,6 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1525 | enum ieee80211_band band); | 1575 | enum ieee80211_band band); |
1526 | 1576 | ||
1527 | /* channel management */ | 1577 | /* channel management */ |
1528 | enum ieee80211_chan_mode { | ||
1529 | CHAN_MODE_UNDEFINED, | ||
1530 | CHAN_MODE_HOPPING, | ||
1531 | CHAN_MODE_FIXED, | ||
1532 | }; | ||
1533 | |||
1534 | enum ieee80211_chan_mode | ||
1535 | ieee80211_get_channel_mode(struct ieee80211_local *local, | ||
1536 | struct ieee80211_sub_if_data *ignore); | ||
1537 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
1538 | struct ieee80211_sub_if_data *sdata, | ||
1539 | enum nl80211_channel_type chantype); | ||
1540 | enum nl80211_channel_type | 1578 | enum nl80211_channel_type |
1541 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); | 1579 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); |
1542 | 1580 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6f8a73c64fb3..7cb8382b19e5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -380,6 +380,15 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
380 | goto out_unlock; | 380 | goto out_unlock; |
381 | } | 381 | } |
382 | 382 | ||
383 | ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, | ||
384 | local->monitor_channel_type, | ||
385 | IEEE80211_CHANCTX_EXCLUSIVE); | ||
386 | if (ret) { | ||
387 | drv_remove_interface(local, sdata); | ||
388 | kfree(sdata); | ||
389 | goto out_unlock; | ||
390 | } | ||
391 | |||
383 | rcu_assign_pointer(local->monitor_sdata, sdata); | 392 | rcu_assign_pointer(local->monitor_sdata, sdata); |
384 | out_unlock: | 393 | out_unlock: |
385 | mutex_unlock(&local->iflist_mtx); | 394 | mutex_unlock(&local->iflist_mtx); |
@@ -403,6 +412,8 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
403 | rcu_assign_pointer(local->monitor_sdata, NULL); | 412 | rcu_assign_pointer(local->monitor_sdata, NULL); |
404 | synchronize_net(); | 413 | synchronize_net(); |
405 | 414 | ||
415 | ieee80211_vif_release_channel(sdata); | ||
416 | |||
406 | drv_remove_interface(local, sdata); | 417 | drv_remove_interface(local, sdata); |
407 | 418 | ||
408 | kfree(sdata); | 419 | kfree(sdata); |
@@ -665,7 +676,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
665 | struct sk_buff *skb, *tmp; | 676 | struct sk_buff *skb, *tmp; |
666 | u32 hw_reconf_flags = 0; | 677 | u32 hw_reconf_flags = 0; |
667 | int i; | 678 | int i; |
668 | enum nl80211_channel_type orig_ct; | ||
669 | 679 | ||
670 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 680 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
671 | 681 | ||
@@ -837,14 +847,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
837 | hw_reconf_flags = 0; | 847 | hw_reconf_flags = 0; |
838 | } | 848 | } |
839 | 849 | ||
840 | /* Re-calculate channel-type, in case there are multiple vifs | ||
841 | * on different channel types. | ||
842 | */ | ||
843 | orig_ct = local->_oper_channel_type; | ||
844 | ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT); | ||
845 | |||
846 | /* do after stop to avoid reconfiguring when we stop anyway */ | 850 | /* do after stop to avoid reconfiguring when we stop anyway */ |
847 | if (hw_reconf_flags || (orig_ct != local->_oper_channel_type)) | 851 | if (hw_reconf_flags) |
848 | ieee80211_hw_config(local, hw_reconf_flags); | 852 | ieee80211_hw_config(local, hw_reconf_flags); |
849 | 853 | ||
850 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 854 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
@@ -1282,11 +1286,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1282 | if (type == ieee80211_vif_type_p2p(&sdata->vif)) | 1286 | if (type == ieee80211_vif_type_p2p(&sdata->vif)) |
1283 | return 0; | 1287 | return 0; |
1284 | 1288 | ||
1285 | /* Setting ad-hoc mode on non-IBSS channel is not supported. */ | ||
1286 | if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS && | ||
1287 | type == NL80211_IFTYPE_ADHOC) | ||
1288 | return -EOPNOTSUPP; | ||
1289 | |||
1290 | if (ieee80211_sdata_running(sdata)) { | 1289 | if (ieee80211_sdata_running(sdata)) { |
1291 | ret = ieee80211_runtime_change_iftype(sdata, type); | 1290 | ret = ieee80211_runtime_change_iftype(sdata, type); |
1292 | if (ret) | 1291 | if (ret) |
@@ -1298,9 +1297,6 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1298 | } | 1297 | } |
1299 | 1298 | ||
1300 | /* reset some values that shouldn't be kept across type changes */ | 1299 | /* reset some values that shouldn't be kept across type changes */ |
1301 | sdata->vif.bss_conf.basic_rates = | ||
1302 | ieee80211_mandatory_rates(sdata->local, | ||
1303 | sdata->local->oper_channel->band); | ||
1304 | sdata->drop_unencrypted = 0; | 1300 | sdata->drop_unencrypted = 0; |
1305 | if (type == NL80211_IFTYPE_STATION) | 1301 | if (type == NL80211_IFTYPE_STATION) |
1306 | sdata->u.mgd.use_4addr = false; | 1302 | sdata->u.mgd.use_4addr = false; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0dd1ea241c54..9cb6280aa2f2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -93,23 +93,21 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
93 | ieee80211_configure_filter(local); | 93 | ieee80211_configure_filter(local); |
94 | } | 94 | } |
95 | 95 | ||
96 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 96 | static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) |
97 | { | 97 | { |
98 | struct ieee80211_channel *chan; | 98 | struct ieee80211_channel *chan; |
99 | int ret = 0; | 99 | u32 changed = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | 102 | u32 offchannel_flag; |
103 | 103 | ||
104 | might_sleep(); | ||
105 | |||
106 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 104 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
107 | if (local->scan_channel) { | 105 | if (local->scan_channel) { |
108 | chan = local->scan_channel; | 106 | chan = local->scan_channel; |
109 | /* If scanning on oper channel, use whatever channel-type | 107 | /* If scanning on oper channel, use whatever channel-type |
110 | * is currently in use. | 108 | * is currently in use. |
111 | */ | 109 | */ |
112 | if (chan == local->oper_channel) | 110 | if (chan == local->_oper_channel) |
113 | channel_type = local->_oper_channel_type; | 111 | channel_type = local->_oper_channel_type; |
114 | else | 112 | else |
115 | channel_type = NL80211_CHAN_NO_HT; | 113 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,11 +115,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | chan = local->tmp_channel; | 115 | chan = local->tmp_channel; |
118 | channel_type = local->tmp_channel_type; | 116 | channel_type = local->tmp_channel_type; |
119 | } else { | 117 | } else { |
120 | chan = local->oper_channel; | 118 | chan = local->_oper_channel; |
121 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
122 | } | 120 | } |
123 | 121 | ||
124 | if (chan != local->oper_channel || | 122 | if (chan != local->_oper_channel || |
125 | channel_type != local->_oper_channel_type) | 123 | channel_type != local->_oper_channel_type) |
126 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 124 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
127 | else | 125 | else |
@@ -164,6 +162,21 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
164 | local->hw.conf.power_level = power; | 162 | local->hw.conf.power_level = power; |
165 | } | 163 | } |
166 | 164 | ||
165 | return changed; | ||
166 | } | ||
167 | |||
168 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | ||
169 | { | ||
170 | int ret = 0; | ||
171 | |||
172 | might_sleep(); | ||
173 | |||
174 | if (!local->use_chanctx) | ||
175 | changed |= ieee80211_hw_conf_chan(local); | ||
176 | else | ||
177 | changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL | | ||
178 | IEEE80211_CONF_CHANGE_POWER); | ||
179 | |||
167 | if (changed && local->open_count) { | 180 | if (changed && local->open_count) { |
168 | ret = drv_config(local, changed); | 181 | ret = drv_config(local, changed); |
169 | /* | 182 | /* |
@@ -775,12 +788,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
775 | sband = local->hw.wiphy->bands[band]; | 788 | sband = local->hw.wiphy->bands[band]; |
776 | if (!sband) | 789 | if (!sband) |
777 | continue; | 790 | continue; |
778 | if (!local->oper_channel) { | 791 | if (!local->use_chanctx && !local->_oper_channel) { |
779 | /* init channel we're on */ | 792 | /* init channel we're on */ |
780 | local->hw.conf.channel = | 793 | local->hw.conf.channel = |
781 | local->oper_channel = &sband->channels[0]; | 794 | local->_oper_channel = &sband->channels[0]; |
782 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; | 795 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; |
783 | } | 796 | } |
797 | if (!local->monitor_channel) { | ||
798 | local->monitor_channel = &sband->channels[0]; | ||
799 | local->monitor_channel_type = NL80211_CHAN_NO_HT; | ||
800 | } | ||
784 | channels += sband->n_channels; | 801 | channels += sband->n_channels; |
785 | 802 | ||
786 | if (max_bitrates < sband->n_bitrates) | 803 | if (max_bitrates < sband->n_bitrates) |
@@ -810,19 +827,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
810 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | 827 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); |
811 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); | 828 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); |
812 | 829 | ||
813 | /* | 830 | /* mac80211 doesn't support more than one IBSS interface right now */ |
814 | * mac80211 doesn't support more than 1 channel, and also not more | ||
815 | * than one IBSS interface | ||
816 | */ | ||
817 | for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { | 831 | for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { |
818 | const struct ieee80211_iface_combination *c; | 832 | const struct ieee80211_iface_combination *c; |
819 | int j; | 833 | int j; |
820 | 834 | ||
821 | c = &hw->wiphy->iface_combinations[i]; | 835 | c = &hw->wiphy->iface_combinations[i]; |
822 | 836 | ||
823 | if (c->num_different_channels > 1) | ||
824 | return -EINVAL; | ||
825 | |||
826 | for (j = 0; j < c->n_limits; j++) | 837 | for (j = 0; j < c->n_limits; j++) |
827 | if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && | 838 | if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && |
828 | c->limits[j].max > 1) | 839 | c->limits[j].max > 1) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index ff0296c7bab8..19725e0a051a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -97,7 +97,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
97 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 97 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
98 | goto mismatch; | 98 | goto mismatch; |
99 | 99 | ||
100 | ieee80211_sta_get_rates(local, ie, local->oper_channel->band, | 100 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), |
101 | &basic_rates); | 101 | &basic_rates); |
102 | 102 | ||
103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
@@ -355,12 +355,22 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
355 | { | 355 | { |
356 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
357 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
358 | struct ieee80211_channel *chan = local->oper_channel; | 358 | struct ieee80211_chanctx_conf *chanctx_conf; |
359 | struct ieee80211_channel *chan; | ||
359 | u8 *pos; | 360 | u8 *pos; |
360 | 361 | ||
361 | if (skb_tailroom(skb) < 3) | 362 | if (skb_tailroom(skb) < 3) |
362 | return -ENOMEM; | 363 | return -ENOMEM; |
363 | 364 | ||
365 | rcu_read_lock(); | ||
366 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
367 | if (WARN_ON(!chanctx_conf)) { | ||
368 | rcu_read_unlock(); | ||
369 | return -EINVAL; | ||
370 | } | ||
371 | chan = chanctx_conf->channel; | ||
372 | rcu_read_unlock(); | ||
373 | |||
364 | sband = local->hw.wiphy->bands[chan->band]; | 374 | sband = local->hw.wiphy->bands[chan->band]; |
365 | if (sband->band == IEEE80211_BAND_2GHZ) { | 375 | if (sband->band == IEEE80211_BAND_2GHZ) { |
366 | pos = skb_put(skb, 2 + 1); | 376 | pos = skb_put(skb, 2 + 1); |
@@ -376,10 +386,11 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
376 | struct ieee80211_sub_if_data *sdata) | 386 | struct ieee80211_sub_if_data *sdata) |
377 | { | 387 | { |
378 | struct ieee80211_local *local = sdata->local; | 388 | struct ieee80211_local *local = sdata->local; |
389 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
379 | struct ieee80211_supported_band *sband; | 390 | struct ieee80211_supported_band *sband; |
380 | u8 *pos; | 391 | u8 *pos; |
381 | 392 | ||
382 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 393 | sband = local->hw.wiphy->bands[band]; |
383 | if (!sband->ht_cap.ht_supported || | 394 | if (!sband->ht_cap.ht_supported || |
384 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 395 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
385 | return 0; | 396 | return 0; |
@@ -397,14 +408,26 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
397 | struct ieee80211_sub_if_data *sdata) | 408 | struct ieee80211_sub_if_data *sdata) |
398 | { | 409 | { |
399 | struct ieee80211_local *local = sdata->local; | 410 | struct ieee80211_local *local = sdata->local; |
400 | struct ieee80211_channel *channel = local->oper_channel; | 411 | struct ieee80211_chanctx_conf *chanctx_conf; |
412 | struct ieee80211_channel *channel; | ||
401 | enum nl80211_channel_type channel_type = | 413 | enum nl80211_channel_type channel_type = |
402 | sdata->vif.bss_conf.channel_type; | 414 | sdata->vif.bss_conf.channel_type; |
403 | struct ieee80211_supported_band *sband = | 415 | struct ieee80211_supported_band *sband; |
404 | local->hw.wiphy->bands[channel->band]; | 416 | struct ieee80211_sta_ht_cap *ht_cap; |
405 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; | ||
406 | u8 *pos; | 417 | u8 *pos; |
407 | 418 | ||
419 | rcu_read_lock(); | ||
420 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
421 | if (WARN_ON(!chanctx_conf)) { | ||
422 | rcu_read_unlock(); | ||
423 | return -EINVAL; | ||
424 | } | ||
425 | channel = chanctx_conf->channel; | ||
426 | rcu_read_unlock(); | ||
427 | |||
428 | sband = local->hw.wiphy->bands[channel->band]; | ||
429 | ht_cap = &sband->ht_cap; | ||
430 | |||
408 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) | 431 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) |
409 | return 0; | 432 | return 0; |
410 | 433 | ||
@@ -610,7 +633,7 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
610 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 633 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
611 | sdata->vif.bss_conf.basic_rates = | 634 | sdata->vif.bss_conf.basic_rates = |
612 | ieee80211_mandatory_rates(sdata->local, | 635 | ieee80211_mandatory_rates(sdata->local, |
613 | sdata->local->oper_channel->band); | 636 | ieee80211_get_sdata_band(sdata)); |
614 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 637 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
615 | BSS_CHANGED_BEACON_ENABLED | | 638 | BSS_CHANGED_BEACON_ENABLED | |
616 | BSS_CHANGED_HT | | 639 | BSS_CHANGED_HT | |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 3ab34d816897..8a8b459610b6 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -252,6 +252,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
252 | mgmt->u.action.u.self_prot.action_code = action; | 252 | mgmt->u.action.u.self_prot.action_code = action; |
253 | 253 | ||
254 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 254 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
255 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
256 | |||
255 | /* capability info */ | 257 | /* capability info */ |
256 | pos = skb_put(skb, 2); | 258 | pos = skb_put(skb, 2); |
257 | memset(pos, 0, 2); | 259 | memset(pos, 0, 2); |
@@ -260,10 +262,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
260 | pos = skb_put(skb, 2); | 262 | pos = skb_put(skb, 2); |
261 | memcpy(pos + 2, &plid, 2); | 263 | memcpy(pos + 2, &plid, 2); |
262 | } | 264 | } |
263 | if (ieee80211_add_srates_ie(sdata, skb, true, | 265 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
264 | local->oper_channel->band) || | 266 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
265 | ieee80211_add_ext_srates_ie(sdata, skb, true, | ||
266 | local->oper_channel->band) || | ||
267 | mesh_add_rsn_ie(skb, sdata) || | 267 | mesh_add_rsn_ie(skb, sdata) || |
268 | mesh_add_meshid_ie(skb, sdata) || | 268 | mesh_add_meshid_ie(skb, sdata) || |
269 | mesh_add_meshconf_ie(skb, sdata)) | 269 | mesh_add_meshconf_ie(skb, sdata)) |
@@ -343,7 +343,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
343 | struct ieee802_11_elems *elems) | 343 | struct ieee802_11_elems *elems) |
344 | { | 344 | { |
345 | struct ieee80211_local *local = sdata->local; | 345 | struct ieee80211_local *local = sdata->local; |
346 | enum ieee80211_band band = local->oper_channel->band; | 346 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
347 | struct ieee80211_supported_band *sband; | 347 | struct ieee80211_supported_band *sband; |
348 | u32 rates, basic_rates = 0; | 348 | u32 rates, basic_rates = 0; |
349 | struct sta_info *sta; | 349 | struct sta_info *sta; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e714ed8bb198..4add50063161 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -178,20 +178,30 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
178 | { | 178 | { |
179 | struct ieee80211_local *local = sdata->local; | 179 | struct ieee80211_local *local = sdata->local; |
180 | struct ieee80211_supported_band *sband; | 180 | struct ieee80211_supported_band *sband; |
181 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
182 | struct ieee80211_channel *chan; | ||
181 | struct sta_info *sta; | 183 | struct sta_info *sta; |
182 | u32 changed = 0; | 184 | u32 changed = 0; |
183 | u16 ht_opmode; | 185 | u16 ht_opmode; |
184 | bool disable_40 = false; | 186 | bool disable_40 = false; |
185 | 187 | ||
186 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 188 | rcu_read_lock(); |
189 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
190 | if (WARN_ON(!chanctx_conf)) { | ||
191 | rcu_read_unlock(); | ||
192 | return 0; | ||
193 | } | ||
194 | chan = chanctx_conf->channel; | ||
195 | rcu_read_unlock(); | ||
196 | sband = local->hw.wiphy->bands[chan->band]; | ||
187 | 197 | ||
188 | switch (sdata->vif.bss_conf.channel_type) { | 198 | switch (sdata->vif.bss_conf.channel_type) { |
189 | case NL80211_CHAN_HT40PLUS: | 199 | case NL80211_CHAN_HT40PLUS: |
190 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | 200 | if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) |
191 | disable_40 = true; | 201 | disable_40 = true; |
192 | break; | 202 | break; |
193 | case NL80211_CHAN_HT40MINUS: | 203 | case NL80211_CHAN_HT40MINUS: |
194 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | 204 | if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) |
195 | disable_40 = true; | 205 | disable_40 = true; |
196 | break; | 206 | break; |
197 | default: | 207 | default: |
@@ -359,11 +369,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
359 | int i, count, rates_len, supp_rates_len; | 369 | int i, count, rates_len, supp_rates_len; |
360 | u16 capab; | 370 | u16 capab; |
361 | struct ieee80211_supported_band *sband; | 371 | struct ieee80211_supported_band *sband; |
372 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
373 | struct ieee80211_channel *chan; | ||
362 | u32 rates = 0; | 374 | u32 rates = 0; |
363 | 375 | ||
364 | lockdep_assert_held(&ifmgd->mtx); | 376 | lockdep_assert_held(&ifmgd->mtx); |
365 | 377 | ||
366 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 378 | rcu_read_lock(); |
379 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
380 | if (WARN_ON(!chanctx_conf)) { | ||
381 | rcu_read_unlock(); | ||
382 | return; | ||
383 | } | ||
384 | chan = chanctx_conf->channel; | ||
385 | rcu_read_unlock(); | ||
386 | sband = local->hw.wiphy->bands[chan->band]; | ||
367 | 387 | ||
368 | if (assoc_data->supp_rates_len) { | 388 | if (assoc_data->supp_rates_len) { |
369 | /* | 389 | /* |
@@ -485,7 +505,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
485 | *pos++ = WLAN_EID_PWR_CAPABILITY; | 505 | *pos++ = WLAN_EID_PWR_CAPABILITY; |
486 | *pos++ = 2; | 506 | *pos++ = 2; |
487 | *pos++ = 0; /* min tx power */ | 507 | *pos++ = 0; /* min tx power */ |
488 | *pos++ = local->oper_channel->max_power; /* max tx power */ | 508 | *pos++ = chan->max_power; /* max tx power */ |
489 | 509 | ||
490 | /* 2. supported channels */ | 510 | /* 2. supported channels */ |
491 | /* TODO: get this in reg domain format */ | 511 | /* TODO: get this in reg domain format */ |
@@ -523,7 +543,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
523 | 543 | ||
524 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 544 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
525 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 545 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
526 | sband, local->oper_channel, ifmgd->ap_smps); | 546 | sband, chan, ifmgd->ap_smps); |
527 | 547 | ||
528 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 548 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
529 | ieee80211_add_vht_ie(sdata, skb, sband); | 549 | ieee80211_add_vht_ie(sdata, skb, sband); |
@@ -657,18 +677,18 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
657 | if (!ifmgd->associated) | 677 | if (!ifmgd->associated) |
658 | goto out; | 678 | goto out; |
659 | 679 | ||
660 | sdata->local->oper_channel = sdata->local->csa_channel; | 680 | sdata->local->_oper_channel = sdata->local->csa_channel; |
661 | if (!sdata->local->ops->channel_switch) { | 681 | if (!sdata->local->ops->channel_switch) { |
662 | /* call "hw_config" only if doing sw channel switch */ | 682 | /* call "hw_config" only if doing sw channel switch */ |
663 | ieee80211_hw_config(sdata->local, | 683 | ieee80211_hw_config(sdata->local, |
664 | IEEE80211_CONF_CHANGE_CHANNEL); | 684 | IEEE80211_CONF_CHANGE_CHANNEL); |
665 | } else { | 685 | } else { |
666 | /* update the device channel directly */ | 686 | /* update the device channel directly */ |
667 | sdata->local->hw.conf.channel = sdata->local->oper_channel; | 687 | sdata->local->hw.conf.channel = sdata->local->_oper_channel; |
668 | } | 688 | } |
669 | 689 | ||
670 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 690 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
671 | ifmgd->associated->channel = sdata->local->oper_channel; | 691 | ifmgd->associated->channel = sdata->local->_oper_channel; |
672 | 692 | ||
673 | /* XXX: wait for a beacon first? */ | 693 | /* XXX: wait for a beacon first? */ |
674 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 694 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
@@ -680,11 +700,8 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
680 | 700 | ||
681 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) | 701 | void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) |
682 | { | 702 | { |
683 | struct ieee80211_sub_if_data *sdata; | 703 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
684 | struct ieee80211_if_managed *ifmgd; | 704 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
685 | |||
686 | sdata = vif_to_sdata(vif); | ||
687 | ifmgd = &sdata->u.mgd; | ||
688 | 705 | ||
689 | trace_api_chswitch_done(sdata, success); | 706 | trace_api_chswitch_done(sdata, success); |
690 | if (!success) { | 707 | if (!success) { |
@@ -723,6 +740,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
723 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 740 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
724 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, | 741 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, |
725 | cbss->channel->band); | 742 | cbss->channel->band); |
743 | struct ieee80211_chanctx *chanctx; | ||
726 | 744 | ||
727 | ASSERT_MGD_MTX(ifmgd); | 745 | ASSERT_MGD_MTX(ifmgd); |
728 | 746 | ||
@@ -748,10 +766,34 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
748 | return; | 766 | return; |
749 | } | 767 | } |
750 | 768 | ||
751 | sdata->local->csa_channel = new_ch; | ||
752 | |||
753 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 769 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
754 | 770 | ||
771 | if (sdata->local->use_chanctx) { | ||
772 | sdata_info(sdata, | ||
773 | "not handling channel switch with channel contexts\n"); | ||
774 | ieee80211_queue_work(&sdata->local->hw, | ||
775 | &ifmgd->csa_connection_drop_work); | ||
776 | } | ||
777 | |||
778 | mutex_lock(&sdata->local->chanctx_mtx); | ||
779 | if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { | ||
780 | mutex_unlock(&sdata->local->chanctx_mtx); | ||
781 | return; | ||
782 | } | ||
783 | chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf), | ||
784 | struct ieee80211_chanctx, conf); | ||
785 | if (chanctx->refcount > 1) { | ||
786 | sdata_info(sdata, | ||
787 | "channel switch with multiple interfaces on the same channel, disconnecting\n"); | ||
788 | ieee80211_queue_work(&sdata->local->hw, | ||
789 | &ifmgd->csa_connection_drop_work); | ||
790 | mutex_unlock(&sdata->local->chanctx_mtx); | ||
791 | return; | ||
792 | } | ||
793 | mutex_unlock(&sdata->local->chanctx_mtx); | ||
794 | |||
795 | sdata->local->csa_channel = new_ch; | ||
796 | |||
755 | if (sw_elem->mode) | 797 | if (sw_elem->mode) |
756 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 798 | ieee80211_stop_queues_by_reason(&sdata->local->hw, |
757 | IEEE80211_QUEUE_STOP_REASON_CSA); | 799 | IEEE80211_QUEUE_STOP_REASON_CSA); |
@@ -1280,7 +1322,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
1280 | } | 1322 | } |
1281 | 1323 | ||
1282 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); | 1324 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); |
1283 | if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) | 1325 | if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_5GHZ) |
1284 | use_short_slot = true; | 1326 | use_short_slot = true; |
1285 | 1327 | ||
1286 | if (use_protection != bss_conf->use_cts_prot) { | 1328 | if (use_protection != bss_conf->use_cts_prot) { |
@@ -1465,9 +1507,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1465 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1507 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1466 | ieee80211_bss_info_change_notify(sdata, changed); | 1508 | ieee80211_bss_info_change_notify(sdata, changed); |
1467 | 1509 | ||
1468 | /* channel(_type) changes are handled by ieee80211_hw_config */ | 1510 | ieee80211_vif_release_channel(sdata); |
1469 | WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); | ||
1470 | ieee80211_hw_config(local, 0); | ||
1471 | 1511 | ||
1472 | /* disassociated - set to defaults now */ | 1512 | /* disassociated - set to defaults now */ |
1473 | ieee80211_set_wmm_default(sdata, false); | 1513 | ieee80211_set_wmm_default(sdata, false); |
@@ -1589,7 +1629,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1589 | 1629 | ||
1590 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | 1630 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, |
1591 | 0, (u32) -1, true, false, | 1631 | 0, (u32) -1, true, false, |
1592 | ifmgd->associated->channel); | 1632 | ifmgd->associated->channel, false); |
1593 | } | 1633 | } |
1594 | 1634 | ||
1595 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1635 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
@@ -1692,8 +1732,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1692 | ssid_len = ssid[1]; | 1732 | ssid_len = ssid[1]; |
1693 | 1733 | ||
1694 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, | 1734 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, |
1695 | (u32) -1, | 1735 | (u32) -1, cbss->channel, |
1696 | sdata->local->oper_channel, | ||
1697 | ssid + 2, ssid_len, | 1736 | ssid + 2, ssid_len, |
1698 | NULL, 0, true); | 1737 | NULL, 0, true); |
1699 | 1738 | ||
@@ -1804,6 +1843,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1804 | 1843 | ||
1805 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 1844 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
1806 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 1845 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
1846 | ieee80211_vif_release_channel(sdata); | ||
1807 | } | 1847 | } |
1808 | 1848 | ||
1809 | cfg80211_put_bss(auth_data->bss); | 1849 | cfg80211_put_bss(auth_data->bss); |
@@ -2030,6 +2070,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
2030 | 2070 | ||
2031 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2071 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
2032 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 2072 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
2073 | ieee80211_vif_release_channel(sdata); | ||
2033 | } | 2074 | } |
2034 | 2075 | ||
2035 | kfree(assoc_data); | 2076 | kfree(assoc_data); |
@@ -2091,7 +2132,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2091 | return false; | 2132 | return false; |
2092 | } | 2133 | } |
2093 | 2134 | ||
2094 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 2135 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
2095 | 2136 | ||
2096 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2137 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
2097 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2138 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
@@ -2369,6 +2410,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2369 | size_t baselen; | 2410 | size_t baselen; |
2370 | struct ieee802_11_elems elems; | 2411 | struct ieee802_11_elems elems; |
2371 | struct ieee80211_local *local = sdata->local; | 2412 | struct ieee80211_local *local = sdata->local; |
2413 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2414 | struct ieee80211_channel *chan; | ||
2372 | u32 changed = 0; | 2415 | u32 changed = 0; |
2373 | bool erp_valid, directed_tim = false; | 2416 | bool erp_valid, directed_tim = false; |
2374 | u8 erp_value = 0; | 2417 | u8 erp_value = 0; |
@@ -2382,8 +2425,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2382 | if (baselen > len) | 2425 | if (baselen > len) |
2383 | return; | 2426 | return; |
2384 | 2427 | ||
2385 | if (rx_status->freq != local->oper_channel->center_freq) | 2428 | rcu_read_lock(); |
2429 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2430 | if (!chanctx_conf) { | ||
2431 | rcu_read_unlock(); | ||
2386 | return; | 2432 | return; |
2433 | } | ||
2434 | |||
2435 | if (rx_status->freq != chanctx_conf->channel->center_freq) { | ||
2436 | rcu_read_unlock(); | ||
2437 | return; | ||
2438 | } | ||
2439 | chan = chanctx_conf->channel; | ||
2440 | rcu_read_unlock(); | ||
2387 | 2441 | ||
2388 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2442 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
2389 | ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { | 2443 | ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { |
@@ -2546,7 +2600,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2546 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { | 2600 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { |
2547 | struct ieee80211_supported_band *sband; | 2601 | struct ieee80211_supported_band *sband; |
2548 | 2602 | ||
2549 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 2603 | sband = local->hw.wiphy->bands[chan->band]; |
2550 | 2604 | ||
2551 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2605 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2552 | bssid, true); | 2606 | bssid, true); |
@@ -2555,7 +2609,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2555 | if (elems.country_elem && elems.pwr_constr_elem && | 2609 | if (elems.country_elem && elems.pwr_constr_elem && |
2556 | mgmt->u.probe_resp.capab_info & | 2610 | mgmt->u.probe_resp.capab_info & |
2557 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) | 2611 | cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT)) |
2558 | ieee80211_handle_pwr_constr(sdata, local->oper_channel, | 2612 | ieee80211_handle_pwr_constr(sdata, chan, |
2559 | elems.country_elem, | 2613 | elems.country_elem, |
2560 | elems.country_elem_len, | 2614 | elems.country_elem_len, |
2561 | elems.pwr_constr_elem); | 2615 | elems.pwr_constr_elem); |
@@ -2728,7 +2782,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2728 | */ | 2782 | */ |
2729 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 2783 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
2730 | NULL, 0, (u32) -1, true, false, | 2784 | NULL, 0, (u32) -1, true, false, |
2731 | auth_data->bss->channel); | 2785 | auth_data->bss->channel, false); |
2732 | } | 2786 | } |
2733 | 2787 | ||
2734 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 2788 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -3118,20 +3172,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3118 | } | 3172 | } |
3119 | } | 3173 | } |
3120 | 3174 | ||
3121 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 3175 | ieee80211_vif_release_channel(sdata); |
3122 | /* can only fail due to HT40+/- mismatch */ | 3176 | return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, |
3123 | channel_type = NL80211_CHAN_HT20; | 3177 | IEEE80211_CHANCTX_SHARED); |
3124 | sdata_info(sdata, | ||
3125 | "disabling 40 MHz due to multi-vif mismatch\n"); | ||
3126 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
3127 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | ||
3128 | channel_type)); | ||
3129 | } | ||
3130 | |||
3131 | local->oper_channel = cbss->channel; | ||
3132 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
3133 | |||
3134 | return 0; | ||
3135 | } | 3178 | } |
3136 | 3179 | ||
3137 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 3180 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, |
@@ -3201,7 +3244,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3201 | sdata->vif.bss_conf.basic_rates = basic_rates; | 3244 | sdata->vif.bss_conf.basic_rates = basic_rates; |
3202 | 3245 | ||
3203 | /* cf. IEEE 802.11 9.2.12 */ | 3246 | /* cf. IEEE 802.11 9.2.12 */ |
3204 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | 3247 | if (cbss->channel->band == IEEE80211_BAND_2GHZ && |
3205 | have_higher_than_11mbit) | 3248 | have_higher_than_11mbit) |
3206 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 3249 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
3207 | else | 3250 | else |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 9c52fc4a045e..c349f3aaf59e 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -199,7 +199,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
199 | 199 | ||
200 | if (roc->mgmt_tx_cookie) { | 200 | if (roc->mgmt_tx_cookie) { |
201 | if (!WARN_ON(!roc->frame)) { | 201 | if (!WARN_ON(!roc->frame)) { |
202 | ieee80211_tx_skb(roc->sdata, roc->frame); | 202 | ieee80211_tx_skb_tid_band(roc->sdata, roc->frame, 7, |
203 | roc->chan->band); | ||
203 | roc->frame = NULL; | 204 | roc->frame = NULL; |
204 | } | 205 | } |
205 | } else { | 206 | } else { |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 5c572e7a1a71..9f404ac901ab 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -135,6 +135,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
135 | ieee80211_bss_info_change_notify(sdata, | 135 | ieee80211_bss_info_change_notify(sdata, |
136 | BSS_CHANGED_BEACON_ENABLED); | 136 | BSS_CHANGED_BEACON_ENABLED); |
137 | 137 | ||
138 | /* the interface is leaving the channel and is removed */ | ||
139 | ieee80211_vif_release_channel(sdata); | ||
138 | drv_remove_interface(local, sdata); | 140 | drv_remove_interface(local, sdata); |
139 | } | 141 | } |
140 | 142 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 10de668eb9f6..ec198ef6aa8a 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -52,11 +52,21 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
52 | struct ieee80211_sta *ista = &sta->sta; | 52 | struct ieee80211_sta *ista = &sta->sta; |
53 | void *priv_sta = sta->rate_ctrl_priv; | 53 | void *priv_sta = sta->rate_ctrl_priv; |
54 | struct ieee80211_supported_band *sband; | 54 | struct ieee80211_supported_band *sband; |
55 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
55 | 56 | ||
56 | if (!ref) | 57 | if (!ref) |
57 | return; | 58 | return; |
58 | 59 | ||
59 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 60 | rcu_read_lock(); |
61 | |||
62 | chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); | ||
63 | if (WARN_ON(!chanctx_conf)) { | ||
64 | rcu_read_unlock(); | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; | ||
69 | rcu_read_unlock(); | ||
60 | 70 | ||
61 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 71 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
62 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | 72 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index fdaa505dab45..987c75d46bc0 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -421,7 +421,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
421 | local->scan_req->ie, local->scan_req->ie_len, | 421 | local->scan_req->ie, local->scan_req->ie_len, |
422 | local->scan_req->rates[band], false, | 422 | local->scan_req->rates[band], false, |
423 | local->scan_req->no_cck, | 423 | local->scan_req->no_cck, |
424 | local->hw.conf.channel); | 424 | local->hw.conf.channel, true); |
425 | 425 | ||
426 | /* | 426 | /* |
427 | * After sending probe requests, wait for probe responses | 427 | * After sending probe requests, wait for probe responses |
@@ -484,7 +484,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
484 | if (local->ops->hw_scan) { | 484 | if (local->ops->hw_scan) { |
485 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 485 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
486 | } else if ((req->n_channels == 1) && | 486 | } else if ((req->n_channels == 1) && |
487 | (req->channels[0] == local->oper_channel)) { | 487 | (req->channels[0] == local->_oper_channel)) { |
488 | /* | 488 | /* |
489 | * If we are scanning only on the operating channel | 489 | * If we are scanning only on the operating channel |
490 | * then we do not need to stop normal activities | 490 | * then we do not need to stop normal activities |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 797dd36a220d..fa639f41aa5b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1008,6 +1008,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1008 | __le16 fc; | 1008 | __le16 fc; |
1009 | bool qos = test_sta_flag(sta, WLAN_STA_WME); | 1009 | bool qos = test_sta_flag(sta, WLAN_STA_WME); |
1010 | struct ieee80211_tx_info *info; | 1010 | struct ieee80211_tx_info *info; |
1011 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1011 | 1012 | ||
1012 | if (qos) { | 1013 | if (qos) { |
1013 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | | 1014 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | |
@@ -1057,7 +1058,16 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1057 | 1058 | ||
1058 | drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false); | 1059 | drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false); |
1059 | 1060 | ||
1060 | ieee80211_xmit(sdata, skb); | 1061 | rcu_read_lock(); |
1062 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1063 | if (WARN_ON(!chanctx_conf)) { | ||
1064 | rcu_read_unlock(); | ||
1065 | kfree_skb(skb); | ||
1066 | return; | ||
1067 | } | ||
1068 | |||
1069 | ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); | ||
1070 | rcu_read_unlock(); | ||
1061 | } | 1071 | } |
1062 | 1072 | ||
1063 | static void | 1073 | static void |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c9bf83f36657..eee448ac71ff 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -324,11 +324,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
324 | struct ieee80211_sub_if_data *sdata; | 324 | struct ieee80211_sub_if_data *sdata; |
325 | struct sta_info *sta; | 325 | struct sta_info *sta; |
326 | 326 | ||
327 | /* | ||
328 | * virtual interfaces are protected by RCU | ||
329 | */ | ||
330 | rcu_read_lock(); | ||
331 | |||
332 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 327 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
333 | struct ieee80211_if_ap *ap; | 328 | struct ieee80211_if_ap *ap; |
334 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 329 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -360,8 +355,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
360 | } | 355 | } |
361 | } | 356 | } |
362 | 357 | ||
363 | rcu_read_unlock(); | ||
364 | |||
365 | local->total_ps_buffered = total; | 358 | local->total_ps_buffered = total; |
366 | ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged); | 359 | ps_dbg_hw(&local->hw, "PS buffers full - purged %d frames\n", purged); |
367 | } | 360 | } |
@@ -1372,7 +1365,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1372 | * Returns false if the frame couldn't be transmitted but was queued instead. | 1365 | * Returns false if the frame couldn't be transmitted but was queued instead. |
1373 | */ | 1366 | */ |
1374 | static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | 1367 | static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, |
1375 | struct sk_buff *skb, bool txpending) | 1368 | struct sk_buff *skb, bool txpending, |
1369 | enum ieee80211_band band) | ||
1376 | { | 1370 | { |
1377 | struct ieee80211_local *local = sdata->local; | 1371 | struct ieee80211_local *local = sdata->local; |
1378 | struct ieee80211_tx_data tx; | 1372 | struct ieee80211_tx_data tx; |
@@ -1386,20 +1380,18 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1386 | return true; | 1380 | return true; |
1387 | } | 1381 | } |
1388 | 1382 | ||
1389 | rcu_read_lock(); | ||
1390 | |||
1391 | /* initialises tx */ | 1383 | /* initialises tx */ |
1392 | led_len = skb->len; | 1384 | led_len = skb->len; |
1393 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); | 1385 | res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); |
1394 | 1386 | ||
1395 | if (unlikely(res_prepare == TX_DROP)) { | 1387 | if (unlikely(res_prepare == TX_DROP)) { |
1396 | ieee80211_free_txskb(&local->hw, skb); | 1388 | ieee80211_free_txskb(&local->hw, skb); |
1397 | goto out; | 1389 | return true; |
1398 | } else if (unlikely(res_prepare == TX_QUEUED)) { | 1390 | } else if (unlikely(res_prepare == TX_QUEUED)) { |
1399 | goto out; | 1391 | return true; |
1400 | } | 1392 | } |
1401 | 1393 | ||
1402 | info->band = local->hw.conf.channel->band; | 1394 | info->band = band; |
1403 | 1395 | ||
1404 | /* set up hw_queue value early */ | 1396 | /* set up hw_queue value early */ |
1405 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || | 1397 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || |
@@ -1410,8 +1402,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1410 | if (!invoke_tx_handlers(&tx)) | 1402 | if (!invoke_tx_handlers(&tx)) |
1411 | result = __ieee80211_tx(local, &tx.skbs, led_len, | 1403 | result = __ieee80211_tx(local, &tx.skbs, led_len, |
1412 | tx.sta, txpending); | 1404 | tx.sta, txpending); |
1413 | out: | 1405 | |
1414 | rcu_read_unlock(); | ||
1415 | return result; | 1406 | return result; |
1416 | } | 1407 | } |
1417 | 1408 | ||
@@ -1446,7 +1437,8 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, | |||
1446 | return 0; | 1437 | return 0; |
1447 | } | 1438 | } |
1448 | 1439 | ||
1449 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | 1440 | void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
1441 | enum ieee80211_band band) | ||
1450 | { | 1442 | { |
1451 | struct ieee80211_local *local = sdata->local; | 1443 | struct ieee80211_local *local = sdata->local; |
1452 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1444 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1454,8 +1446,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1454 | int headroom; | 1446 | int headroom; |
1455 | bool may_encrypt; | 1447 | bool may_encrypt; |
1456 | 1448 | ||
1457 | rcu_read_lock(); | ||
1458 | |||
1459 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); | 1449 | may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); |
1460 | 1450 | ||
1461 | headroom = local->tx_headroom; | 1451 | headroom = local->tx_headroom; |
@@ -1466,7 +1456,6 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1466 | 1456 | ||
1467 | if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { | 1457 | if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { |
1468 | ieee80211_free_txskb(&local->hw, skb); | 1458 | ieee80211_free_txskb(&local->hw, skb); |
1469 | rcu_read_unlock(); | ||
1470 | return; | 1459 | return; |
1471 | } | 1460 | } |
1472 | 1461 | ||
@@ -1478,13 +1467,11 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1478 | !is_multicast_ether_addr(hdr->addr1) && | 1467 | !is_multicast_ether_addr(hdr->addr1) && |
1479 | mesh_nexthop_resolve(skb, sdata)) { | 1468 | mesh_nexthop_resolve(skb, sdata)) { |
1480 | /* skb queued: don't free */ | 1469 | /* skb queued: don't free */ |
1481 | rcu_read_unlock(); | ||
1482 | return; | 1470 | return; |
1483 | } | 1471 | } |
1484 | 1472 | ||
1485 | ieee80211_set_qos_hdr(sdata, skb); | 1473 | ieee80211_set_qos_hdr(sdata, skb); |
1486 | ieee80211_tx(sdata, skb, false); | 1474 | ieee80211_tx(sdata, skb, false, band); |
1487 | rcu_read_unlock(); | ||
1488 | } | 1475 | } |
1489 | 1476 | ||
1490 | static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) | 1477 | static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) |
@@ -1574,7 +1561,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1574 | struct net_device *dev) | 1561 | struct net_device *dev) |
1575 | { | 1562 | { |
1576 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1563 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1577 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1564 | struct ieee80211_chanctx_conf *chanctx_conf; |
1565 | struct ieee80211_channel *chan; | ||
1578 | struct ieee80211_radiotap_header *prthdr = | 1566 | struct ieee80211_radiotap_header *prthdr = |
1579 | (struct ieee80211_radiotap_header *)skb->data; | 1567 | (struct ieee80211_radiotap_header *)skb->data; |
1580 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1568 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1583,26 +1571,6 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1583 | u16 len_rthdr; | 1571 | u16 len_rthdr; |
1584 | int hdrlen; | 1572 | int hdrlen; |
1585 | 1573 | ||
1586 | /* | ||
1587 | * Frame injection is not allowed if beaconing is not allowed | ||
1588 | * or if we need radar detection. Beaconing is usually not allowed when | ||
1589 | * the mode or operation (Adhoc, AP, Mesh) does not support DFS. | ||
1590 | * Passive scan is also used in world regulatory domains where | ||
1591 | * your country is not known and as such it should be treated as | ||
1592 | * NO TX unless the channel is explicitly allowed in which case | ||
1593 | * your current regulatory domain would not have the passive scan | ||
1594 | * flag. | ||
1595 | * | ||
1596 | * Since AP mode uses monitor interfaces to inject/TX management | ||
1597 | * frames we can make AP mode the exception to this rule once it | ||
1598 | * supports radar detection as its implementation can deal with | ||
1599 | * radar detection by itself. We can do that later by adding a | ||
1600 | * monitor flag interfaces used for AP support. | ||
1601 | */ | ||
1602 | if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | | ||
1603 | IEEE80211_CHAN_PASSIVE_SCAN))) | ||
1604 | goto fail; | ||
1605 | |||
1606 | /* check for not even having the fixed radiotap header part */ | 1574 | /* check for not even having the fixed radiotap header part */ |
1607 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) | 1575 | if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) |
1608 | goto fail; /* too short to be possibly valid */ | 1576 | goto fail; /* too short to be possibly valid */ |
@@ -1688,11 +1656,45 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1688 | } | 1656 | } |
1689 | } | 1657 | } |
1690 | 1658 | ||
1691 | ieee80211_xmit(sdata, skb); | 1659 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1660 | if (!chanctx_conf) { | ||
1661 | tmp_sdata = rcu_dereference(local->monitor_sdata); | ||
1662 | if (tmp_sdata) | ||
1663 | chanctx_conf = | ||
1664 | rcu_dereference(tmp_sdata->vif.chanctx_conf); | ||
1665 | } | ||
1666 | if (!chanctx_conf) | ||
1667 | goto fail_rcu; | ||
1668 | |||
1669 | chan = chanctx_conf->channel; | ||
1670 | |||
1671 | /* | ||
1672 | * Frame injection is not allowed if beaconing is not allowed | ||
1673 | * or if we need radar detection. Beaconing is usually not allowed when | ||
1674 | * the mode or operation (Adhoc, AP, Mesh) does not support DFS. | ||
1675 | * Passive scan is also used in world regulatory domains where | ||
1676 | * your country is not known and as such it should be treated as | ||
1677 | * NO TX unless the channel is explicitly allowed in which case | ||
1678 | * your current regulatory domain would not have the passive scan | ||
1679 | * flag. | ||
1680 | * | ||
1681 | * Since AP mode uses monitor interfaces to inject/TX management | ||
1682 | * frames we can make AP mode the exception to this rule once it | ||
1683 | * supports radar detection as its implementation can deal with | ||
1684 | * radar detection by itself. We can do that later by adding a | ||
1685 | * monitor flag interfaces used for AP support. | ||
1686 | */ | ||
1687 | if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR | | ||
1688 | IEEE80211_CHAN_PASSIVE_SCAN))) | ||
1689 | goto fail_rcu; | ||
1690 | |||
1691 | ieee80211_xmit(sdata, skb, chan->band); | ||
1692 | rcu_read_unlock(); | 1692 | rcu_read_unlock(); |
1693 | 1693 | ||
1694 | return NETDEV_TX_OK; | 1694 | return NETDEV_TX_OK; |
1695 | 1695 | ||
1696 | fail_rcu: | ||
1697 | rcu_read_unlock(); | ||
1696 | fail: | 1698 | fail: |
1697 | dev_kfree_skb(skb); | 1699 | dev_kfree_skb(skb); |
1698 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ | 1700 | return NETDEV_TX_OK; /* meaning, we dealt with the skb */ |
@@ -1734,6 +1736,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1734 | bool multicast; | 1736 | bool multicast; |
1735 | u32 info_flags = 0; | 1737 | u32 info_flags = 0; |
1736 | u16 info_id = 0; | 1738 | u16 info_id = 0; |
1739 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1740 | struct ieee80211_sub_if_data *ap_sdata; | ||
1741 | enum ieee80211_band band; | ||
1737 | 1742 | ||
1738 | if (unlikely(skb->len < ETH_HLEN)) | 1743 | if (unlikely(skb->len < ETH_HLEN)) |
1739 | goto fail; | 1744 | goto fail; |
@@ -1743,9 +1748,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1743 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1748 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1744 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | 1749 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1745 | 1750 | ||
1751 | rcu_read_lock(); | ||
1752 | |||
1746 | switch (sdata->vif.type) { | 1753 | switch (sdata->vif.type) { |
1747 | case NL80211_IFTYPE_AP_VLAN: | 1754 | case NL80211_IFTYPE_AP_VLAN: |
1748 | rcu_read_lock(); | ||
1749 | sta = rcu_dereference(sdata->u.vlan.sta); | 1755 | sta = rcu_dereference(sdata->u.vlan.sta); |
1750 | if (sta) { | 1756 | if (sta) { |
1751 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1757 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
@@ -1758,7 +1764,12 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1758 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); | 1764 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); |
1759 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | 1765 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); |
1760 | } | 1766 | } |
1761 | rcu_read_unlock(); | 1767 | ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
1768 | u.ap); | ||
1769 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); | ||
1770 | if (!chanctx_conf) | ||
1771 | goto fail_rcu; | ||
1772 | band = chanctx_conf->channel->band; | ||
1762 | if (sta) | 1773 | if (sta) |
1763 | break; | 1774 | break; |
1764 | /* fall through */ | 1775 | /* fall through */ |
@@ -1769,6 +1780,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1769 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); | 1780 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1770 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1781 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1771 | hdrlen = 24; | 1782 | hdrlen = 24; |
1783 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1784 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1785 | if (!chanctx_conf) | ||
1786 | goto fail_rcu; | ||
1787 | band = chanctx_conf->channel->band; | ||
1772 | break; | 1788 | break; |
1773 | case NL80211_IFTYPE_WDS: | 1789 | case NL80211_IFTYPE_WDS: |
1774 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1790 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
@@ -1778,15 +1794,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1778 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1794 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1779 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1795 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1780 | hdrlen = 30; | 1796 | hdrlen = 30; |
1797 | /* | ||
1798 | * This is the exception! WDS style interfaces are prohibited | ||
1799 | * when channel contexts are in used so this must be valid | ||
1800 | */ | ||
1801 | band = local->hw.conf.channel->band; | ||
1781 | break; | 1802 | break; |
1782 | #ifdef CONFIG_MAC80211_MESH | 1803 | #ifdef CONFIG_MAC80211_MESH |
1783 | case NL80211_IFTYPE_MESH_POINT: | 1804 | case NL80211_IFTYPE_MESH_POINT: |
1784 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1805 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1785 | /* Do not send frames with mesh_ttl == 0 */ | 1806 | /* Do not send frames with mesh_ttl == 0 */ |
1786 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1807 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1787 | goto fail; | 1808 | goto fail_rcu; |
1788 | } | 1809 | } |
1789 | rcu_read_lock(); | 1810 | |
1790 | if (!is_multicast_ether_addr(skb->data)) { | 1811 | if (!is_multicast_ether_addr(skb->data)) { |
1791 | mpath = mesh_path_lookup(skb->data, sdata); | 1812 | mpath = mesh_path_lookup(skb->data, sdata); |
1792 | if (!mpath) | 1813 | if (!mpath) |
@@ -1803,7 +1824,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1803 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { | 1824 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { |
1804 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1825 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1805 | skb->data, skb->data + ETH_ALEN); | 1826 | skb->data, skb->data + ETH_ALEN); |
1806 | rcu_read_unlock(); | ||
1807 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1827 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1808 | sdata, NULL, NULL); | 1828 | sdata, NULL, NULL); |
1809 | } else { | 1829 | } else { |
@@ -1819,7 +1839,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1819 | mesh_da = mppath->mpp; | 1839 | mesh_da = mppath->mpp; |
1820 | else if (mpath) | 1840 | else if (mpath) |
1821 | mesh_da = mpath->dst; | 1841 | mesh_da = mpath->dst; |
1822 | rcu_read_unlock(); | ||
1823 | 1842 | ||
1824 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1843 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1825 | mesh_da, sdata->vif.addr); | 1844 | mesh_da, sdata->vif.addr); |
@@ -1839,13 +1858,16 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1839 | skb->data + ETH_ALEN); | 1858 | skb->data + ETH_ALEN); |
1840 | 1859 | ||
1841 | } | 1860 | } |
1861 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1862 | if (!chanctx_conf) | ||
1863 | goto fail_rcu; | ||
1864 | band = chanctx_conf->channel->band; | ||
1842 | break; | 1865 | break; |
1843 | #endif | 1866 | #endif |
1844 | case NL80211_IFTYPE_STATION: | 1867 | case NL80211_IFTYPE_STATION: |
1845 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 1868 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
1846 | bool tdls_peer = false; | 1869 | bool tdls_peer = false; |
1847 | 1870 | ||
1848 | rcu_read_lock(); | ||
1849 | sta = sta_info_get(sdata, skb->data); | 1871 | sta = sta_info_get(sdata, skb->data); |
1850 | if (sta) { | 1872 | if (sta) { |
1851 | authorized = test_sta_flag(sta, | 1873 | authorized = test_sta_flag(sta, |
@@ -1856,7 +1878,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1856 | tdls_auth = test_sta_flag(sta, | 1878 | tdls_auth = test_sta_flag(sta, |
1857 | WLAN_STA_TDLS_PEER_AUTH); | 1879 | WLAN_STA_TDLS_PEER_AUTH); |
1858 | } | 1880 | } |
1859 | rcu_read_unlock(); | ||
1860 | 1881 | ||
1861 | /* | 1882 | /* |
1862 | * If the TDLS link is enabled, send everything | 1883 | * If the TDLS link is enabled, send everything |
@@ -1871,7 +1892,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1871 | if (tdls_direct) { | 1892 | if (tdls_direct) { |
1872 | /* link during setup - throw out frames to peer */ | 1893 | /* link during setup - throw out frames to peer */ |
1873 | if (!tdls_auth) | 1894 | if (!tdls_auth) |
1874 | goto fail; | 1895 | goto fail_rcu; |
1875 | 1896 | ||
1876 | /* DA SA BSSID */ | 1897 | /* DA SA BSSID */ |
1877 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1898 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1896,6 +1917,10 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1896 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1917 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1897 | hdrlen = 24; | 1918 | hdrlen = 24; |
1898 | } | 1919 | } |
1920 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1921 | if (!chanctx_conf) | ||
1922 | goto fail_rcu; | ||
1923 | band = chanctx_conf->channel->band; | ||
1899 | break; | 1924 | break; |
1900 | case NL80211_IFTYPE_ADHOC: | 1925 | case NL80211_IFTYPE_ADHOC: |
1901 | /* DA SA BSSID */ | 1926 | /* DA SA BSSID */ |
@@ -1903,9 +1928,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1903 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1928 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
1904 | memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN); | 1929 | memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN); |
1905 | hdrlen = 24; | 1930 | hdrlen = 24; |
1931 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1932 | if (!chanctx_conf) | ||
1933 | goto fail_rcu; | ||
1934 | band = chanctx_conf->channel->band; | ||
1906 | break; | 1935 | break; |
1907 | default: | 1936 | default: |
1908 | goto fail; | 1937 | goto fail_rcu; |
1909 | } | 1938 | } |
1910 | 1939 | ||
1911 | /* | 1940 | /* |
@@ -1915,13 +1944,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1915 | */ | 1944 | */ |
1916 | multicast = is_multicast_ether_addr(hdr.addr1); | 1945 | multicast = is_multicast_ether_addr(hdr.addr1); |
1917 | if (!multicast) { | 1946 | if (!multicast) { |
1918 | rcu_read_lock(); | ||
1919 | sta = sta_info_get(sdata, hdr.addr1); | 1947 | sta = sta_info_get(sdata, hdr.addr1); |
1920 | if (sta) { | 1948 | if (sta) { |
1921 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); | 1949 | authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); |
1922 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | 1950 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); |
1923 | } | 1951 | } |
1924 | rcu_read_unlock(); | ||
1925 | } | 1952 | } |
1926 | 1953 | ||
1927 | /* For mesh, the use of the QoS header is mandatory */ | 1954 | /* For mesh, the use of the QoS header is mandatory */ |
@@ -1949,7 +1976,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1949 | 1976 | ||
1950 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | 1977 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); |
1951 | 1978 | ||
1952 | goto fail; | 1979 | goto fail_rcu; |
1953 | } | 1980 | } |
1954 | 1981 | ||
1955 | if (unlikely(!multicast && skb->sk && | 1982 | if (unlikely(!multicast && skb->sk && |
@@ -2004,7 +2031,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2004 | kfree_skb(tmp_skb); | 2031 | kfree_skb(tmp_skb); |
2005 | 2032 | ||
2006 | if (!skb) | 2033 | if (!skb) |
2007 | goto fail; | 2034 | goto fail_rcu; |
2008 | } | 2035 | } |
2009 | 2036 | ||
2010 | hdr.frame_control = fc; | 2037 | hdr.frame_control = fc; |
@@ -2052,7 +2079,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2052 | head_need = max_t(int, 0, head_need); | 2079 | head_need = max_t(int, 0, head_need); |
2053 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { | 2080 | if (ieee80211_skb_resize(sdata, skb, head_need, true)) { |
2054 | ieee80211_free_txskb(&local->hw, skb); | 2081 | ieee80211_free_txskb(&local->hw, skb); |
2055 | return NETDEV_TX_OK; | 2082 | goto fail_rcu; |
2056 | } | 2083 | } |
2057 | } | 2084 | } |
2058 | 2085 | ||
@@ -2104,10 +2131,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2104 | info->flags = info_flags; | 2131 | info->flags = info_flags; |
2105 | info->ack_frame_id = info_id; | 2132 | info->ack_frame_id = info_id; |
2106 | 2133 | ||
2107 | ieee80211_xmit(sdata, skb); | 2134 | ieee80211_xmit(sdata, skb, band); |
2135 | rcu_read_unlock(); | ||
2108 | 2136 | ||
2109 | return NETDEV_TX_OK; | 2137 | return NETDEV_TX_OK; |
2110 | 2138 | ||
2139 | fail_rcu: | ||
2140 | rcu_read_unlock(); | ||
2111 | fail: | 2141 | fail: |
2112 | dev_kfree_skb(skb); | 2142 | dev_kfree_skb(skb); |
2113 | return NETDEV_TX_OK; | 2143 | return NETDEV_TX_OK; |
@@ -2139,11 +2169,18 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
2139 | struct sta_info *sta; | 2169 | struct sta_info *sta; |
2140 | struct ieee80211_hdr *hdr; | 2170 | struct ieee80211_hdr *hdr; |
2141 | bool result; | 2171 | bool result; |
2172 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2142 | 2173 | ||
2143 | sdata = vif_to_sdata(info->control.vif); | 2174 | sdata = vif_to_sdata(info->control.vif); |
2144 | 2175 | ||
2145 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { | 2176 | if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) { |
2146 | result = ieee80211_tx(sdata, skb, true); | 2177 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2178 | if (unlikely(!chanctx_conf)) { | ||
2179 | dev_kfree_skb(skb); | ||
2180 | return true; | ||
2181 | } | ||
2182 | result = ieee80211_tx(sdata, skb, true, | ||
2183 | chanctx_conf->channel->band); | ||
2147 | } else { | 2184 | } else { |
2148 | struct sk_buff_head skbs; | 2185 | struct sk_buff_head skbs; |
2149 | 2186 | ||
@@ -2285,14 +2322,16 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2285 | struct ieee80211_sub_if_data *sdata = NULL; | 2322 | struct ieee80211_sub_if_data *sdata = NULL; |
2286 | struct ieee80211_if_ap *ap = NULL; | 2323 | struct ieee80211_if_ap *ap = NULL; |
2287 | struct beacon_data *beacon; | 2324 | struct beacon_data *beacon; |
2288 | enum ieee80211_band band = local->oper_channel->band; | 2325 | enum ieee80211_band band; |
2289 | struct ieee80211_tx_rate_control txrc; | 2326 | struct ieee80211_tx_rate_control txrc; |
2327 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2290 | 2328 | ||
2291 | rcu_read_lock(); | 2329 | rcu_read_lock(); |
2292 | 2330 | ||
2293 | sdata = vif_to_sdata(vif); | 2331 | sdata = vif_to_sdata(vif); |
2332 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2294 | 2333 | ||
2295 | if (!ieee80211_sdata_running(sdata)) | 2334 | if (!ieee80211_sdata_running(sdata) || !chanctx_conf) |
2296 | goto out; | 2335 | goto out; |
2297 | 2336 | ||
2298 | if (tim_offset) | 2337 | if (tim_offset) |
@@ -2409,6 +2448,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2409 | *pos++ = WLAN_EID_SSID; | 2448 | *pos++ = WLAN_EID_SSID; |
2410 | *pos++ = 0x0; | 2449 | *pos++ = 0x0; |
2411 | 2450 | ||
2451 | band = chanctx_conf->channel->band; | ||
2452 | |||
2412 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 2453 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
2413 | mesh_add_ds_params_ie(skb, sdata) || | 2454 | mesh_add_ds_params_ie(skb, sdata) || |
2414 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 2455 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
@@ -2426,6 +2467,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2426 | goto out; | 2467 | goto out; |
2427 | } | 2468 | } |
2428 | 2469 | ||
2470 | band = chanctx_conf->channel->band; | ||
2471 | |||
2429 | info = IEEE80211_SKB_CB(skb); | 2472 | info = IEEE80211_SKB_CB(skb); |
2430 | 2473 | ||
2431 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 2474 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
@@ -2656,14 +2699,17 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2656 | struct ieee80211_if_ap *bss = NULL; | 2699 | struct ieee80211_if_ap *bss = NULL; |
2657 | struct beacon_data *beacon; | 2700 | struct beacon_data *beacon; |
2658 | struct ieee80211_tx_info *info; | 2701 | struct ieee80211_tx_info *info; |
2702 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
2659 | 2703 | ||
2660 | sdata = vif_to_sdata(vif); | 2704 | sdata = vif_to_sdata(vif); |
2661 | bss = &sdata->u.ap; | 2705 | bss = &sdata->u.ap; |
2662 | 2706 | ||
2663 | rcu_read_lock(); | 2707 | rcu_read_lock(); |
2664 | beacon = rcu_dereference(bss->beacon); | 2708 | beacon = rcu_dereference(bss->beacon); |
2709 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2665 | 2710 | ||
2666 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) | 2711 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head || |
2712 | !chanctx_conf) | ||
2667 | goto out; | 2713 | goto out; |
2668 | 2714 | ||
2669 | if (bss->dtim_count != 0 || !bss->dtim_bc_mc) | 2715 | if (bss->dtim_count != 0 || !bss->dtim_bc_mc) |
@@ -2693,7 +2739,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2693 | info = IEEE80211_SKB_CB(skb); | 2739 | info = IEEE80211_SKB_CB(skb); |
2694 | 2740 | ||
2695 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2741 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2696 | info->band = local->oper_channel->band; | 2742 | info->band = chanctx_conf->channel->band; |
2697 | 2743 | ||
2698 | if (invoke_tx_handlers(&tx)) | 2744 | if (invoke_tx_handlers(&tx)) |
2699 | skb = NULL; | 2745 | skb = NULL; |
@@ -2704,8 +2750,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2704 | } | 2750 | } |
2705 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2751 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2706 | 2752 | ||
2707 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | 2753 | void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, |
2708 | struct sk_buff *skb, int tid) | 2754 | struct sk_buff *skb, int tid, |
2755 | enum ieee80211_band band) | ||
2709 | { | 2756 | { |
2710 | int ac = ieee802_1d_to_ac[tid & 7]; | 2757 | int ac = ieee802_1d_to_ac[tid & 7]; |
2711 | 2758 | ||
@@ -2722,6 +2769,6 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | |||
2722 | * requirements are that we do not come into tx with bhs on. | 2769 | * requirements are that we do not come into tx with bhs on. |
2723 | */ | 2770 | */ |
2724 | local_bh_disable(); | 2771 | local_bh_disable(); |
2725 | ieee80211_xmit(sdata, skb); | 2772 | ieee80211_xmit(sdata, skb, band); |
2726 | local_bh_enable(); | 2773 | local_bh_enable(); |
2727 | } | 2774 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22ca35054dd0..7d737071dedb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -832,6 +832,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
832 | { | 832 | { |
833 | struct ieee80211_local *local = sdata->local; | 833 | struct ieee80211_local *local = sdata->local; |
834 | struct ieee80211_tx_queue_params qparam; | 834 | struct ieee80211_tx_queue_params qparam; |
835 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
835 | int ac; | 836 | int ac; |
836 | bool use_11b, enable_qos; | 837 | bool use_11b, enable_qos; |
837 | int aCWmin, aCWmax; | 838 | int aCWmin, aCWmax; |
@@ -844,8 +845,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
844 | 845 | ||
845 | memset(&qparam, 0, sizeof(qparam)); | 846 | memset(&qparam, 0, sizeof(qparam)); |
846 | 847 | ||
847 | use_11b = (local->oper_channel->band == IEEE80211_BAND_2GHZ) && | 848 | rcu_read_lock(); |
849 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
850 | use_11b = (chanctx_conf && | ||
851 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && | ||
848 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 852 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
853 | rcu_read_unlock(); | ||
849 | 854 | ||
850 | /* | 855 | /* |
851 | * By default disable QoS in STA mode for old access points, which do | 856 | * By default disable QoS in STA mode for old access points, which do |
@@ -924,7 +929,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
924 | const size_t supp_rates_len, | 929 | const size_t supp_rates_len, |
925 | const u8 *supp_rates) | 930 | const u8 *supp_rates) |
926 | { | 931 | { |
927 | struct ieee80211_local *local = sdata->local; | 932 | struct ieee80211_chanctx_conf *chanctx_conf; |
928 | int i, have_higher_than_11mbit = 0; | 933 | int i, have_higher_than_11mbit = 0; |
929 | 934 | ||
930 | /* cf. IEEE 802.11 9.2.12 */ | 935 | /* cf. IEEE 802.11 9.2.12 */ |
@@ -932,11 +937,16 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
932 | if ((supp_rates[i] & 0x7f) * 5 > 110) | 937 | if ((supp_rates[i] & 0x7f) * 5 > 110) |
933 | have_higher_than_11mbit = 1; | 938 | have_higher_than_11mbit = 1; |
934 | 939 | ||
935 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && | 940 | rcu_read_lock(); |
941 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
942 | |||
943 | if (chanctx_conf && | ||
944 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && | ||
936 | have_higher_than_11mbit) | 945 | have_higher_than_11mbit) |
937 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 946 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
938 | else | 947 | else |
939 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 948 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
949 | rcu_read_unlock(); | ||
940 | 950 | ||
941 | ieee80211_set_wmm_default(sdata, true); | 951 | ieee80211_set_wmm_default(sdata, true); |
942 | } | 952 | } |
@@ -1206,7 +1216,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1206 | const u8 *ssid, size_t ssid_len, | 1216 | const u8 *ssid, size_t ssid_len, |
1207 | const u8 *ie, size_t ie_len, | 1217 | const u8 *ie, size_t ie_len, |
1208 | u32 ratemask, bool directed, bool no_cck, | 1218 | u32 ratemask, bool directed, bool no_cck, |
1209 | struct ieee80211_channel *channel) | 1219 | struct ieee80211_channel *channel, bool scan) |
1210 | { | 1220 | { |
1211 | struct sk_buff *skb; | 1221 | struct sk_buff *skb; |
1212 | 1222 | ||
@@ -1217,7 +1227,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1217 | if (no_cck) | 1227 | if (no_cck) |
1218 | IEEE80211_SKB_CB(skb)->flags |= | 1228 | IEEE80211_SKB_CB(skb)->flags |= |
1219 | IEEE80211_TX_CTL_NO_CCK_RATE; | 1229 | IEEE80211_TX_CTL_NO_CCK_RATE; |
1220 | ieee80211_tx_skb(sdata, skb); | 1230 | if (scan) |
1231 | ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); | ||
1232 | else | ||
1233 | ieee80211_tx_skb(sdata, skb); | ||
1221 | } | 1234 | } |
1222 | } | 1235 | } |
1223 | 1236 | ||
@@ -1280,6 +1293,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1280 | { | 1293 | { |
1281 | struct ieee80211_hw *hw = &local->hw; | 1294 | struct ieee80211_hw *hw = &local->hw; |
1282 | struct ieee80211_sub_if_data *sdata; | 1295 | struct ieee80211_sub_if_data *sdata; |
1296 | struct ieee80211_chanctx *ctx; | ||
1283 | struct sta_info *sta; | 1297 | struct sta_info *sta; |
1284 | int res, i; | 1298 | int res, i; |
1285 | 1299 | ||
@@ -1352,6 +1366,12 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1352 | res = drv_add_interface(local, sdata); | 1366 | res = drv_add_interface(local, sdata); |
1353 | } | 1367 | } |
1354 | 1368 | ||
1369 | /* add channel contexts */ | ||
1370 | mutex_lock(&local->chanctx_mtx); | ||
1371 | list_for_each_entry(ctx, &local->chanctx_list, list) | ||
1372 | WARN_ON(drv_add_chanctx(local, ctx)); | ||
1373 | mutex_unlock(&local->chanctx_mtx); | ||
1374 | |||
1355 | /* add STAs back */ | 1375 | /* add STAs back */ |
1356 | mutex_lock(&local->sta_mtx); | 1376 | mutex_lock(&local->sta_mtx); |
1357 | list_for_each_entry(sta, &local->sta_list, list) { | 1377 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -1392,11 +1412,22 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1392 | 1412 | ||
1393 | /* Finally also reconfigure all the BSS information */ | 1413 | /* Finally also reconfigure all the BSS information */ |
1394 | list_for_each_entry(sdata, &local->interfaces, list) { | 1414 | list_for_each_entry(sdata, &local->interfaces, list) { |
1415 | struct ieee80211_chanctx_conf *ctx_conf; | ||
1395 | u32 changed; | 1416 | u32 changed; |
1396 | 1417 | ||
1397 | if (!ieee80211_sdata_running(sdata)) | 1418 | if (!ieee80211_sdata_running(sdata)) |
1398 | continue; | 1419 | continue; |
1399 | 1420 | ||
1421 | mutex_lock(&local->chanctx_mtx); | ||
1422 | ctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1423 | lockdep_is_held(&local->chanctx_mtx)); | ||
1424 | if (ctx_conf) { | ||
1425 | ctx = container_of(ctx_conf, struct ieee80211_chanctx, | ||
1426 | conf); | ||
1427 | drv_assign_vif_chanctx(local, sdata, ctx); | ||
1428 | } | ||
1429 | mutex_unlock(&local->chanctx_mtx); | ||
1430 | |||
1400 | /* common change flags for all interface types */ | 1431 | /* common change flags for all interface types */ |
1401 | changed = BSS_CHANGED_ERP_CTS_PROT | | 1432 | changed = BSS_CHANGED_ERP_CTS_PROT | |
1402 | BSS_CHANGED_ERP_PREAMBLE | | 1433 | BSS_CHANGED_ERP_PREAMBLE | |