aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-12 15:39:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-12 15:39:05 -0400
commit812fd645968118c35a3f4d0d18dd3f4d07221df0 (patch)
treeb68ee223f22a811e9743b193872052cd264fe2d0 /net/mac80211
parentcb180840a0c6bff7c0787373c23cefdf20417a27 (diff)
parent940d0ac9dbe3fb9d4806e96f006286c2e476deed (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts: drivers/net/wireless/iwlwifi/mvm/mac80211.c
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c20
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/mesh.c38
-rw-r--r--net/mac80211/mesh.h5
-rw-r--r--net/mac80211/mesh_plink.c7
-rw-r--r--net/mac80211/mlme.c98
-rw-r--r--net/mac80211/rx.c26
-rw-r--r--net/mac80211/sta_info.c4
-rw-r--r--net/mac80211/sta_info.h3
-rw-r--r--net/mac80211/tx.c6
-rw-r--r--net/mac80211/util.c5
12 files changed, 108 insertions, 110 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 30622101d3b5..64cf294c2b96 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1759,6 +1759,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
1759 /* mcast rate setting in Mesh Node */ 1759 /* mcast rate setting in Mesh Node */
1760 memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, 1760 memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate,
1761 sizeof(setup->mcast_rate)); 1761 sizeof(setup->mcast_rate));
1762 sdata->vif.bss_conf.basic_rates = setup->basic_rates;
1762 1763
1763 sdata->vif.bss_conf.beacon_int = setup->beacon_interval; 1764 sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
1764 sdata->vif.bss_conf.dtim_period = setup->dtim_period; 1765 sdata->vif.bss_conf.dtim_period = setup->dtim_period;
@@ -1871,6 +1872,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
1871 if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask)) 1872 if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask))
1872 conf->dot11MeshAwakeWindowDuration = 1873 conf->dot11MeshAwakeWindowDuration =
1873 nconf->dot11MeshAwakeWindowDuration; 1874 nconf->dot11MeshAwakeWindowDuration;
1875 if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask))
1876 conf->plink_timeout = nconf->plink_timeout;
1874 ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); 1877 ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON);
1875 return 0; 1878 return 0;
1876} 1879}
@@ -2838,6 +2841,12 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2838 return -EOPNOTSUPP; 2841 return -EOPNOTSUPP;
2839 } 2842 }
2840 2843
2844 /* configurations requiring offchan cannot work if no channel has been
2845 * specified
2846 */
2847 if (need_offchan && !chan)
2848 return -EINVAL;
2849
2841 mutex_lock(&local->mtx); 2850 mutex_lock(&local->mtx);
2842 2851
2843 /* Check if the operating channel is the requested channel */ 2852 /* Check if the operating channel is the requested channel */
@@ -2847,10 +2856,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2847 rcu_read_lock(); 2856 rcu_read_lock();
2848 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 2857 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
2849 2858
2850 if (chanctx_conf) 2859 if (chanctx_conf) {
2851 need_offchan = chan != chanctx_conf->def.chan; 2860 need_offchan = chan && (chan != chanctx_conf->def.chan);
2852 else 2861 } else if (!chan) {
2862 ret = -EINVAL;
2863 rcu_read_unlock();
2864 goto out_unlock;
2865 } else {
2853 need_offchan = true; 2866 need_offchan = true;
2867 }
2854 rcu_read_unlock(); 2868 rcu_read_unlock();
2855 } 2869 }
2856 2870
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9eed6f1d1614..7a6f1a0207ec 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -366,7 +366,7 @@ struct ieee80211_mgd_assoc_data {
366 u8 ssid_len; 366 u8 ssid_len;
367 u8 supp_rates_len; 367 u8 supp_rates_len;
368 bool wmm, uapsd; 368 bool wmm, uapsd;
369 bool have_beacon, need_beacon; 369 bool need_beacon;
370 bool synced; 370 bool synced;
371 bool timeout_started; 371 bool timeout_started;
372 372
@@ -404,6 +404,7 @@ struct ieee80211_if_managed {
404 404
405 bool powersave; /* powersave requested for this iface */ 405 bool powersave; /* powersave requested for this iface */
406 bool broken_ap; /* AP is broken -- turn off powersave */ 406 bool broken_ap; /* AP is broken -- turn off powersave */
407 bool have_beacon;
407 u8 dtim_period; 408 u8 dtim_period;
408 enum ieee80211_smps_mode req_smps, /* requested smps mode */ 409 enum ieee80211_smps_mode req_smps, /* requested smps mode */
409 driver_smps_mode; /* smps mode request */ 410 driver_smps_mode; /* smps mode request */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1998f1475267..626c83c042d7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -686,8 +686,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
686 return -EINVAL; 686 return -EINVAL;
687 687
688#ifdef CONFIG_PM 688#ifdef CONFIG_PM
689 if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) && 689 if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
690 (!local->ops->suspend || !local->ops->resume))
691 return -EINVAL; 690 return -EINVAL;
692#endif 691#endif
693 692
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index b3d1fdd46368..6c33af482df4 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -274,8 +274,7 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
274 *pos++ = ifmsh->mesh_auth_id; 274 *pos++ = ifmsh->mesh_auth_id;
275 /* Mesh Formation Info - number of neighbors */ 275 /* Mesh Formation Info - number of neighbors */
276 neighbors = atomic_read(&ifmsh->estab_plinks); 276 neighbors = atomic_read(&ifmsh->estab_plinks);
277 /* Number of neighbor mesh STAs or 15 whichever is smaller */ 277 neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS);
278 neighbors = (neighbors > 15) ? 15 : neighbors;
279 *pos++ = neighbors << 1; 278 *pos++ = neighbors << 1;
280 /* Mesh capability */ 279 /* Mesh capability */
281 *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; 280 *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING;
@@ -576,13 +575,11 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
576 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 575 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
577 u32 changed; 576 u32 changed;
578 577
579 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); 578 ieee80211_sta_expire(sdata, ifmsh->mshcfg.plink_timeout * HZ);
580 mesh_path_expire(sdata); 579 mesh_path_expire(sdata);
581 580
582 changed = mesh_accept_plinks_update(sdata); 581 changed = mesh_accept_plinks_update(sdata);
583 sdata_lock(sdata);
584 ieee80211_mbss_info_change_notify(sdata, changed); 582 ieee80211_mbss_info_change_notify(sdata, changed);
585 sdata_unlock(sdata);
586 583
587 mod_timer(&ifmsh->housekeeping_timer, 584 mod_timer(&ifmsh->housekeeping_timer,
588 round_jiffies(jiffies + 585 round_jiffies(jiffies +
@@ -741,9 +738,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
741 BSS_CHANGED_HT | 738 BSS_CHANGED_HT |
742 BSS_CHANGED_BASIC_RATES | 739 BSS_CHANGED_BASIC_RATES |
743 BSS_CHANGED_BEACON_INT; 740 BSS_CHANGED_BEACON_INT;
744 enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
745 struct ieee80211_supported_band *sband =
746 sdata->local->hw.wiphy->bands[band];
747 741
748 local->fif_other_bss++; 742 local->fif_other_bss++;
749 /* mesh ifaces must set allmulti to forward mcast traffic */ 743 /* mesh ifaces must set allmulti to forward mcast traffic */
@@ -761,7 +755,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
761 sdata->vif.bss_conf.ht_operation_mode = 755 sdata->vif.bss_conf.ht_operation_mode =
762 ifmsh->mshcfg.ht_opmode; 756 ifmsh->mshcfg.ht_opmode;
763 sdata->vif.bss_conf.enable_beacon = true; 757 sdata->vif.bss_conf.enable_beacon = true;
764 sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband);
765 758
766 changed |= ieee80211_mps_local_status_update(sdata); 759 changed |= ieee80211_mps_local_status_update(sdata);
767 760
@@ -789,12 +782,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
789 sdata->vif.bss_conf.enable_beacon = false; 782 sdata->vif.bss_conf.enable_beacon = false;
790 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 783 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
791 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 784 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
792 sdata_lock(sdata);
793 bcn = rcu_dereference_protected(ifmsh->beacon, 785 bcn = rcu_dereference_protected(ifmsh->beacon,
794 lockdep_is_held(&sdata->wdev.mtx)); 786 lockdep_is_held(&sdata->wdev.mtx));
795 rcu_assign_pointer(ifmsh->beacon, NULL); 787 rcu_assign_pointer(ifmsh->beacon, NULL);
796 kfree_rcu(bcn, rcu_head); 788 kfree_rcu(bcn, rcu_head);
797 sdata_unlock(sdata);
798 789
799 /* flush STAs and mpaths on this iface */ 790 /* flush STAs and mpaths on this iface */
800 sta_info_flush(sdata); 791 sta_info_flush(sdata);
@@ -807,14 +798,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
807 del_timer_sync(&sdata->u.mesh.housekeeping_timer); 798 del_timer_sync(&sdata->u.mesh.housekeeping_timer);
808 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); 799 del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);
809 del_timer_sync(&sdata->u.mesh.mesh_path_timer); 800 del_timer_sync(&sdata->u.mesh.mesh_path_timer);
810 /*
811 * If the timer fired while we waited for it, it will have
812 * requeued the work. Now the work will be running again
813 * but will not rearm the timer again because it checks
814 * whether the interface is running, which, at this point,
815 * it no longer is.
816 */
817 cancel_work_sync(&sdata->work);
818 801
819 local->fif_other_bss--; 802 local->fif_other_bss--;
820 atomic_dec(&local->iff_allmultis); 803 atomic_dec(&local->iff_allmultis);
@@ -955,6 +938,12 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
955 struct ieee80211_mgmt *mgmt; 938 struct ieee80211_mgmt *mgmt;
956 u16 stype; 939 u16 stype;
957 940
941 sdata_lock(sdata);
942
943 /* mesh already went down */
944 if (!sdata->wdev.mesh_id_len)
945 goto out;
946
958 rx_status = IEEE80211_SKB_RXCB(skb); 947 rx_status = IEEE80211_SKB_RXCB(skb);
959 mgmt = (struct ieee80211_mgmt *) skb->data; 948 mgmt = (struct ieee80211_mgmt *) skb->data;
960 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; 949 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
@@ -972,12 +961,20 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
972 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); 961 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
973 break; 962 break;
974 } 963 }
964out:
965 sdata_unlock(sdata);
975} 966}
976 967
977void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) 968void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
978{ 969{
979 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 970 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
980 971
972 sdata_lock(sdata);
973
974 /* mesh already went down */
975 if (!sdata->wdev.mesh_id_len)
976 goto out;
977
981 if (ifmsh->preq_queue_len && 978 if (ifmsh->preq_queue_len &&
982 time_after(jiffies, 979 time_after(jiffies,
983 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) 980 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
@@ -997,6 +994,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
997 994
998 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) 995 if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags))
999 mesh_sync_adjust_tbtt(sdata); 996 mesh_sync_adjust_tbtt(sdata);
997
998out:
999 sdata_unlock(sdata);
1000} 1000}
1001 1001
1002void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) 1002void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index da158774eebb..01a28bca6e9b 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -188,7 +188,6 @@ struct mesh_rmc {
188 u32 idx_mask; 188 u32 idx_mask;
189}; 189};
190 190
191#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
192#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) 191#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
193 192
194#define MESH_PATH_EXPIRE (600 * HZ) 193#define MESH_PATH_EXPIRE (600 * HZ)
@@ -324,14 +323,14 @@ static inline
324u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) 323u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
325{ 324{
326 atomic_inc(&sdata->u.mesh.estab_plinks); 325 atomic_inc(&sdata->u.mesh.estab_plinks);
327 return mesh_accept_plinks_update(sdata); 326 return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON;
328} 327}
329 328
330static inline 329static inline
331u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) 330u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
332{ 331{
333 atomic_dec(&sdata->u.mesh.estab_plinks); 332 atomic_dec(&sdata->u.mesh.estab_plinks);
334 return mesh_accept_plinks_update(sdata); 333 return mesh_accept_plinks_update(sdata) | BSS_CHANGED_BEACON;
335} 334}
336 335
337static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) 336static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 6c4da99bc4fb..09bebed99416 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -517,9 +517,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
517 ieee80211_mps_frame_release(sta, elems); 517 ieee80211_mps_frame_release(sta, elems);
518out: 518out:
519 rcu_read_unlock(); 519 rcu_read_unlock();
520 sdata_lock(sdata);
521 ieee80211_mbss_info_change_notify(sdata, changed); 520 ieee80211_mbss_info_change_notify(sdata, changed);
522 sdata_unlock(sdata);
523} 521}
524 522
525static void mesh_plink_timer(unsigned long data) 523static void mesh_plink_timer(unsigned long data)
@@ -1070,9 +1068,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
1070 1068
1071 rcu_read_unlock(); 1069 rcu_read_unlock();
1072 1070
1073 if (changed) { 1071 if (changed)
1074 sdata_lock(sdata);
1075 ieee80211_mbss_info_change_notify(sdata, changed); 1072 ieee80211_mbss_info_change_notify(sdata, changed);
1076 sdata_unlock(sdata);
1077 }
1078} 1073}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f44f4caa69ee..ad9bb9e10cbb 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -880,6 +880,10 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
880 880
881 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | 881 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
882 IEEE80211_TX_INTFL_OFFCHAN_TX_OK; 882 IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
883
884 if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
885 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
886
883 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | 887 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
884 IEEE80211_STA_CONNECTION_POLL)) 888 IEEE80211_STA_CONNECTION_POLL))
885 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; 889 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;
@@ -1356,7 +1360,7 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
1356 IEEE80211_STA_CONNECTION_POLL)) 1360 IEEE80211_STA_CONNECTION_POLL))
1357 return false; 1361 return false;
1358 1362
1359 if (!sdata->vif.bss_conf.dtim_period) 1363 if (!mgd->have_beacon)
1360 return false; 1364 return false;
1361 1365
1362 rcu_read_lock(); 1366 rcu_read_lock();
@@ -1767,7 +1771,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1767 1771
1768 ieee80211_led_assoc(local, 1); 1772 ieee80211_led_assoc(local, 1);
1769 1773
1770 if (sdata->u.mgd.assoc_data->have_beacon) { 1774 if (sdata->u.mgd.have_beacon) {
1771 /* 1775 /*
1772 * If the AP is buggy we may get here with no DTIM period 1776 * If the AP is buggy we may get here with no DTIM period
1773 * known, so assume it's 1 which is the only safe assumption 1777 * known, so assume it's 1 which is the only safe assumption
@@ -1775,7 +1779,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1775 * probably just won't work at all. 1779 * probably just won't work at all.
1776 */ 1780 */
1777 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; 1781 bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
1778 bss_info_changed |= BSS_CHANGED_DTIM_PERIOD; 1782 bss_info_changed |= BSS_CHANGED_BEACON_INFO;
1779 } else { 1783 } else {
1780 bss_conf->dtim_period = 0; 1784 bss_conf->dtim_period = 0;
1781 } 1785 }
@@ -1899,6 +1903,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1899 del_timer_sync(&sdata->u.mgd.chswitch_timer); 1903 del_timer_sync(&sdata->u.mgd.chswitch_timer);
1900 1904
1901 sdata->vif.bss_conf.dtim_period = 0; 1905 sdata->vif.bss_conf.dtim_period = 0;
1906 ifmgd->have_beacon = false;
1902 1907
1903 ifmgd->flags = 0; 1908 ifmgd->flags = 0;
1904 ieee80211_vif_release_channel(sdata); 1909 ieee80211_vif_release_channel(sdata);
@@ -2151,7 +2156,8 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
2151 IEEE80211_MAX_QUEUE_MAP, 2156 IEEE80211_MAX_QUEUE_MAP,
2152 IEEE80211_QUEUE_STOP_REASON_CSA); 2157 IEEE80211_QUEUE_STOP_REASON_CSA);
2153 2158
2154 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); 2159 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
2160 IEEE80211_DEAUTH_FRAME_LEN);
2155 sdata_unlock(sdata); 2161 sdata_unlock(sdata);
2156} 2162}
2157 2163
@@ -2298,7 +2304,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2298 sdata_info(sdata, "%pM denied authentication (status %d)\n", 2304 sdata_info(sdata, "%pM denied authentication (status %d)\n",
2299 mgmt->sa, status_code); 2305 mgmt->sa, status_code);
2300 ieee80211_destroy_auth_data(sdata, false); 2306 ieee80211_destroy_auth_data(sdata, false);
2301 cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); 2307 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2302 return; 2308 return;
2303 } 2309 }
2304 2310
@@ -2333,7 +2339,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2333 * Report auth frame to user space for processing since another 2339 * Report auth frame to user space for processing since another
2334 * round of Authentication frames is still needed. 2340 * round of Authentication frames is still needed.
2335 */ 2341 */
2336 cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); 2342 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2337 return; 2343 return;
2338 } 2344 }
2339 2345
@@ -2350,7 +2356,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2350 } 2356 }
2351 mutex_unlock(&sdata->local->sta_mtx); 2357 mutex_unlock(&sdata->local->sta_mtx);
2352 2358
2353 cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len); 2359 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2354 return; 2360 return;
2355 out_err: 2361 out_err:
2356 mutex_unlock(&sdata->local->sta_mtx); 2362 mutex_unlock(&sdata->local->sta_mtx);
@@ -2383,7 +2389,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
2383 2389
2384 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2390 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2385 2391
2386 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len); 2392 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2387} 2393}
2388 2394
2389 2395
@@ -2409,7 +2415,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
2409 2415
2410 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2416 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2411 2417
2412 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len); 2418 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2413} 2419}
2414 2420
2415static void ieee80211_get_rates(struct ieee80211_supported_band *sband, 2421static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2707,7 +2713,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2707 /* oops -- internal error -- send timeout for now */ 2713 /* oops -- internal error -- send timeout for now */
2708 ieee80211_destroy_assoc_data(sdata, false); 2714 ieee80211_destroy_assoc_data(sdata, false);
2709 cfg80211_put_bss(sdata->local->hw.wiphy, bss); 2715 cfg80211_put_bss(sdata->local->hw.wiphy, bss);
2710 cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); 2716 cfg80211_assoc_timeout(sdata->dev, mgmt->bssid);
2711 return; 2717 return;
2712 } 2718 }
2713 sdata_info(sdata, "associated\n"); 2719 sdata_info(sdata, "associated\n");
@@ -2720,7 +2726,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2720 ieee80211_destroy_assoc_data(sdata, true); 2726 ieee80211_destroy_assoc_data(sdata, true);
2721 } 2727 }
2722 2728
2723 cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len); 2729 cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len);
2724} 2730}
2725 2731
2726static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2732static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2732,24 +2738,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2732 int freq; 2738 int freq;
2733 struct ieee80211_bss *bss; 2739 struct ieee80211_bss *bss;
2734 struct ieee80211_channel *channel; 2740 struct ieee80211_channel *channel;
2735 bool need_ps = false;
2736 2741
2737 sdata_assert_lock(sdata); 2742 sdata_assert_lock(sdata);
2738 2743
2739 if ((sdata->u.mgd.associated &&
2740 ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
2741 (sdata->u.mgd.assoc_data &&
2742 ether_addr_equal(mgmt->bssid,
2743 sdata->u.mgd.assoc_data->bss->bssid))) {
2744 /* not previously set so we may need to recalc */
2745 need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period;
2746
2747 if (elems->tim && !elems->parse_error) {
2748 const struct ieee80211_tim_ie *tim_ie = elems->tim;
2749 sdata->u.mgd.dtim_period = tim_ie->dtim_period;
2750 }
2751 }
2752
2753 if (elems->ds_params) 2744 if (elems->ds_params)
2754 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 2745 freq = ieee80211_channel_to_frequency(elems->ds_params[0],
2755 rx_status->band); 2746 rx_status->band);
@@ -2770,12 +2761,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2770 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) 2761 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
2771 return; 2762 return;
2772 2763
2773 if (need_ps) {
2774 mutex_lock(&local->iflist_mtx);
2775 ieee80211_recalc_ps(local, -1);
2776 mutex_unlock(&local->iflist_mtx);
2777 }
2778
2779 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, 2764 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
2780 elems, true); 2765 elems, true);
2781 2766
@@ -2889,7 +2874,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2889 len - baselen, false, &elems); 2874 len - baselen, false, &elems);
2890 2875
2891 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); 2876 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2892 ifmgd->assoc_data->have_beacon = true; 2877 if (elems.tim && !elems.parse_error) {
2878 const struct ieee80211_tim_ie *tim_ie = elems.tim;
2879 ifmgd->dtim_period = tim_ie->dtim_period;
2880 }
2881 ifmgd->have_beacon = true;
2893 ifmgd->assoc_data->need_beacon = false; 2882 ifmgd->assoc_data->need_beacon = false;
2894 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { 2883 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
2895 sdata->vif.bss_conf.sync_tsf = 2884 sdata->vif.bss_conf.sync_tsf =
@@ -3071,7 +3060,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3071 * If we haven't had a beacon before, tell the driver about the 3060 * If we haven't had a beacon before, tell the driver about the
3072 * DTIM period (and beacon timing if desired) now. 3061 * DTIM period (and beacon timing if desired) now.
3073 */ 3062 */
3074 if (!bss_conf->dtim_period) { 3063 if (!ifmgd->have_beacon) {
3075 /* a few bogus AP send dtim_period = 0 or no TIM IE */ 3064 /* a few bogus AP send dtim_period = 0 or no TIM IE */
3076 if (elems.tim) 3065 if (elems.tim)
3077 bss_conf->dtim_period = elems.tim->dtim_period ?: 1; 3066 bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
@@ -3090,7 +3079,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3090 sdata->vif.bss_conf.sync_dtim_count = 0; 3079 sdata->vif.bss_conf.sync_dtim_count = 0;
3091 } 3080 }
3092 3081
3093 changed |= BSS_CHANGED_DTIM_PERIOD; 3082 changed |= BSS_CHANGED_BEACON_INFO;
3083 ifmgd->have_beacon = true;
3084
3085 mutex_lock(&local->iflist_mtx);
3086 ieee80211_recalc_ps(local, -1);
3087 mutex_unlock(&local->iflist_mtx);
3088
3094 ieee80211_recalc_ps_vif(sdata); 3089 ieee80211_recalc_ps_vif(sdata);
3095 } 3090 }
3096 3091
@@ -3113,8 +3108,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3113 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 3108 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3114 WLAN_REASON_DEAUTH_LEAVING, 3109 WLAN_REASON_DEAUTH_LEAVING,
3115 true, deauth_buf); 3110 true, deauth_buf);
3116 cfg80211_send_deauth(sdata->dev, deauth_buf, 3111 cfg80211_tx_mlme_mgmt(sdata->dev, deauth_buf,
3117 sizeof(deauth_buf)); 3112 sizeof(deauth_buf));
3118 return; 3113 return;
3119 } 3114 }
3120 3115
@@ -3232,7 +3227,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
3232 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, 3227 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
3233 tx, frame_buf); 3228 tx, frame_buf);
3234 3229
3235 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); 3230 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3231 IEEE80211_DEAUTH_FRAME_LEN);
3236} 3232}
3237 3233
3238static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) 3234static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3423,15 +3419,14 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3423 3419
3424 ieee80211_destroy_auth_data(sdata, false); 3420 ieee80211_destroy_auth_data(sdata, false);
3425 3421
3426 cfg80211_send_auth_timeout(sdata->dev, bssid); 3422 cfg80211_auth_timeout(sdata->dev, bssid);
3427 } 3423 }
3428 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started) 3424 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
3429 run_again(sdata, ifmgd->auth_data->timeout); 3425 run_again(sdata, ifmgd->auth_data->timeout);
3430 3426
3431 if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started && 3427 if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
3432 time_after(jiffies, ifmgd->assoc_data->timeout)) { 3428 time_after(jiffies, ifmgd->assoc_data->timeout)) {
3433 if ((ifmgd->assoc_data->need_beacon && 3429 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
3434 !ifmgd->assoc_data->have_beacon) ||
3435 ieee80211_do_assoc(sdata)) { 3430 ieee80211_do_assoc(sdata)) {
3436 u8 bssid[ETH_ALEN]; 3431 u8 bssid[ETH_ALEN];
3437 3432
@@ -3439,7 +3434,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3439 3434
3440 ieee80211_destroy_assoc_data(sdata, false); 3435 ieee80211_destroy_assoc_data(sdata, false);
3441 3436
3442 cfg80211_send_assoc_timeout(sdata->dev, bssid); 3437 cfg80211_assoc_timeout(sdata->dev, bssid);
3443 } 3438 }
3444 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3439 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
3445 run_again(sdata, ifmgd->assoc_data->timeout); 3440 run_again(sdata, ifmgd->assoc_data->timeout);
@@ -3988,8 +3983,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
3988 WLAN_REASON_UNSPECIFIED, 3983 WLAN_REASON_UNSPECIFIED,
3989 false, frame_buf); 3984 false, frame_buf);
3990 3985
3991 cfg80211_send_deauth(sdata->dev, frame_buf, 3986 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3992 sizeof(frame_buf)); 3987 sizeof(frame_buf));
3993 } 3988 }
3994 3989
3995 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 3990 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4051,8 +4046,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4051 WLAN_REASON_UNSPECIFIED, 4046 WLAN_REASON_UNSPECIFIED,
4052 false, frame_buf); 4047 false, frame_buf);
4053 4048
4054 cfg80211_send_deauth(sdata->dev, frame_buf, 4049 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4055 sizeof(frame_buf)); 4050 sizeof(frame_buf));
4056 } 4051 }
4057 4052
4058 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 4053 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
@@ -4199,6 +4194,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4199 4194
4200 ifmgd->assoc_data = assoc_data; 4195 ifmgd->assoc_data = assoc_data;
4201 ifmgd->dtim_period = 0; 4196 ifmgd->dtim_period = 0;
4197 ifmgd->have_beacon = false;
4202 4198
4203 err = ieee80211_prep_connection(sdata, req->bss, true); 4199 err = ieee80211_prep_connection(sdata, req->bss, true);
4204 if (err) 4200 if (err)
@@ -4230,7 +4226,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4230 ifmgd->dtim_period = tim->dtim_period; 4226 ifmgd->dtim_period = tim->dtim_period;
4231 dtim_count = tim->dtim_count; 4227 dtim_count = tim->dtim_count;
4232 } 4228 }
4233 assoc_data->have_beacon = true; 4229 ifmgd->have_beacon = true;
4234 assoc_data->timeout = jiffies; 4230 assoc_data->timeout = jiffies;
4235 assoc_data->timeout_started = true; 4231 assoc_data->timeout_started = true;
4236 4232
@@ -4305,8 +4301,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4305 4301
4306 out: 4302 out:
4307 if (report_frame) 4303 if (report_frame)
4308 cfg80211_send_deauth(sdata->dev, frame_buf, 4304 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4309 IEEE80211_DEAUTH_FRAME_LEN); 4305 IEEE80211_DEAUTH_FRAME_LEN);
4310 4306
4311 return 0; 4307 return 0;
4312} 4308}
@@ -4336,8 +4332,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
4336 req->reason_code, !req->local_state_change, 4332 req->reason_code, !req->local_state_change,
4337 frame_buf); 4333 frame_buf);
4338 4334
4339 cfg80211_send_disassoc(sdata->dev, frame_buf, 4335 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4340 IEEE80211_DEAUTH_FRAME_LEN); 4336 IEEE80211_DEAUTH_FRAME_LEN);
4341 4337
4342 return 0; 4338 return 0;
4343} 4339}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bdd7b4a719e9..23dbcfc69b3b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1747,27 +1747,21 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
1747 if (unlikely(!ieee80211_has_protected(fc) && 1747 if (unlikely(!ieee80211_has_protected(fc) &&
1748 ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && 1748 ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
1749 rx->key)) { 1749 rx->key)) {
1750 if (ieee80211_is_deauth(fc)) 1750 if (ieee80211_is_deauth(fc) ||
1751 cfg80211_send_unprot_deauth(rx->sdata->dev, 1751 ieee80211_is_disassoc(fc))
1752 rx->skb->data, 1752 cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
1753 rx->skb->len); 1753 rx->skb->data,
1754 else if (ieee80211_is_disassoc(fc)) 1754 rx->skb->len);
1755 cfg80211_send_unprot_disassoc(rx->sdata->dev,
1756 rx->skb->data,
1757 rx->skb->len);
1758 return -EACCES; 1755 return -EACCES;
1759 } 1756 }
1760 /* BIP does not use Protected field, so need to check MMIE */ 1757 /* BIP does not use Protected field, so need to check MMIE */
1761 if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && 1758 if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
1762 ieee80211_get_mmie_keyidx(rx->skb) < 0)) { 1759 ieee80211_get_mmie_keyidx(rx->skb) < 0)) {
1763 if (ieee80211_is_deauth(fc)) 1760 if (ieee80211_is_deauth(fc) ||
1764 cfg80211_send_unprot_deauth(rx->sdata->dev, 1761 ieee80211_is_disassoc(fc))
1765 rx->skb->data, 1762 cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev,
1766 rx->skb->len); 1763 rx->skb->data,
1767 else if (ieee80211_is_disassoc(fc)) 1764 rx->skb->len);
1768 cfg80211_send_unprot_disassoc(rx->sdata->dev,
1769 rx->skb->data,
1770 rx->skb->len);
1771 return -EACCES; 1765 return -EACCES;
1772 } 1766 }
1773 /* 1767 /*
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a04c5671d7fd..b4297982d34a 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1132,6 +1132,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
1132 * ends the poll/service period. 1132 * ends the poll/service period.
1133 */ 1133 */
1134 info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | 1134 info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
1135 IEEE80211_TX_CTL_PS_RESPONSE |
1135 IEEE80211_TX_STATUS_EOSP | 1136 IEEE80211_TX_STATUS_EOSP |
1136 IEEE80211_TX_CTL_REQ_TX_STATUS; 1137 IEEE80211_TX_CTL_REQ_TX_STATUS;
1137 1138
@@ -1269,7 +1270,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
1269 * STA may still remain is PS mode after this frame 1270 * STA may still remain is PS mode after this frame
1270 * exchange. 1271 * exchange.
1271 */ 1272 */
1272 info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; 1273 info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER |
1274 IEEE80211_TX_CTL_PS_RESPONSE;
1273 1275
1274 /* 1276 /*
1275 * Use MoreData flag to indicate whether there are 1277 * Use MoreData flag to indicate whether there are
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 41c28b977f7c..bd12fc54266c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -297,6 +297,9 @@ struct sta_ampdu_mlme {
297 * @rcu_head: RCU head used for freeing this station struct 297 * @rcu_head: RCU head used for freeing this station struct
298 * @cur_max_bandwidth: maximum bandwidth to use for TX to the station, 298 * @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
299 * taken from HT/VHT capabilities or VHT operating mode notification 299 * taken from HT/VHT capabilities or VHT operating mode notification
300 * @chains: chains ever used for RX from this station
301 * @chain_signal_last: last signal (per chain)
302 * @chain_signal_avg: signal average (per chain)
300 */ 303 */
301struct sta_info { 304struct sta_info {
302 /* General information, mostly static */ 305 /* General information, mostly static */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 34be9336b5d1..4105d0ca963e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1790,12 +1790,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1790 break; 1790 break;
1791#ifdef CONFIG_MAC80211_MESH 1791#ifdef CONFIG_MAC80211_MESH
1792 case NL80211_IFTYPE_MESH_POINT: 1792 case NL80211_IFTYPE_MESH_POINT:
1793 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
1794 /* Do not send frames with mesh_ttl == 0 */
1795 sdata->u.mesh.mshstats.dropped_frames_ttl++;
1796 goto fail_rcu;
1797 }
1798
1799 if (!is_multicast_ether_addr(skb->data)) { 1793 if (!is_multicast_ether_addr(skb->data)) {
1800 struct sta_info *next_hop; 1794 struct sta_info *next_hop;
1801 bool mpp_lookup = true; 1795 bool mpp_lookup = true;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 89a83770d152..5a6c1351d1d3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1584,8 +1584,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1584 BSS_CHANGED_ARP_FILTER | 1584 BSS_CHANGED_ARP_FILTER |
1585 BSS_CHANGED_PS; 1585 BSS_CHANGED_PS;
1586 1586
1587 if (sdata->u.mgd.dtim_period) 1587 /* Re-send beacon info report to the driver */
1588 changed |= BSS_CHANGED_DTIM_PERIOD; 1588 if (sdata->u.mgd.have_beacon)
1589 changed |= BSS_CHANGED_BEACON_INFO;
1589 1590
1590 sdata_lock(sdata); 1591 sdata_lock(sdata);
1591 ieee80211_bss_info_change_notify(sdata, changed); 1592 ieee80211_bss_info_change_notify(sdata, changed);