diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 178 |
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 | ||
24 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, | 25 | static 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 | ||
1227 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1229 | static 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 | ||
1521 | static 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 | |||
1530 | static 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 | |||
1551 | static 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 | |||
1519 | static int ieee80211_get_mesh_config(struct wiphy *wiphy, | 1572 | static 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 | ||
2022 | static 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 | |||
2028 | static 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 | |||
1969 | static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev, | 2033 | static 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, ¶ms->chandef, | 3165 | err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->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 | ||
3604 | static 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 | |||
3630 | static 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 | |||
3524 | const struct cfg80211_ops mac80211_config_ops = { | 3674 | const 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 | }; |