aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c156
1 files changed, 89 insertions, 67 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 3345401be1b3..31a8afaf7332 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -830,16 +830,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
830 qos_info = 0; 830 qos_info = 0;
831 } 831 }
832 832
833 pos = skb_put(skb, 9); 833 pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info);
834 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
835 *pos++ = 7; /* len */
836 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
837 *pos++ = 0x50;
838 *pos++ = 0xf2;
839 *pos++ = 2; /* WME */
840 *pos++ = 0; /* WME info */
841 *pos++ = 1; /* WME ver */
842 *pos++ = qos_info;
843 } 834 }
844 835
845 /* add any remaining custom (i.e. vendor specific here) IEs */ 836 /* add any remaining custom (i.e. vendor specific here) IEs */
@@ -940,58 +931,77 @@ static void ieee80211_chswitch_work(struct work_struct *work)
940 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); 931 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
941 struct ieee80211_local *local = sdata->local; 932 struct ieee80211_local *local = sdata->local;
942 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 933 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
943 u32 changed = 0;
944 int ret; 934 int ret;
945 935
946 if (!ieee80211_sdata_running(sdata)) 936 if (!ieee80211_sdata_running(sdata))
947 return; 937 return;
948 938
949 sdata_lock(sdata); 939 sdata_lock(sdata);
940 mutex_lock(&local->mtx);
941 mutex_lock(&local->chanctx_mtx);
942
950 if (!ifmgd->associated) 943 if (!ifmgd->associated)
951 goto out; 944 goto out;
952 945
953 mutex_lock(&local->mtx); 946 if (!sdata->vif.csa_active)
954 ret = ieee80211_vif_change_channel(sdata, &changed); 947 goto out;
955 mutex_unlock(&local->mtx); 948
956 if (ret) { 949 /*
950 * using reservation isn't immediate as it may be deferred until later
951 * with multi-vif. once reservation is complete it will re-schedule the
952 * work with no reserved_chanctx so verify chandef to check if it
953 * completed successfully
954 */
955
956 if (sdata->reserved_chanctx) {
957 /*
958 * with multi-vif csa driver may call ieee80211_csa_finish()
959 * many times while waiting for other interfaces to use their
960 * reservations
961 */
962 if (sdata->reserved_ready)
963 goto out;
964
965 ret = ieee80211_vif_use_reserved_context(sdata);
966 if (ret) {
967 sdata_info(sdata,
968 "failed to use reserved channel context, disconnecting (err=%d)\n",
969 ret);
970 ieee80211_queue_work(&sdata->local->hw,
971 &ifmgd->csa_connection_drop_work);
972 goto out;
973 }
974
975 goto out;
976 }
977
978 if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
979 &sdata->csa_chandef)) {
957 sdata_info(sdata, 980 sdata_info(sdata,
958 "vif channel switch failed, disconnecting\n"); 981 "failed to finalize channel switch, disconnecting\n");
959 ieee80211_queue_work(&sdata->local->hw, 982 ieee80211_queue_work(&sdata->local->hw,
960 &ifmgd->csa_connection_drop_work); 983 &ifmgd->csa_connection_drop_work);
961 goto out; 984 goto out;
962 } 985 }
963 986
964 if (!local->use_chanctx) {
965 local->_oper_chandef = sdata->csa_chandef;
966 /* Call "hw_config" only if doing sw channel switch.
967 * Otherwise update the channel directly
968 */
969 if (!local->ops->channel_switch)
970 ieee80211_hw_config(local, 0);
971 else
972 local->hw.conf.chandef = local->_oper_chandef;
973 }
974
975 /* XXX: shouldn't really modify cfg80211-owned data! */ 987 /* XXX: shouldn't really modify cfg80211-owned data! */
976 ifmgd->associated->channel = sdata->csa_chandef.chan; 988 ifmgd->associated->channel = sdata->csa_chandef.chan;
977 989
978 ieee80211_bss_info_change_notify(sdata, changed);
979
980 mutex_lock(&local->mtx);
981 sdata->vif.csa_active = false; 990 sdata->vif.csa_active = false;
982 /* XXX: wait for a beacon first? */
983 if (!ieee80211_csa_needs_block_tx(local))
984 ieee80211_wake_queues_by_reason(&local->hw,
985 IEEE80211_MAX_QUEUE_MAP,
986 IEEE80211_QUEUE_STOP_REASON_CSA);
987 mutex_unlock(&local->mtx);
988 991
989 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; 992 /* XXX: wait for a beacon first? */
993 if (sdata->csa_block_tx) {
994 ieee80211_wake_vif_queues(local, sdata,
995 IEEE80211_QUEUE_STOP_REASON_CSA);
996 sdata->csa_block_tx = false;
997 }
990 998
991 ieee80211_sta_reset_beacon_monitor(sdata); 999 ieee80211_sta_reset_beacon_monitor(sdata);
992 ieee80211_sta_reset_conn_monitor(sdata); 1000 ieee80211_sta_reset_conn_monitor(sdata);
993 1001
994out: 1002out:
1003 mutex_unlock(&local->chanctx_mtx);
1004 mutex_unlock(&local->mtx);
995 sdata_unlock(sdata); 1005 sdata_unlock(sdata);
996} 1006}
997 1007
@@ -1028,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1028 struct ieee80211_local *local = sdata->local; 1038 struct ieee80211_local *local = sdata->local;
1029 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1030 struct cfg80211_bss *cbss = ifmgd->associated; 1040 struct cfg80211_bss *cbss = ifmgd->associated;
1041 struct ieee80211_chanctx_conf *conf;
1031 struct ieee80211_chanctx *chanctx; 1042 struct ieee80211_chanctx *chanctx;
1032 enum ieee80211_band current_band; 1043 enum ieee80211_band current_band;
1033 struct ieee80211_csa_ie csa_ie; 1044 struct ieee80211_csa_ie csa_ie;
@@ -1042,7 +1053,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1042 return; 1053 return;
1043 1054
1044 /* disregard subsequent announcements if we are already processing */ 1055 /* disregard subsequent announcements if we are already processing */
1045 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) 1056 if (sdata->vif.csa_active)
1046 return; 1057 return;
1047 1058
1048 current_band = cbss->channel->band; 1059 current_band = cbss->channel->band;
@@ -1069,9 +1080,22 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1069 return; 1080 return;
1070 } 1081 }
1071 1082
1072 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; 1083 mutex_lock(&local->mtx);
1073
1074 mutex_lock(&local->chanctx_mtx); 1084 mutex_lock(&local->chanctx_mtx);
1085 conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
1086 lockdep_is_held(&local->chanctx_mtx));
1087 if (!conf) {
1088 sdata_info(sdata,
1089 "no channel context assigned to vif?, disconnecting\n");
1090 ieee80211_queue_work(&local->hw,
1091 &ifmgd->csa_connection_drop_work);
1092 mutex_unlock(&local->chanctx_mtx);
1093 mutex_unlock(&local->mtx);
1094 return;
1095 }
1096
1097 chanctx = container_of(conf, struct ieee80211_chanctx, conf);
1098
1075 if (local->use_chanctx) { 1099 if (local->use_chanctx) {
1076 u32 num_chanctx = 0; 1100 u32 num_chanctx = 0;
1077 list_for_each_entry(chanctx, &local->chanctx_list, list) 1101 list_for_each_entry(chanctx, &local->chanctx_list, list)
@@ -1084,38 +1108,32 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1084 ieee80211_queue_work(&local->hw, 1108 ieee80211_queue_work(&local->hw,
1085 &ifmgd->csa_connection_drop_work); 1109 &ifmgd->csa_connection_drop_work);
1086 mutex_unlock(&local->chanctx_mtx); 1110 mutex_unlock(&local->chanctx_mtx);
1111 mutex_unlock(&local->mtx);
1087 return; 1112 return;
1088 } 1113 }
1089 } 1114 }
1090 1115
1091 if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { 1116 res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
1092 ieee80211_queue_work(&local->hw, 1117 chanctx->mode, false);
1093 &ifmgd->csa_connection_drop_work); 1118 if (res) {
1094 mutex_unlock(&local->chanctx_mtx);
1095 return;
1096 }
1097 chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
1098 struct ieee80211_chanctx, conf);
1099 if (ieee80211_chanctx_refcount(local, chanctx) > 1) {
1100 sdata_info(sdata, 1119 sdata_info(sdata,
1101 "channel switch with multiple interfaces on the same channel, disconnecting\n"); 1120 "failed to reserve channel context for channel switch, disconnecting (err=%d)\n",
1121 res);
1102 ieee80211_queue_work(&local->hw, 1122 ieee80211_queue_work(&local->hw,
1103 &ifmgd->csa_connection_drop_work); 1123 &ifmgd->csa_connection_drop_work);
1104 mutex_unlock(&local->chanctx_mtx); 1124 mutex_unlock(&local->chanctx_mtx);
1125 mutex_unlock(&local->mtx);
1105 return; 1126 return;
1106 } 1127 }
1107 mutex_unlock(&local->chanctx_mtx); 1128 mutex_unlock(&local->chanctx_mtx);
1108 1129
1109 sdata->csa_chandef = csa_ie.chandef;
1110
1111 mutex_lock(&local->mtx);
1112 sdata->vif.csa_active = true; 1130 sdata->vif.csa_active = true;
1131 sdata->csa_chandef = csa_ie.chandef;
1113 sdata->csa_block_tx = csa_ie.mode; 1132 sdata->csa_block_tx = csa_ie.mode;
1114 1133
1115 if (sdata->csa_block_tx) 1134 if (sdata->csa_block_tx)
1116 ieee80211_stop_queues_by_reason(&local->hw, 1135 ieee80211_stop_vif_queues(local, sdata,
1117 IEEE80211_MAX_QUEUE_MAP, 1136 IEEE80211_QUEUE_STOP_REASON_CSA);
1118 IEEE80211_QUEUE_STOP_REASON_CSA);
1119 mutex_unlock(&local->mtx); 1137 mutex_unlock(&local->mtx);
1120 1138
1121 if (local->ops->channel_switch) { 1139 if (local->ops->channel_switch) {
@@ -1385,7 +1403,8 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
1385 1403
1386 ieee80211_wake_queues_by_reason(&local->hw, 1404 ieee80211_wake_queues_by_reason(&local->hw,
1387 IEEE80211_MAX_QUEUE_MAP, 1405 IEEE80211_MAX_QUEUE_MAP,
1388 IEEE80211_QUEUE_STOP_REASON_PS); 1406 IEEE80211_QUEUE_STOP_REASON_PS,
1407 false);
1389} 1408}
1390 1409
1391void ieee80211_dynamic_ps_enable_work(struct work_struct *work) 1410void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
@@ -1830,10 +1849,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1830 ieee80211_vif_release_channel(sdata); 1849 ieee80211_vif_release_channel(sdata);
1831 1850
1832 sdata->vif.csa_active = false; 1851 sdata->vif.csa_active = false;
1833 if (!ieee80211_csa_needs_block_tx(local)) 1852 if (sdata->csa_block_tx) {
1834 ieee80211_wake_queues_by_reason(&local->hw, 1853 ieee80211_wake_vif_queues(local, sdata,
1835 IEEE80211_MAX_QUEUE_MAP, 1854 IEEE80211_QUEUE_STOP_REASON_CSA);
1836 IEEE80211_QUEUE_STOP_REASON_CSA); 1855 sdata->csa_block_tx = false;
1856 }
1837 mutex_unlock(&local->mtx); 1857 mutex_unlock(&local->mtx);
1838 1858
1839 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; 1859 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
@@ -2075,14 +2095,13 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2075 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 2095 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
2076 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 2096 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
2077 true, frame_buf); 2097 true, frame_buf);
2078 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
2079
2080 mutex_lock(&local->mtx); 2098 mutex_lock(&local->mtx);
2081 sdata->vif.csa_active = false; 2099 sdata->vif.csa_active = false;
2082 if (!ieee80211_csa_needs_block_tx(local)) 2100 if (sdata->csa_block_tx) {
2083 ieee80211_wake_queues_by_reason(&local->hw, 2101 ieee80211_wake_vif_queues(local, sdata,
2084 IEEE80211_MAX_QUEUE_MAP, 2102 IEEE80211_QUEUE_STOP_REASON_CSA);
2085 IEEE80211_QUEUE_STOP_REASON_CSA); 2103 sdata->csa_block_tx = false;
2104 }
2086 mutex_unlock(&local->mtx); 2105 mutex_unlock(&local->mtx);
2087 2106
2088 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 2107 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
@@ -3688,6 +3707,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
3688 INIT_WORK(&ifmgd->csa_connection_drop_work, 3707 INIT_WORK(&ifmgd->csa_connection_drop_work,
3689 ieee80211_csa_connection_drop_work); 3708 ieee80211_csa_connection_drop_work);
3690 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); 3709 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
3710 INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
3711 ieee80211_tdls_peer_del_work);
3691 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 3712 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
3692 (unsigned long) sdata); 3713 (unsigned long) sdata);
3693 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 3714 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@ -4551,6 +4572,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
4551 cancel_work_sync(&ifmgd->request_smps_work); 4572 cancel_work_sync(&ifmgd->request_smps_work);
4552 cancel_work_sync(&ifmgd->csa_connection_drop_work); 4573 cancel_work_sync(&ifmgd->csa_connection_drop_work);
4553 cancel_work_sync(&ifmgd->chswitch_work); 4574 cancel_work_sync(&ifmgd->chswitch_work);
4575 cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);
4554 4576
4555 sdata_lock(sdata); 4577 sdata_lock(sdata);
4556 if (ifmgd->assoc_data) { 4578 if (ifmgd->assoc_data) {