aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c178
1 files changed, 167 insertions, 11 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 343da1e35025..06185940cbb6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -20,6 +20,7 @@
20#include "cfg.h" 20#include "cfg.h"
21#include "rate.h" 21#include "rate.h"
22#include "mesh.h" 22#include "mesh.h"
23#include "wme.h"
23 24
24static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, 25static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
25 const char *name, 26 const char *name,
@@ -190,7 +191,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
190 * receive the key. When wpa_supplicant has roamed 191 * receive the key. When wpa_supplicant has roamed
191 * using FT, it attempts to set the key before 192 * using FT, it attempts to set the key before
192 * association has completed, this rejects that attempt 193 * association has completed, this rejects that attempt
193 * so it will set the key again after assocation. 194 * so it will set the key again after association.
194 * 195 *
195 * TODO: accept the key if we have a station entry and 196 * TODO: accept the key if we have a station entry and
196 * add it to the device after the station. 197 * add it to the device after the station.
@@ -229,6 +230,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
229 case NUM_NL80211_IFTYPES: 230 case NUM_NL80211_IFTYPES:
230 case NL80211_IFTYPE_P2P_CLIENT: 231 case NL80211_IFTYPE_P2P_CLIENT:
231 case NL80211_IFTYPE_P2P_GO: 232 case NL80211_IFTYPE_P2P_GO:
233 case NL80211_IFTYPE_OCB:
232 /* shouldn't happen */ 234 /* shouldn't happen */
233 WARN_ON_ONCE(1); 235 WARN_ON_ONCE(1);
234 break; 236 break;
@@ -1225,14 +1227,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
1225} 1227}
1226 1228
1227static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, 1229static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
1228 const u8 *mac) 1230 struct station_del_parameters *params)
1229{ 1231{
1230 struct ieee80211_sub_if_data *sdata; 1232 struct ieee80211_sub_if_data *sdata;
1231 1233
1232 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1234 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1233 1235
1234 if (mac) 1236 if (params->mac)
1235 return sta_info_destroy_addr_bss(sdata, mac); 1237 return sta_info_destroy_addr_bss(sdata, params->mac);
1236 1238
1237 sta_info_flush(sdata); 1239 sta_info_flush(sdata);
1238 return 0; 1240 return 0;
@@ -1516,6 +1518,57 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
1516 return 0; 1518 return 0;
1517} 1519}
1518 1520
1521static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp,
1522 struct mpath_info *pinfo)
1523{
1524 memset(pinfo, 0, sizeof(*pinfo));
1525 memcpy(mpp, mpath->mpp, ETH_ALEN);
1526
1527 pinfo->generation = mpp_paths_generation;
1528}
1529
1530static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
1531 u8 *dst, u8 *mpp, struct mpath_info *pinfo)
1532
1533{
1534 struct ieee80211_sub_if_data *sdata;
1535 struct mesh_path *mpath;
1536
1537 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1538
1539 rcu_read_lock();
1540 mpath = mpp_path_lookup(sdata, dst);
1541 if (!mpath) {
1542 rcu_read_unlock();
1543 return -ENOENT;
1544 }
1545 memcpy(dst, mpath->dst, ETH_ALEN);
1546 mpp_set_pinfo(mpath, mpp, pinfo);
1547 rcu_read_unlock();
1548 return 0;
1549}
1550
1551static int ieee80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
1552 int idx, u8 *dst, u8 *mpp,
1553 struct mpath_info *pinfo)
1554{
1555 struct ieee80211_sub_if_data *sdata;
1556 struct mesh_path *mpath;
1557
1558 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1559
1560 rcu_read_lock();
1561 mpath = mpp_path_lookup_by_idx(sdata, idx);
1562 if (!mpath) {
1563 rcu_read_unlock();
1564 return -ENOENT;
1565 }
1566 memcpy(dst, mpath->dst, ETH_ALEN);
1567 mpp_set_pinfo(mpath, mpp, pinfo);
1568 rcu_read_unlock();
1569 return 0;
1570}
1571
1519static int ieee80211_get_mesh_config(struct wiphy *wiphy, 1572static int ieee80211_get_mesh_config(struct wiphy *wiphy,
1520 struct net_device *dev, 1573 struct net_device *dev,
1521 struct mesh_config *conf) 1574 struct mesh_config *conf)
@@ -1966,6 +2019,17 @@ static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1966 return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); 2019 return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
1967} 2020}
1968 2021
2022static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
2023 struct ocb_setup *setup)
2024{
2025 return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
2026}
2027
2028static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
2029{
2030 return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
2031}
2032
1969static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, 2033static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
1970 int rate[IEEE80211_NUM_BANDS]) 2034 int rate[IEEE80211_NUM_BANDS])
1971{ 2035{
@@ -2081,6 +2145,9 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy,
2081 struct ieee80211_local *local = wiphy_priv(wiphy); 2145 struct ieee80211_local *local = wiphy_priv(wiphy);
2082 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); 2146 struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
2083 2147
2148 if (local->ops->get_txpower)
2149 return drv_get_txpower(local, sdata, dbm);
2150
2084 if (!local->use_chanctx) 2151 if (!local->use_chanctx)
2085 *dbm = local->hw.conf.power_level; 2152 *dbm = local->hw.conf.power_level;
2086 else 2153 else
@@ -2850,11 +2917,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
2850 if (sdata->reserved_ready) 2917 if (sdata->reserved_ready)
2851 return 0; 2918 return 0;
2852 2919
2853 err = ieee80211_vif_use_reserved_context(sdata); 2920 return ieee80211_vif_use_reserved_context(sdata);
2854 if (err)
2855 return err;
2856
2857 return 0;
2858 } 2921 }
2859 2922
2860 if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef, 2923 if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
@@ -2868,7 +2931,6 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
2868 return err; 2931 return err;
2869 2932
2870 ieee80211_bss_info_change_notify(sdata, changed); 2933 ieee80211_bss_info_change_notify(sdata, changed);
2871 cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
2872 2934
2873 if (sdata->csa_block_tx) { 2935 if (sdata->csa_block_tx) {
2874 ieee80211_wake_vif_queues(local, sdata, 2936 ieee80211_wake_vif_queues(local, sdata,
@@ -2876,6 +2938,12 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
2876 sdata->csa_block_tx = false; 2938 sdata->csa_block_tx = false;
2877 } 2939 }
2878 2940
2941 err = drv_post_channel_switch(sdata);
2942 if (err)
2943 return err;
2944
2945 cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
2946
2879 return 0; 2947 return 0;
2880} 2948}
2881 2949
@@ -3053,9 +3121,11 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3053{ 3121{
3054 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3122 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3055 struct ieee80211_local *local = sdata->local; 3123 struct ieee80211_local *local = sdata->local;
3124 struct ieee80211_channel_switch ch_switch;
3056 struct ieee80211_chanctx_conf *conf; 3125 struct ieee80211_chanctx_conf *conf;
3057 struct ieee80211_chanctx *chanctx; 3126 struct ieee80211_chanctx *chanctx;
3058 int err, changed = 0; 3127 u32 changed = 0;
3128 int err;
3059 3129
3060 sdata_assert_lock(sdata); 3130 sdata_assert_lock(sdata);
3061 lockdep_assert_held(&local->mtx); 3131 lockdep_assert_held(&local->mtx);
@@ -3088,6 +3158,10 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3088 goto out; 3158 goto out;
3089 } 3159 }
3090 3160
3161 err = drv_pre_channel_switch(sdata, &ch_switch);
3162 if (err)
3163 goto out;
3164
3091 err = ieee80211_vif_reserve_chanctx(sdata, &params->chandef, 3165 err = ieee80211_vif_reserve_chanctx(sdata, &params->chandef,
3092 chanctx->mode, 3166 chanctx->mode,
3093 params->radar_required); 3167 params->radar_required);
@@ -3101,6 +3175,12 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3101 goto out; 3175 goto out;
3102 } 3176 }
3103 3177
3178 ch_switch.timestamp = 0;
3179 ch_switch.device_timestamp = 0;
3180 ch_switch.block_tx = params->block_tx;
3181 ch_switch.chandef = params->chandef;
3182 ch_switch.count = params->count;
3183
3104 err = ieee80211_set_csa_beacon(sdata, params, &changed); 3184 err = ieee80211_set_csa_beacon(sdata, params, &changed);
3105 if (err) { 3185 if (err) {
3106 ieee80211_vif_unreserve_chanctx(sdata); 3186 ieee80211_vif_unreserve_chanctx(sdata);
@@ -3521,6 +3601,76 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
3521 return ret; 3601 return ret;
3522} 3602}
3523 3603
3604static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev,
3605 u8 tsid, const u8 *peer, u8 up,
3606 u16 admitted_time)
3607{
3608 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3609 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3610 int ac = ieee802_1d_to_ac[up];
3611
3612 if (sdata->vif.type != NL80211_IFTYPE_STATION)
3613 return -EOPNOTSUPP;
3614
3615 if (!(sdata->wmm_acm & BIT(up)))
3616 return -EINVAL;
3617
3618 if (ifmgd->tx_tspec[ac].admitted_time)
3619 return -EBUSY;
3620
3621 if (admitted_time) {
3622 ifmgd->tx_tspec[ac].admitted_time = 32 * admitted_time;
3623 ifmgd->tx_tspec[ac].tsid = tsid;
3624 ifmgd->tx_tspec[ac].up = up;
3625 }
3626
3627 return 0;
3628}
3629
3630static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
3631 u8 tsid, const u8 *peer)
3632{
3633 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3634 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3635 struct ieee80211_local *local = wiphy_priv(wiphy);
3636 int ac;
3637
3638 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
3639 struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
3640
3641 /* skip unused entries */
3642 if (!tx_tspec->admitted_time)
3643 continue;
3644
3645 if (tx_tspec->tsid != tsid)
3646 continue;
3647
3648 /* due to this new packets will be reassigned to non-ACM ACs */
3649 tx_tspec->up = -1;
3650
3651 /* Make sure that all packets have been sent to avoid to
3652 * restore the QoS params on packets that are still on the
3653 * queues.
3654 */
3655 synchronize_net();
3656 ieee80211_flush_queues(local, sdata);
3657
3658 /* restore the normal QoS parameters
3659 * (unconditionally to avoid races)
3660 */
3661 tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
3662 tx_tspec->downgraded = false;
3663 ieee80211_sta_handle_tspec_ac_params(sdata);
3664
3665 /* finally clear all the data */
3666 memset(tx_tspec, 0, sizeof(*tx_tspec));
3667
3668 return 0;
3669 }
3670
3671 return -ENOENT;
3672}
3673
3524const struct cfg80211_ops mac80211_config_ops = { 3674const struct cfg80211_ops mac80211_config_ops = {
3525 .add_virtual_intf = ieee80211_add_iface, 3675 .add_virtual_intf = ieee80211_add_iface,
3526 .del_virtual_intf = ieee80211_del_iface, 3676 .del_virtual_intf = ieee80211_del_iface,
@@ -3547,11 +3697,15 @@ const struct cfg80211_ops mac80211_config_ops = {
3547 .change_mpath = ieee80211_change_mpath, 3697 .change_mpath = ieee80211_change_mpath,
3548 .get_mpath = ieee80211_get_mpath, 3698 .get_mpath = ieee80211_get_mpath,
3549 .dump_mpath = ieee80211_dump_mpath, 3699 .dump_mpath = ieee80211_dump_mpath,
3700 .get_mpp = ieee80211_get_mpp,
3701 .dump_mpp = ieee80211_dump_mpp,
3550 .update_mesh_config = ieee80211_update_mesh_config, 3702 .update_mesh_config = ieee80211_update_mesh_config,
3551 .get_mesh_config = ieee80211_get_mesh_config, 3703 .get_mesh_config = ieee80211_get_mesh_config,
3552 .join_mesh = ieee80211_join_mesh, 3704 .join_mesh = ieee80211_join_mesh,
3553 .leave_mesh = ieee80211_leave_mesh, 3705 .leave_mesh = ieee80211_leave_mesh,
3554#endif 3706#endif
3707 .join_ocb = ieee80211_join_ocb,
3708 .leave_ocb = ieee80211_leave_ocb,
3555 .change_bss = ieee80211_change_bss, 3709 .change_bss = ieee80211_change_bss,
3556 .set_txq_params = ieee80211_set_txq_params, 3710 .set_txq_params = ieee80211_set_txq_params,
3557 .set_monitor_channel = ieee80211_set_monitor_channel, 3711 .set_monitor_channel = ieee80211_set_monitor_channel,
@@ -3597,4 +3751,6 @@ const struct cfg80211_ops mac80211_config_ops = {
3597 .channel_switch = ieee80211_channel_switch, 3751 .channel_switch = ieee80211_channel_switch,
3598 .set_qos_map = ieee80211_set_qos_map, 3752 .set_qos_map = ieee80211_set_qos_map,
3599 .set_ap_chanwidth = ieee80211_set_ap_chanwidth, 3753 .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
3754 .add_tx_ts = ieee80211_add_tx_ts,
3755 .del_tx_ts = ieee80211_del_tx_ts,
3600}; 3756};