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.c281
1 files changed, 235 insertions, 46 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 93af0f1c9d99..0d166e766dad 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -775,11 +775,30 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
775 WLAN_EID_QOS_CAPA, 775 WLAN_EID_QOS_CAPA,
776 WLAN_EID_RRM_ENABLED_CAPABILITIES, 776 WLAN_EID_RRM_ENABLED_CAPABILITIES,
777 WLAN_EID_MOBILITY_DOMAIN, 777 WLAN_EID_MOBILITY_DOMAIN,
778 WLAN_EID_FAST_BSS_TRANSITION, /* reassoc only */
779 WLAN_EID_RIC_DATA, /* reassoc only */
778 WLAN_EID_SUPPORTED_REGULATORY_CLASSES, 780 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
779 }; 781 };
780 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, 782 static const u8 after_ric[] = {
781 before_ht, ARRAY_SIZE(before_ht), 783 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
782 offset); 784 WLAN_EID_HT_CAPABILITY,
785 WLAN_EID_BSS_COEX_2040,
786 WLAN_EID_EXT_CAPABILITY,
787 WLAN_EID_QOS_TRAFFIC_CAPA,
788 WLAN_EID_TIM_BCAST_REQ,
789 WLAN_EID_INTERWORKING,
790 /* 60GHz doesn't happen right now */
791 WLAN_EID_VHT_CAPABILITY,
792 WLAN_EID_OPMODE_NOTIF,
793 };
794
795 noffset = ieee80211_ie_split_ric(assoc_data->ie,
796 assoc_data->ie_len,
797 before_ht,
798 ARRAY_SIZE(before_ht),
799 after_ric,
800 ARRAY_SIZE(after_ric),
801 offset);
783 pos = skb_put(skb, noffset - offset); 802 pos = skb_put(skb, noffset - offset);
784 memcpy(pos, assoc_data->ie + offset, noffset - offset); 803 memcpy(pos, assoc_data->ie + offset, noffset - offset);
785 offset = noffset; 804 offset = noffset;
@@ -813,6 +832,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
813 WLAN_EID_TIM_BCAST_REQ, 832 WLAN_EID_TIM_BCAST_REQ,
814 WLAN_EID_INTERWORKING, 833 WLAN_EID_INTERWORKING,
815 }; 834 };
835
836 /* RIC already taken above, so no need to handle here anymore */
816 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, 837 noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
817 before_vht, ARRAY_SIZE(before_vht), 838 before_vht, ARRAY_SIZE(before_vht),
818 offset); 839 offset);
@@ -1001,14 +1022,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
1001 /* XXX: shouldn't really modify cfg80211-owned data! */ 1022 /* XXX: shouldn't really modify cfg80211-owned data! */
1002 ifmgd->associated->channel = sdata->csa_chandef.chan; 1023 ifmgd->associated->channel = sdata->csa_chandef.chan;
1003 1024
1004 sdata->vif.csa_active = false; 1025 ifmgd->csa_waiting_bcn = true;
1005
1006 /* XXX: wait for a beacon first? */
1007 if (sdata->csa_block_tx) {
1008 ieee80211_wake_vif_queues(local, sdata,
1009 IEEE80211_QUEUE_STOP_REASON_CSA);
1010 sdata->csa_block_tx = false;
1011 }
1012 1026
1013 ieee80211_sta_reset_beacon_monitor(sdata); 1027 ieee80211_sta_reset_beacon_monitor(sdata);
1014 ieee80211_sta_reset_conn_monitor(sdata); 1028 ieee80211_sta_reset_conn_monitor(sdata);
@@ -1019,6 +1033,35 @@ out:
1019 sdata_unlock(sdata); 1033 sdata_unlock(sdata);
1020} 1034}
1021 1035
1036static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
1037{
1038 struct ieee80211_local *local = sdata->local;
1039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1040 int ret;
1041
1042 sdata_assert_lock(sdata);
1043
1044 WARN_ON(!sdata->vif.csa_active);
1045
1046 if (sdata->csa_block_tx) {
1047 ieee80211_wake_vif_queues(local, sdata,
1048 IEEE80211_QUEUE_STOP_REASON_CSA);
1049 sdata->csa_block_tx = false;
1050 }
1051
1052 sdata->vif.csa_active = false;
1053 ifmgd->csa_waiting_bcn = false;
1054
1055 ret = drv_post_channel_switch(sdata);
1056 if (ret) {
1057 sdata_info(sdata,
1058 "driver post channel switch failed, disconnecting\n");
1059 ieee80211_queue_work(&local->hw,
1060 &ifmgd->csa_connection_drop_work);
1061 return;
1062 }
1063}
1064
1022void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success) 1065void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
1023{ 1066{
1024 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1067 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -1046,7 +1089,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
1046 1089
1047static void 1090static void
1048ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, 1091ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1049 u64 timestamp, struct ieee802_11_elems *elems, 1092 u64 timestamp, u32 device_timestamp,
1093 struct ieee802_11_elems *elems,
1050 bool beacon) 1094 bool beacon)
1051{ 1095{
1052 struct ieee80211_local *local = sdata->local; 1096 struct ieee80211_local *local = sdata->local;
@@ -1056,6 +1100,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1056 struct ieee80211_chanctx *chanctx; 1100 struct ieee80211_chanctx *chanctx;
1057 enum ieee80211_band current_band; 1101 enum ieee80211_band current_band;
1058 struct ieee80211_csa_ie csa_ie; 1102 struct ieee80211_csa_ie csa_ie;
1103 struct ieee80211_channel_switch ch_switch;
1059 int res; 1104 int res;
1060 1105
1061 sdata_assert_lock(sdata); 1106 sdata_assert_lock(sdata);
@@ -1110,21 +1155,31 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1110 1155
1111 chanctx = container_of(conf, struct ieee80211_chanctx, conf); 1156 chanctx = container_of(conf, struct ieee80211_chanctx, conf);
1112 1157
1113 if (local->use_chanctx) { 1158 if (local->use_chanctx &&
1114 u32 num_chanctx = 0; 1159 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
1115 list_for_each_entry(chanctx, &local->chanctx_list, list) 1160 sdata_info(sdata,
1116 num_chanctx++; 1161 "driver doesn't support chan-switch with channel contexts\n");
1162 ieee80211_queue_work(&local->hw,
1163 &ifmgd->csa_connection_drop_work);
1164 mutex_unlock(&local->chanctx_mtx);
1165 mutex_unlock(&local->mtx);
1166 return;
1167 }
1117 1168
1118 if (num_chanctx > 1 || 1169 ch_switch.timestamp = timestamp;
1119 !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) { 1170 ch_switch.device_timestamp = device_timestamp;
1120 sdata_info(sdata, 1171 ch_switch.block_tx = csa_ie.mode;
1121 "not handling chan-switch with channel contexts\n"); 1172 ch_switch.chandef = csa_ie.chandef;
1122 ieee80211_queue_work(&local->hw, 1173 ch_switch.count = csa_ie.count;
1123 &ifmgd->csa_connection_drop_work); 1174
1124 mutex_unlock(&local->chanctx_mtx); 1175 if (drv_pre_channel_switch(sdata, &ch_switch)) {
1125 mutex_unlock(&local->mtx); 1176 sdata_info(sdata,
1126 return; 1177 "preparing for channel switch failed, disconnecting\n");
1127 } 1178 ieee80211_queue_work(&local->hw,
1179 &ifmgd->csa_connection_drop_work);
1180 mutex_unlock(&local->chanctx_mtx);
1181 mutex_unlock(&local->mtx);
1182 return;
1128 } 1183 }
1129 1184
1130 res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef, 1185 res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
@@ -1152,14 +1207,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1152 1207
1153 if (local->ops->channel_switch) { 1208 if (local->ops->channel_switch) {
1154 /* use driver's channel switch callback */ 1209 /* use driver's channel switch callback */
1155 struct ieee80211_channel_switch ch_switch = { 1210 drv_channel_switch(local, sdata, &ch_switch);
1156 .timestamp = timestamp,
1157 .block_tx = csa_ie.mode,
1158 .chandef = csa_ie.chandef,
1159 .count = csa_ie.count,
1160 };
1161
1162 drv_channel_switch(local, &ch_switch);
1163 return; 1211 return;
1164 } 1212 }
1165 1213
@@ -1580,6 +1628,95 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
1580 mutex_unlock(&sdata->local->mtx); 1628 mutex_unlock(&sdata->local->mtx);
1581} 1629}
1582 1630
1631static bool
1632__ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
1633{
1634 struct ieee80211_local *local = sdata->local;
1635 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1636 bool ret;
1637 int ac;
1638
1639 if (local->hw.queues < IEEE80211_NUM_ACS)
1640 return false;
1641
1642 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
1643 struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
1644 int non_acm_ac;
1645 unsigned long now = jiffies;
1646
1647 if (tx_tspec->action == TX_TSPEC_ACTION_NONE &&
1648 tx_tspec->admitted_time &&
1649 time_after(now, tx_tspec->time_slice_start + HZ)) {
1650 tx_tspec->consumed_tx_time = 0;
1651 tx_tspec->time_slice_start = now;
1652
1653 if (tx_tspec->downgraded)
1654 tx_tspec->action =
1655 TX_TSPEC_ACTION_STOP_DOWNGRADE;
1656 }
1657
1658 switch (tx_tspec->action) {
1659 case TX_TSPEC_ACTION_STOP_DOWNGRADE:
1660 /* take the original parameters */
1661 if (drv_conf_tx(local, sdata, ac, &sdata->tx_conf[ac]))
1662 sdata_err(sdata,
1663 "failed to set TX queue parameters for queue %d\n",
1664 ac);
1665 tx_tspec->action = TX_TSPEC_ACTION_NONE;
1666 tx_tspec->downgraded = false;
1667 ret = true;
1668 break;
1669 case TX_TSPEC_ACTION_DOWNGRADE:
1670 if (time_after(now, tx_tspec->time_slice_start + HZ)) {
1671 tx_tspec->action = TX_TSPEC_ACTION_NONE;
1672 ret = true;
1673 break;
1674 }
1675 /* downgrade next lower non-ACM AC */
1676 for (non_acm_ac = ac + 1;
1677 non_acm_ac < IEEE80211_NUM_ACS;
1678 non_acm_ac++)
1679 if (!(sdata->wmm_acm & BIT(7 - 2 * non_acm_ac)))
1680 break;
1681 /* The loop will result in using BK even if it requires
1682 * admission control, such configuration makes no sense
1683 * and we have to transmit somehow - the AC selection
1684 * does the same thing.
1685 */
1686 if (drv_conf_tx(local, sdata, ac,
1687 &sdata->tx_conf[non_acm_ac]))
1688 sdata_err(sdata,
1689 "failed to set TX queue parameters for queue %d\n",
1690 ac);
1691 tx_tspec->action = TX_TSPEC_ACTION_NONE;
1692 ret = true;
1693 schedule_delayed_work(&ifmgd->tx_tspec_wk,
1694 tx_tspec->time_slice_start + HZ - now + 1);
1695 break;
1696 case TX_TSPEC_ACTION_NONE:
1697 /* nothing now */
1698 break;
1699 }
1700 }
1701
1702 return ret;
1703}
1704
1705void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
1706{
1707 if (__ieee80211_sta_handle_tspec_ac_params(sdata))
1708 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
1709}
1710
1711static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
1712{
1713 struct ieee80211_sub_if_data *sdata;
1714
1715 sdata = container_of(work, struct ieee80211_sub_if_data,
1716 u.mgd.tx_tspec_wk.work);
1717 ieee80211_sta_handle_tspec_ac_params(sdata);
1718}
1719
1583/* MLME */ 1720/* MLME */
1584static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, 1721static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
1585 struct ieee80211_sub_if_data *sdata, 1722 struct ieee80211_sub_if_data *sdata,
@@ -1664,12 +1801,14 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
1664 params.uapsd = uapsd; 1801 params.uapsd = uapsd;
1665 1802
1666 mlme_dbg(sdata, 1803 mlme_dbg(sdata,
1667 "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n", 1804 "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
1668 queue, aci, acm, 1805 queue, aci, acm,
1669 params.aifs, params.cw_min, params.cw_max, 1806 params.aifs, params.cw_min, params.cw_max,
1670 params.txop, params.uapsd); 1807 params.txop, params.uapsd,
1808 ifmgd->tx_tspec[queue].downgraded);
1671 sdata->tx_conf[queue] = params; 1809 sdata->tx_conf[queue] = params;
1672 if (drv_conf_tx(local, sdata, queue, &params)) 1810 if (!ifmgd->tx_tspec[queue].downgraded &&
1811 drv_conf_tx(local, sdata, queue, &params))
1673 sdata_err(sdata, 1812 sdata_err(sdata,
1674 "failed to set TX queue parameters for queue %d\n", 1813 "failed to set TX queue parameters for queue %d\n",
1675 queue); 1814 queue);
@@ -1924,6 +2063,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1924 ieee80211_vif_release_channel(sdata); 2063 ieee80211_vif_release_channel(sdata);
1925 2064
1926 sdata->vif.csa_active = false; 2065 sdata->vif.csa_active = false;
2066 ifmgd->csa_waiting_bcn = false;
1927 if (sdata->csa_block_tx) { 2067 if (sdata->csa_block_tx) {
1928 ieee80211_wake_vif_queues(local, sdata, 2068 ieee80211_wake_vif_queues(local, sdata,
1929 IEEE80211_QUEUE_STOP_REASON_CSA); 2069 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -1931,6 +2071,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1931 } 2071 }
1932 mutex_unlock(&local->mtx); 2072 mutex_unlock(&local->mtx);
1933 2073
2074 /* existing TX TSPEC sessions no longer exist */
2075 memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec));
2076 cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
2077
1934 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; 2078 sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
1935} 2079}
1936 2080
@@ -1983,9 +2127,46 @@ out:
1983 mutex_unlock(&local->mtx); 2127 mutex_unlock(&local->mtx);
1984} 2128}
1985 2129
2130static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
2131 struct ieee80211_hdr *hdr,
2132 u16 tx_time)
2133{
2134 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2135 u16 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
2136 int ac = ieee80211_ac_from_tid(tid);
2137 struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
2138 unsigned long now = jiffies;
2139
2140 if (likely(!tx_tspec->admitted_time))
2141 return;
2142
2143 if (time_after(now, tx_tspec->time_slice_start + HZ)) {
2144 tx_tspec->consumed_tx_time = 0;
2145 tx_tspec->time_slice_start = now;
2146
2147 if (tx_tspec->downgraded) {
2148 tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
2149 schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
2150 }
2151 }
2152
2153 if (tx_tspec->downgraded)
2154 return;
2155
2156 tx_tspec->consumed_tx_time += tx_time;
2157
2158 if (tx_tspec->consumed_tx_time >= tx_tspec->admitted_time) {
2159 tx_tspec->downgraded = true;
2160 tx_tspec->action = TX_TSPEC_ACTION_DOWNGRADE;
2161 schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
2162 }
2163}
2164
1986void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, 2165void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
1987 struct ieee80211_hdr *hdr, bool ack) 2166 struct ieee80211_hdr *hdr, bool ack, u16 tx_time)
1988{ 2167{
2168 ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
2169
1989 if (!ieee80211_is_data(hdr->frame_control)) 2170 if (!ieee80211_is_data(hdr->frame_control))
1990 return; 2171 return;
1991 2172
@@ -2048,8 +2229,6 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
2048 2229
2049 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 2230 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
2050 run_again(sdata, ifmgd->probe_timeout); 2231 run_again(sdata, ifmgd->probe_timeout);
2051 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
2052 ieee80211_flush_queues(sdata->local, sdata);
2053} 2232}
2054 2233
2055static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, 2234static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -2172,6 +2351,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2172 true, frame_buf); 2351 true, frame_buf);
2173 mutex_lock(&local->mtx); 2352 mutex_lock(&local->mtx);
2174 sdata->vif.csa_active = false; 2353 sdata->vif.csa_active = false;
2354 ifmgd->csa_waiting_bcn = false;
2175 if (sdata->csa_block_tx) { 2355 if (sdata->csa_block_tx) {
2176 ieee80211_wake_vif_queues(local, sdata, 2356 ieee80211_wake_vif_queues(local, sdata,
2177 IEEE80211_QUEUE_STOP_REASON_CSA); 2357 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -3196,6 +3376,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3196 } 3376 }
3197 } 3377 }
3198 3378
3379 if (ifmgd->csa_waiting_bcn)
3380 ieee80211_chswitch_post_beacon(sdata);
3381
3199 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) 3382 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
3200 return; 3383 return;
3201 ifmgd->beacon_crc = ncrc; 3384 ifmgd->beacon_crc = ncrc;
@@ -3204,6 +3387,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3204 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); 3387 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
3205 3388
3206 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, 3389 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
3390 rx_status->device_timestamp,
3207 &elems, true); 3391 &elems, true);
3208 3392
3209 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && 3393 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
@@ -3335,8 +3519,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3335 break; 3519 break;
3336 3520
3337 ieee80211_sta_process_chanswitch(sdata, 3521 ieee80211_sta_process_chanswitch(sdata,
3338 rx_status->mactime, 3522 rx_status->mactime,
3339 &elems, false); 3523 rx_status->device_timestamp,
3524 &elems, false);
3340 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { 3525 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
3341 ies_len = skb->len - 3526 ies_len = skb->len -
3342 offsetof(struct ieee80211_mgmt, 3527 offsetof(struct ieee80211_mgmt,
@@ -3357,8 +3542,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3357 &mgmt->u.action.u.ext_chan_switch.data; 3542 &mgmt->u.action.u.ext_chan_switch.data;
3358 3543
3359 ieee80211_sta_process_chanswitch(sdata, 3544 ieee80211_sta_process_chanswitch(sdata,
3360 rx_status->mactime, 3545 rx_status->mactime,
3361 &elems, false); 3546 rx_status->device_timestamp,
3547 &elems, false);
3362 } 3548 }
3363 break; 3549 break;
3364 } 3550 }
@@ -3665,11 +3851,12 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
3665 struct ieee80211_sub_if_data *sdata = 3851 struct ieee80211_sub_if_data *sdata =
3666 (struct ieee80211_sub_if_data *) data; 3852 (struct ieee80211_sub_if_data *) data;
3667 struct ieee80211_local *local = sdata->local; 3853 struct ieee80211_local *local = sdata->local;
3854 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3668 3855
3669 if (local->quiescing) 3856 if (local->quiescing)
3670 return; 3857 return;
3671 3858
3672 if (sdata->vif.csa_active) 3859 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
3673 return; 3860 return;
3674 3861
3675 sdata->u.mgd.connection_loss = false; 3862 sdata->u.mgd.connection_loss = false;
@@ -3687,7 +3874,7 @@ static void ieee80211_sta_conn_mon_timer(unsigned long data)
3687 if (local->quiescing) 3874 if (local->quiescing)
3688 return; 3875 return;
3689 3876
3690 if (sdata->vif.csa_active) 3877 if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
3691 return; 3878 return;
3692 3879
3693 ieee80211_queue_work(&local->hw, &ifmgd->monitor_work); 3880 ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
@@ -3799,6 +3986,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
3799 (unsigned long) sdata); 3986 (unsigned long) sdata);
3800 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 3987 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
3801 (unsigned long) sdata); 3988 (unsigned long) sdata);
3989 INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
3990 ieee80211_sta_handle_tspec_ac_params_wk);
3802 3991
3803 ifmgd->flags = 0; 3992 ifmgd->flags = 0;
3804 ifmgd->powersave = sdata->wdev.ps; 3993 ifmgd->powersave = sdata->wdev.ps;