diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 398 |
1 files changed, 246 insertions, 152 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 05f3a313db88..c46d4ee1c298 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,13 @@ 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 | /* TODO: make hostapd tell us what it wants */ |
883 | params->channel_type); | 888 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
889 | sdata->needed_rx_chains = sdata->local->rx_chains; | ||
890 | |||
891 | err = ieee80211_vif_use_channel(sdata, params->channel, | ||
892 | params->channel_type, | ||
893 | IEEE80211_CHANCTX_SHARED); | ||
884 | if (err) | 894 | if (err) |
885 | return err; | 895 | return err; |
886 | 896 | ||
@@ -912,6 +922,15 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
912 | return err; | 922 | return err; |
913 | changed |= err; | 923 | changed |= err; |
914 | 924 | ||
925 | err = drv_start_ap(sdata->local, sdata); | ||
926 | if (err) { | ||
927 | old = rtnl_dereference(sdata->u.ap.beacon); | ||
928 | if (old) | ||
929 | kfree_rcu(old, rcu_head); | ||
930 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | ||
931 | return err; | ||
932 | } | ||
933 | |||
915 | ieee80211_bss_info_change_notify(sdata, changed); | 934 | ieee80211_bss_info_change_notify(sdata, changed); |
916 | 935 | ||
917 | netif_carrier_on(dev); | 936 | netif_carrier_on(dev); |
@@ -943,26 +962,40 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
943 | 962 | ||
944 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | 963 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) |
945 | { | 964 | { |
946 | struct ieee80211_sub_if_data *sdata, *vlan; | 965 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
947 | struct beacon_data *old; | 966 | struct ieee80211_sub_if_data *vlan; |
948 | 967 | struct ieee80211_local *local = sdata->local; | |
949 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 968 | struct beacon_data *old_beacon; |
969 | struct probe_resp *old_probe_resp; | ||
950 | 970 | ||
951 | old = rtnl_dereference(sdata->u.ap.beacon); | 971 | old_beacon = rtnl_dereference(sdata->u.ap.beacon); |
952 | if (!old) | 972 | if (!old_beacon) |
953 | return -ENOENT; | 973 | return -ENOENT; |
974 | old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp); | ||
954 | 975 | ||
976 | /* turn off carrier for this interface and dependent VLANs */ | ||
955 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 977 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
956 | netif_carrier_off(vlan->dev); | 978 | netif_carrier_off(vlan->dev); |
957 | netif_carrier_off(dev); | 979 | netif_carrier_off(dev); |
958 | 980 | ||
981 | /* remove beacon and probe response */ | ||
959 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 982 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
983 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | ||
984 | kfree_rcu(old_beacon, rcu_head); | ||
985 | if (old_probe_resp) | ||
986 | kfree_rcu(old_probe_resp, rcu_head); | ||
960 | 987 | ||
961 | kfree_rcu(old, rcu_head); | 988 | sta_info_flush(local, sdata); |
962 | |||
963 | sta_info_flush(sdata->local, sdata); | ||
964 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 989 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
965 | 990 | ||
991 | drv_stop_ap(sdata->local, sdata); | ||
992 | |||
993 | /* free all potentially still buffered bcast frames */ | ||
994 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); | ||
995 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | ||
996 | |||
997 | ieee80211_vif_release_channel(sdata); | ||
998 | |||
966 | return 0; | 999 | return 0; |
967 | } | 1000 | } |
968 | 1001 | ||
@@ -1019,9 +1052,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1019 | int i, j; | 1052 | int i, j; |
1020 | struct ieee80211_supported_band *sband; | 1053 | struct ieee80211_supported_band *sband; |
1021 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1054 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1055 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
1022 | u32 mask, set; | 1056 | u32 mask, set; |
1023 | 1057 | ||
1024 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 1058 | sband = local->hw.wiphy->bands[band]; |
1025 | 1059 | ||
1026 | mask = params->sta_flags_mask; | 1060 | mask = params->sta_flags_mask; |
1027 | set = params->sta_flags_set; | 1061 | set = params->sta_flags_set; |
@@ -1136,7 +1170,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1136 | rates |= BIT(j); | 1170 | rates |= BIT(j); |
1137 | } | 1171 | } |
1138 | } | 1172 | } |
1139 | sta->sta.supp_rates[local->oper_channel->band] = rates; | 1173 | sta->sta.supp_rates[band] = rates; |
1140 | } | 1174 | } |
1141 | 1175 | ||
1142 | if (params->ht_capa) | 1176 | if (params->ht_capa) |
@@ -1144,6 +1178,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1144 | params->ht_capa, | 1178 | params->ht_capa, |
1145 | &sta->sta.ht_cap); | 1179 | &sta->sta.ht_cap); |
1146 | 1180 | ||
1181 | if (params->vht_capa) | ||
1182 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | ||
1183 | params->vht_capa, | ||
1184 | &sta->sta.vht_cap); | ||
1185 | |||
1147 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1186 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1148 | #ifdef CONFIG_MAC80211_MESH | 1187 | #ifdef CONFIG_MAC80211_MESH |
1149 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) | 1188 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) |
@@ -1664,8 +1703,13 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1664 | if (err) | 1703 | if (err) |
1665 | return err; | 1704 | return err; |
1666 | 1705 | ||
1667 | err = ieee80211_set_channel(wiphy, dev, setup->channel, | 1706 | /* can mesh use other SMPS modes? */ |
1668 | setup->channel_type); | 1707 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
1708 | sdata->needed_rx_chains = sdata->local->rx_chains; | ||
1709 | |||
1710 | err = ieee80211_vif_use_channel(sdata, setup->channel, | ||
1711 | setup->channel_type, | ||
1712 | IEEE80211_CHANCTX_SHARED); | ||
1669 | if (err) | 1713 | if (err) |
1670 | return err; | 1714 | return err; |
1671 | 1715 | ||
@@ -1679,6 +1723,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); | 1723 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1680 | 1724 | ||
1681 | ieee80211_stop_mesh(sdata); | 1725 | ieee80211_stop_mesh(sdata); |
1726 | ieee80211_vif_release_channel(sdata); | ||
1682 | 1727 | ||
1683 | return 0; | 1728 | return 0; |
1684 | } | 1729 | } |
@@ -1688,10 +1733,14 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1688 | struct net_device *dev, | 1733 | struct net_device *dev, |
1689 | struct bss_parameters *params) | 1734 | struct bss_parameters *params) |
1690 | { | 1735 | { |
1691 | struct ieee80211_sub_if_data *sdata; | 1736 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1737 | enum ieee80211_band band; | ||
1692 | u32 changed = 0; | 1738 | u32 changed = 0; |
1693 | 1739 | ||
1694 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1740 | if (!rtnl_dereference(sdata->u.ap.beacon)) |
1741 | return -ENOENT; | ||
1742 | |||
1743 | band = ieee80211_get_sdata_band(sdata); | ||
1695 | 1744 | ||
1696 | if (params->use_cts_prot >= 0) { | 1745 | if (params->use_cts_prot >= 0) { |
1697 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; | 1746 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
@@ -1704,7 +1753,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1704 | } | 1753 | } |
1705 | 1754 | ||
1706 | if (!sdata->vif.bss_conf.use_short_slot && | 1755 | if (!sdata->vif.bss_conf.use_short_slot && |
1707 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { | 1756 | band == IEEE80211_BAND_5GHZ) { |
1708 | sdata->vif.bss_conf.use_short_slot = true; | 1757 | sdata->vif.bss_conf.use_short_slot = true; |
1709 | changed |= BSS_CHANGED_ERP_SLOT; | 1758 | changed |= BSS_CHANGED_ERP_SLOT; |
1710 | } | 1759 | } |
@@ -1718,9 +1767,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1718 | if (params->basic_rates) { | 1767 | if (params->basic_rates) { |
1719 | int i, j; | 1768 | int i, j; |
1720 | u32 rates = 0; | 1769 | u32 rates = 0; |
1721 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1770 | struct ieee80211_supported_band *sband = wiphy->bands[band]; |
1722 | struct ieee80211_supported_band *sband = | ||
1723 | wiphy->bands[local->oper_channel->band]; | ||
1724 | 1771 | ||
1725 | for (i = 0; i < params->basic_rates_len; i++) { | 1772 | for (i = 0; i < params->basic_rates_len; i++) { |
1726 | int rate = (params->basic_rates[i] & 0x7f) * 5; | 1773 | int rate = (params->basic_rates[i] & 0x7f) * 5; |
@@ -1829,7 +1876,16 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1829 | * beaconing hasn't been configured yet | 1876 | * beaconing hasn't been configured yet |
1830 | */ | 1877 | */ |
1831 | case NL80211_IFTYPE_AP: | 1878 | case NL80211_IFTYPE_AP: |
1832 | if (sdata->u.ap.beacon) | 1879 | /* |
1880 | * If the scan has been forced (and the driver supports | ||
1881 | * forcing), don't care about being beaconing already. | ||
1882 | * This will create problems to the attached stations (e.g. all | ||
1883 | * the frames sent while scanning on other channel will be | ||
1884 | * lost) | ||
1885 | */ | ||
1886 | if (sdata->u.ap.beacon && | ||
1887 | (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || | ||
1888 | !(req->flags & NL80211_SCAN_FLAG_AP))) | ||
1833 | return -EOPNOTSUPP; | 1889 | return -EOPNOTSUPP; |
1834 | break; | 1890 | break; |
1835 | default: | 1891 | default: |
@@ -1872,20 +1928,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | |||
1872 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, | 1928 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, |
1873 | struct cfg80211_assoc_request *req) | 1929 | struct cfg80211_assoc_request *req) |
1874 | { | 1930 | { |
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); | 1931 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); |
1890 | } | 1932 | } |
1891 | 1933 | ||
@@ -1904,30 +1946,22 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | |||
1904 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | 1946 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, |
1905 | struct cfg80211_ibss_params *params) | 1947 | struct cfg80211_ibss_params *params) |
1906 | { | 1948 | { |
1907 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1949 | 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 | } | 1950 | } |
1925 | 1951 | ||
1926 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | 1952 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) |
1927 | { | 1953 | { |
1954 | return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); | ||
1955 | } | ||
1956 | |||
1957 | static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, | ||
1958 | int rate[IEEE80211_NUM_BANDS]) | ||
1959 | { | ||
1928 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1960 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1929 | 1961 | ||
1930 | return ieee80211_ibss_leave(sdata); | 1962 | memcpy(sdata->vif.bss_conf.mcast_rate, rate, sizeof(rate)); |
1963 | |||
1964 | return 0; | ||
1931 | } | 1965 | } |
1932 | 1966 | ||
1933 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 1967 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
@@ -1968,41 +2002,65 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1968 | } | 2002 | } |
1969 | 2003 | ||
1970 | static int ieee80211_set_tx_power(struct wiphy *wiphy, | 2004 | static int ieee80211_set_tx_power(struct wiphy *wiphy, |
2005 | struct wireless_dev *wdev, | ||
1971 | enum nl80211_tx_power_setting type, int mbm) | 2006 | enum nl80211_tx_power_setting type, int mbm) |
1972 | { | 2007 | { |
1973 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2008 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1974 | struct ieee80211_channel *chan = local->oper_channel; | 2009 | struct ieee80211_sub_if_data *sdata; |
1975 | u32 changes = 0; | 2010 | |
2011 | if (wdev) { | ||
2012 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2013 | |||
2014 | switch (type) { | ||
2015 | case NL80211_TX_POWER_AUTOMATIC: | ||
2016 | sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL; | ||
2017 | break; | ||
2018 | case NL80211_TX_POWER_LIMITED: | ||
2019 | case NL80211_TX_POWER_FIXED: | ||
2020 | if (mbm < 0 || (mbm % 100)) | ||
2021 | return -EOPNOTSUPP; | ||
2022 | sdata->user_power_level = MBM_TO_DBM(mbm); | ||
2023 | break; | ||
2024 | } | ||
2025 | |||
2026 | ieee80211_recalc_txpower(sdata); | ||
2027 | |||
2028 | return 0; | ||
2029 | } | ||
1976 | 2030 | ||
1977 | switch (type) { | 2031 | switch (type) { |
1978 | case NL80211_TX_POWER_AUTOMATIC: | 2032 | case NL80211_TX_POWER_AUTOMATIC: |
1979 | local->user_power_level = -1; | 2033 | local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
1980 | break; | 2034 | break; |
1981 | case NL80211_TX_POWER_LIMITED: | 2035 | case NL80211_TX_POWER_LIMITED: |
1982 | if (mbm < 0 || (mbm % 100)) | ||
1983 | return -EOPNOTSUPP; | ||
1984 | local->user_power_level = MBM_TO_DBM(mbm); | ||
1985 | break; | ||
1986 | case NL80211_TX_POWER_FIXED: | 2036 | case NL80211_TX_POWER_FIXED: |
1987 | if (mbm < 0 || (mbm % 100)) | 2037 | if (mbm < 0 || (mbm % 100)) |
1988 | return -EOPNOTSUPP; | 2038 | return -EOPNOTSUPP; |
1989 | /* TODO: move to cfg80211 when it knows the channel */ | ||
1990 | if (MBM_TO_DBM(mbm) > chan->max_power) | ||
1991 | return -EINVAL; | ||
1992 | local->user_power_level = MBM_TO_DBM(mbm); | 2039 | local->user_power_level = MBM_TO_DBM(mbm); |
1993 | break; | 2040 | break; |
1994 | } | 2041 | } |
1995 | 2042 | ||
1996 | ieee80211_hw_config(local, changes); | 2043 | mutex_lock(&local->iflist_mtx); |
2044 | list_for_each_entry(sdata, &local->interfaces, list) | ||
2045 | sdata->user_power_level = local->user_power_level; | ||
2046 | list_for_each_entry(sdata, &local->interfaces, list) | ||
2047 | ieee80211_recalc_txpower(sdata); | ||
2048 | mutex_unlock(&local->iflist_mtx); | ||
1997 | 2049 | ||
1998 | return 0; | 2050 | return 0; |
1999 | } | 2051 | } |
2000 | 2052 | ||
2001 | static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm) | 2053 | static int ieee80211_get_tx_power(struct wiphy *wiphy, |
2054 | struct wireless_dev *wdev, | ||
2055 | int *dbm) | ||
2002 | { | 2056 | { |
2003 | struct ieee80211_local *local = wiphy_priv(wiphy); | 2057 | struct ieee80211_local *local = wiphy_priv(wiphy); |
2058 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | ||
2004 | 2059 | ||
2005 | *dbm = local->hw.conf.power_level; | 2060 | if (!local->use_chanctx) |
2061 | *dbm = local->hw.conf.power_level; | ||
2062 | else | ||
2063 | *dbm = sdata->vif.bss_conf.txpower; | ||
2006 | 2064 | ||
2007 | return 0; | 2065 | return 0; |
2008 | } | 2066 | } |
@@ -2067,13 +2125,12 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2067 | 2125 | ||
2068 | /* | 2126 | /* |
2069 | * If not associated, or current association is not an HT | 2127 | * If not associated, or current association is not an HT |
2070 | * association, there's no need to send an action frame. | 2128 | * association, there's no need to do anything, just store |
2129 | * the new value until we associate. | ||
2071 | */ | 2130 | */ |
2072 | if (!sdata->u.mgd.associated || | 2131 | if (!sdata->u.mgd.associated || |
2073 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 2132 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
2074 | ieee80211_recalc_smps(sdata->local); | ||
2075 | return 0; | 2133 | return 0; |
2076 | } | ||
2077 | 2134 | ||
2078 | ap = sdata->u.mgd.associated->bssid; | 2135 | ap = sdata->u.mgd.associated->bssid; |
2079 | 2136 | ||
@@ -2189,6 +2246,9 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2189 | 2246 | ||
2190 | lockdep_assert_held(&local->mtx); | 2247 | lockdep_assert_held(&local->mtx); |
2191 | 2248 | ||
2249 | if (local->use_chanctx && !local->ops->remain_on_channel) | ||
2250 | return -EOPNOTSUPP; | ||
2251 | |||
2192 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); | 2252 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); |
2193 | if (!roc) | 2253 | if (!roc) |
2194 | return -ENOMEM; | 2254 | return -ENOMEM; |
@@ -2332,13 +2392,22 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2332 | list_add_tail(&roc->list, &local->roc_list); | 2392 | list_add_tail(&roc->list, &local->roc_list); |
2333 | 2393 | ||
2334 | /* | 2394 | /* |
2335 | * cookie is either the roc (for normal roc) | 2395 | * cookie is either the roc cookie (for normal roc) |
2336 | * or the SKB (for mgmt TX) | 2396 | * or the SKB (for mgmt TX) |
2337 | */ | 2397 | */ |
2338 | if (txskb) | 2398 | if (!txskb) { |
2399 | /* local->mtx protects this */ | ||
2400 | local->roc_cookie_counter++; | ||
2401 | roc->cookie = local->roc_cookie_counter; | ||
2402 | /* wow, you wrapped 64 bits ... more likely a bug */ | ||
2403 | if (WARN_ON(roc->cookie == 0)) { | ||
2404 | roc->cookie = 1; | ||
2405 | local->roc_cookie_counter++; | ||
2406 | } | ||
2407 | *cookie = roc->cookie; | ||
2408 | } else { | ||
2339 | *cookie = (unsigned long)txskb; | 2409 | *cookie = (unsigned long)txskb; |
2340 | else | 2410 | } |
2341 | *cookie = (unsigned long)roc; | ||
2342 | 2411 | ||
2343 | return 0; | 2412 | return 0; |
2344 | } | 2413 | } |
@@ -2373,7 +2442,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2373 | struct ieee80211_roc_work *dep, *tmp2; | 2442 | struct ieee80211_roc_work *dep, *tmp2; |
2374 | 2443 | ||
2375 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { | 2444 | list_for_each_entry_safe(dep, tmp2, &roc->dependents, list) { |
2376 | if (!mgmt_tx && (unsigned long)dep != cookie) | 2445 | if (!mgmt_tx && dep->cookie != cookie) |
2377 | continue; | 2446 | continue; |
2378 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) | 2447 | else if (mgmt_tx && dep->mgmt_tx_cookie != cookie) |
2379 | continue; | 2448 | continue; |
@@ -2385,7 +2454,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local, | |||
2385 | return 0; | 2454 | return 0; |
2386 | } | 2455 | } |
2387 | 2456 | ||
2388 | if (!mgmt_tx && (unsigned long)roc != cookie) | 2457 | if (!mgmt_tx && roc->cookie != cookie) |
2389 | continue; | 2458 | continue; |
2390 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) | 2459 | else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) |
2391 | continue; | 2460 | continue; |
@@ -2515,10 +2584,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2515 | 2584 | ||
2516 | /* Check if the operating channel is the requested channel */ | 2585 | /* Check if the operating channel is the requested channel */ |
2517 | if (!need_offchan) { | 2586 | if (!need_offchan) { |
2518 | need_offchan = chan != local->oper_channel; | 2587 | struct ieee80211_chanctx_conf *chanctx_conf; |
2519 | if (channel_type_valid && | 2588 | |
2520 | channel_type != local->_oper_channel_type) | 2589 | rcu_read_lock(); |
2590 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
2591 | |||
2592 | if (chanctx_conf) { | ||
2593 | need_offchan = chan != chanctx_conf->channel; | ||
2594 | if (channel_type_valid && | ||
2595 | channel_type != chanctx_conf->channel_type) | ||
2596 | need_offchan = true; | ||
2597 | } else { | ||
2521 | need_offchan = true; | 2598 | need_offchan = true; |
2599 | } | ||
2600 | rcu_read_unlock(); | ||
2522 | } | 2601 | } |
2523 | 2602 | ||
2524 | if (need_offchan && !offchan) { | 2603 | if (need_offchan && !offchan) { |
@@ -2594,6 +2673,9 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | |||
2594 | else | 2673 | else |
2595 | local->probe_req_reg--; | 2674 | local->probe_req_reg--; |
2596 | 2675 | ||
2676 | if (!local->open_count) | ||
2677 | break; | ||
2678 | |||
2597 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | 2679 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); |
2598 | break; | 2680 | break; |
2599 | default: | 2681 | default: |
@@ -2667,7 +2749,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | |||
2667 | u16 capab; | 2749 | u16 capab; |
2668 | 2750 | ||
2669 | capab = 0; | 2751 | capab = 0; |
2670 | if (local->oper_channel->band != IEEE80211_BAND_2GHZ) | 2752 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) |
2671 | return capab; | 2753 | return capab; |
2672 | 2754 | ||
2673 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | 2755 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) |
@@ -2699,7 +2781,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2699 | u16 status_code, struct sk_buff *skb) | 2781 | u16 status_code, struct sk_buff *skb) |
2700 | { | 2782 | { |
2701 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2783 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2702 | struct ieee80211_local *local = sdata->local; | 2784 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
2703 | struct ieee80211_tdls_data *tf; | 2785 | struct ieee80211_tdls_data *tf; |
2704 | 2786 | ||
2705 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2787 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2719,10 +2801,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2719 | tf->u.setup_req.capability = | 2801 | tf->u.setup_req.capability = |
2720 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2802 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2721 | 2803 | ||
2722 | ieee80211_add_srates_ie(sdata, skb, false, | 2804 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2723 | local->oper_channel->band); | 2805 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2724 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2725 | local->oper_channel->band); | ||
2726 | ieee80211_tdls_add_ext_capab(skb); | 2806 | ieee80211_tdls_add_ext_capab(skb); |
2727 | break; | 2807 | break; |
2728 | case WLAN_TDLS_SETUP_RESPONSE: | 2808 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2735,10 +2815,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2735 | tf->u.setup_resp.capability = | 2815 | tf->u.setup_resp.capability = |
2736 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2816 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2737 | 2817 | ||
2738 | ieee80211_add_srates_ie(sdata, skb, false, | 2818 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2739 | local->oper_channel->band); | 2819 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2740 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2741 | local->oper_channel->band); | ||
2742 | ieee80211_tdls_add_ext_capab(skb); | 2820 | ieee80211_tdls_add_ext_capab(skb); |
2743 | break; | 2821 | break; |
2744 | case WLAN_TDLS_SETUP_CONFIRM: | 2822 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2776,7 +2854,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2776 | u16 status_code, struct sk_buff *skb) | 2854 | u16 status_code, struct sk_buff *skb) |
2777 | { | 2855 | { |
2778 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2856 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2779 | struct ieee80211_local *local = sdata->local; | 2857 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
2780 | struct ieee80211_mgmt *mgmt; | 2858 | struct ieee80211_mgmt *mgmt; |
2781 | 2859 | ||
2782 | mgmt = (void *)skb_put(skb, 24); | 2860 | mgmt = (void *)skb_put(skb, 24); |
@@ -2799,10 +2877,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2799 | mgmt->u.action.u.tdls_discover_resp.capability = | 2877 | mgmt->u.action.u.tdls_discover_resp.capability = |
2800 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2878 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2801 | 2879 | ||
2802 | ieee80211_add_srates_ie(sdata, skb, false, | 2880 | ieee80211_add_srates_ie(sdata, skb, false, band); |
2803 | local->oper_channel->band); | 2881 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); |
2804 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2805 | local->oper_channel->band); | ||
2806 | ieee80211_tdls_add_ext_capab(skb); | 2882 | ieee80211_tdls_add_ext_capab(skb); |
2807 | break; | 2883 | break; |
2808 | default: | 2884 | default: |
@@ -2819,7 +2895,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2819 | { | 2895 | { |
2820 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2896 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2821 | struct ieee80211_local *local = sdata->local; | 2897 | struct ieee80211_local *local = sdata->local; |
2822 | struct ieee80211_tx_info *info; | ||
2823 | struct sk_buff *skb = NULL; | 2898 | struct sk_buff *skb = NULL; |
2824 | bool send_direct; | 2899 | bool send_direct; |
2825 | int ret; | 2900 | int ret; |
@@ -2845,7 +2920,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2845 | if (!skb) | 2920 | if (!skb) |
2846 | return -ENOMEM; | 2921 | return -ENOMEM; |
2847 | 2922 | ||
2848 | info = IEEE80211_SKB_CB(skb); | ||
2849 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2923 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2850 | 2924 | ||
2851 | switch (action_code) { | 2925 | switch (action_code) { |
@@ -2982,12 +3056,19 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
2982 | bool qos; | 3056 | bool qos; |
2983 | struct ieee80211_tx_info *info; | 3057 | struct ieee80211_tx_info *info; |
2984 | struct sta_info *sta; | 3058 | struct sta_info *sta; |
3059 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3060 | enum ieee80211_band band; | ||
2985 | 3061 | ||
2986 | rcu_read_lock(); | 3062 | rcu_read_lock(); |
3063 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3064 | if (WARN_ON(!chanctx_conf)) { | ||
3065 | rcu_read_unlock(); | ||
3066 | return -EINVAL; | ||
3067 | } | ||
3068 | band = chanctx_conf->channel->band; | ||
2987 | sta = sta_info_get(sdata, peer); | 3069 | sta = sta_info_get(sdata, peer); |
2988 | if (sta) { | 3070 | if (sta) { |
2989 | qos = test_sta_flag(sta, WLAN_STA_WME); | 3071 | qos = test_sta_flag(sta, WLAN_STA_WME); |
2990 | rcu_read_unlock(); | ||
2991 | } else { | 3072 | } else { |
2992 | rcu_read_unlock(); | 3073 | rcu_read_unlock(); |
2993 | return -ENOLINK; | 3074 | return -ENOLINK; |
@@ -3005,8 +3086,10 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3005 | } | 3086 | } |
3006 | 3087 | ||
3007 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); | 3088 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); |
3008 | if (!skb) | 3089 | if (!skb) { |
3090 | rcu_read_unlock(); | ||
3009 | return -ENOMEM; | 3091 | return -ENOMEM; |
3092 | } | ||
3010 | 3093 | ||
3011 | skb->dev = dev; | 3094 | skb->dev = dev; |
3012 | 3095 | ||
@@ -3031,8 +3114,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3031 | nullfunc->qos_ctrl = cpu_to_le16(7); | 3114 | nullfunc->qos_ctrl = cpu_to_le16(7); |
3032 | 3115 | ||
3033 | local_bh_disable(); | 3116 | local_bh_disable(); |
3034 | ieee80211_xmit(sdata, skb); | 3117 | ieee80211_xmit(sdata, skb, band); |
3035 | local_bh_enable(); | 3118 | local_bh_enable(); |
3119 | rcu_read_unlock(); | ||
3036 | 3120 | ||
3037 | *cookie = (unsigned long) skb; | 3121 | *cookie = (unsigned long) skb; |
3038 | return 0; | 3122 | return 0; |
@@ -3042,10 +3126,19 @@ static struct ieee80211_channel * | |||
3042 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | 3126 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, |
3043 | enum nl80211_channel_type *type) | 3127 | enum nl80211_channel_type *type) |
3044 | { | 3128 | { |
3045 | struct ieee80211_local *local = wiphy_priv(wiphy); | 3129 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3130 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3131 | struct ieee80211_channel *chan = NULL; | ||
3132 | |||
3133 | rcu_read_lock(); | ||
3134 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3135 | if (chanctx_conf) { | ||
3136 | *type = chanctx_conf->channel_type; | ||
3137 | chan = chanctx_conf->channel; | ||
3138 | } | ||
3139 | rcu_read_unlock(); | ||
3046 | 3140 | ||
3047 | *type = local->_oper_channel_type; | 3141 | return chan; |
3048 | return local->oper_channel; | ||
3049 | } | 3142 | } |
3050 | 3143 | ||
3051 | #ifdef CONFIG_PM | 3144 | #ifdef CONFIG_PM |
@@ -3100,6 +3193,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3100 | .disassoc = ieee80211_disassoc, | 3193 | .disassoc = ieee80211_disassoc, |
3101 | .join_ibss = ieee80211_join_ibss, | 3194 | .join_ibss = ieee80211_join_ibss, |
3102 | .leave_ibss = ieee80211_leave_ibss, | 3195 | .leave_ibss = ieee80211_leave_ibss, |
3196 | .set_mcast_rate = ieee80211_set_mcast_rate, | ||
3103 | .set_wiphy_params = ieee80211_set_wiphy_params, | 3197 | .set_wiphy_params = ieee80211_set_wiphy_params, |
3104 | .set_tx_power = ieee80211_set_tx_power, | 3198 | .set_tx_power = ieee80211_set_tx_power, |
3105 | .get_tx_power = ieee80211_get_tx_power, | 3199 | .get_tx_power = ieee80211_get_tx_power, |