aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-21 15:42:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-21 15:42:30 -0400
commit7d2a47aab2a511c87a96238977e04e6378969d45 (patch)
treee3765af6d4b292d8f3c013a5962324eab683a931 /net/mac80211
parentfedaf4ffc224a194e2d13a3ec2abe5df0bc94258 (diff)
parentb887664d882ee4f6a67e0bf05e5f141d32fcc067 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts: net/wireless/nl80211.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 a1c6e1ceede8..082f270b5912 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1765,6 +1765,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
1765 /* mcast rate setting in Mesh Node */ 1765 /* mcast rate setting in Mesh Node */
1766 memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, 1766 memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate,
1767 sizeof(setup->mcast_rate)); 1767 sizeof(setup->mcast_rate));
1768 sdata->vif.bss_conf.basic_rates = setup->basic_rates;
1768 1769
1769 sdata->vif.bss_conf.beacon_int = setup->beacon_interval; 1770 sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
1770 sdata->vif.bss_conf.dtim_period = setup->dtim_period; 1771 sdata->vif.bss_conf.dtim_period = setup->dtim_period;
@@ -1877,6 +1878,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
1877 if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask)) 1878 if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask))
1878 conf->dot11MeshAwakeWindowDuration = 1879 conf->dot11MeshAwakeWindowDuration =
1879 nconf->dot11MeshAwakeWindowDuration; 1880 nconf->dot11MeshAwakeWindowDuration;
1881 if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask))
1882 conf->plink_timeout = nconf->plink_timeout;
1880 ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON); 1883 ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON);
1881 return 0; 1884 return 0;
1882} 1885}
@@ -2844,6 +2847,12 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2844 return -EOPNOTSUPP; 2847 return -EOPNOTSUPP;
2845 } 2848 }
2846 2849
2850 /* configurations requiring offchan cannot work if no channel has been
2851 * specified
2852 */
2853 if (need_offchan && !chan)
2854 return -EINVAL;
2855
2847 mutex_lock(&local->mtx); 2856 mutex_lock(&local->mtx);
2848 2857
2849 /* Check if the operating channel is the requested channel */ 2858 /* Check if the operating channel is the requested channel */
@@ -2853,10 +2862,15 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2853 rcu_read_lock(); 2862 rcu_read_lock();
2854 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); 2863 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
2855 2864
2856 if (chanctx_conf) 2865 if (chanctx_conf) {
2857 need_offchan = chan != chanctx_conf->def.chan; 2866 need_offchan = chan && (chan != chanctx_conf->def.chan);
2858 else 2867 } else if (!chan) {
2868 ret = -EINVAL;
2869 rcu_read_unlock();
2870 goto out_unlock;
2871 } else {
2859 need_offchan = true; 2872 need_offchan = true;
2873 }
2860 rcu_read_unlock(); 2874 rcu_read_unlock();
2861 } 2875 }
2862 2876
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 923e1772e8f3..f97cd9d9105f 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 118540b16729..9e49f557fa5c 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,
@@ -2780,7 +2786,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2780 /* oops -- internal error -- send timeout for now */ 2786 /* oops -- internal error -- send timeout for now */
2781 ieee80211_destroy_assoc_data(sdata, false); 2787 ieee80211_destroy_assoc_data(sdata, false);
2782 cfg80211_put_bss(sdata->local->hw.wiphy, bss); 2788 cfg80211_put_bss(sdata->local->hw.wiphy, bss);
2783 cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); 2789 cfg80211_assoc_timeout(sdata->dev, mgmt->bssid);
2784 return; 2790 return;
2785 } 2791 }
2786 sdata_info(sdata, "associated\n"); 2792 sdata_info(sdata, "associated\n");
@@ -2793,7 +2799,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2793 ieee80211_destroy_assoc_data(sdata, true); 2799 ieee80211_destroy_assoc_data(sdata, true);
2794 } 2800 }
2795 2801
2796 cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len); 2802 cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len);
2797} 2803}
2798 2804
2799static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, 2805static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2805,24 +2811,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2805 int freq; 2811 int freq;
2806 struct ieee80211_bss *bss; 2812 struct ieee80211_bss *bss;
2807 struct ieee80211_channel *channel; 2813 struct ieee80211_channel *channel;
2808 bool need_ps = false;
2809 2814
2810 sdata_assert_lock(sdata); 2815 sdata_assert_lock(sdata);
2811 2816
2812 if ((sdata->u.mgd.associated &&
2813 ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
2814 (sdata->u.mgd.assoc_data &&
2815 ether_addr_equal(mgmt->bssid,
2816 sdata->u.mgd.assoc_data->bss->bssid))) {
2817 /* not previously set so we may need to recalc */
2818 need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period;
2819
2820 if (elems->tim && !elems->parse_error) {
2821 const struct ieee80211_tim_ie *tim_ie = elems->tim;
2822 sdata->u.mgd.dtim_period = tim_ie->dtim_period;
2823 }
2824 }
2825
2826 if (elems->ds_params) 2817 if (elems->ds_params)
2827 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 2818 freq = ieee80211_channel_to_frequency(elems->ds_params[0],
2828 rx_status->band); 2819 rx_status->band);
@@ -2843,12 +2834,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2843 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) 2834 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
2844 return; 2835 return;
2845 2836
2846 if (need_ps) {
2847 mutex_lock(&local->iflist_mtx);
2848 ieee80211_recalc_ps(local, -1);
2849 mutex_unlock(&local->iflist_mtx);
2850 }
2851
2852 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, 2837 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
2853 elems, true); 2838 elems, true);
2854 2839
@@ -2962,7 +2947,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2962 len - baselen, false, &elems); 2947 len - baselen, false, &elems);
2963 2948
2964 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); 2949 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
2965 ifmgd->assoc_data->have_beacon = true; 2950 if (elems.tim && !elems.parse_error) {
2951 const struct ieee80211_tim_ie *tim_ie = elems.tim;
2952 ifmgd->dtim_period = tim_ie->dtim_period;
2953 }
2954 ifmgd->have_beacon = true;
2966 ifmgd->assoc_data->need_beacon = false; 2955 ifmgd->assoc_data->need_beacon = false;
2967 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { 2956 if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) {
2968 sdata->vif.bss_conf.sync_tsf = 2957 sdata->vif.bss_conf.sync_tsf =
@@ -3144,7 +3133,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3144 * If we haven't had a beacon before, tell the driver about the 3133 * If we haven't had a beacon before, tell the driver about the
3145 * DTIM period (and beacon timing if desired) now. 3134 * DTIM period (and beacon timing if desired) now.
3146 */ 3135 */
3147 if (!bss_conf->dtim_period) { 3136 if (!ifmgd->have_beacon) {
3148 /* a few bogus AP send dtim_period = 0 or no TIM IE */ 3137 /* a few bogus AP send dtim_period = 0 or no TIM IE */
3149 if (elems.tim) 3138 if (elems.tim)
3150 bss_conf->dtim_period = elems.tim->dtim_period ?: 1; 3139 bss_conf->dtim_period = elems.tim->dtim_period ?: 1;
@@ -3163,7 +3152,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3163 sdata->vif.bss_conf.sync_dtim_count = 0; 3152 sdata->vif.bss_conf.sync_dtim_count = 0;
3164 } 3153 }
3165 3154
3166 changed |= BSS_CHANGED_DTIM_PERIOD; 3155 changed |= BSS_CHANGED_BEACON_INFO;
3156 ifmgd->have_beacon = true;
3157
3158 mutex_lock(&local->iflist_mtx);
3159 ieee80211_recalc_ps(local, -1);
3160 mutex_unlock(&local->iflist_mtx);
3161
3167 ieee80211_recalc_ps_vif(sdata); 3162 ieee80211_recalc_ps_vif(sdata);
3168 } 3163 }
3169 3164
@@ -3186,8 +3181,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3186 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 3181 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3187 WLAN_REASON_DEAUTH_LEAVING, 3182 WLAN_REASON_DEAUTH_LEAVING,
3188 true, deauth_buf); 3183 true, deauth_buf);
3189 cfg80211_send_deauth(sdata->dev, deauth_buf, 3184 cfg80211_tx_mlme_mgmt(sdata->dev, deauth_buf,
3190 sizeof(deauth_buf)); 3185 sizeof(deauth_buf));
3191 return; 3186 return;
3192 } 3187 }
3193 3188
@@ -3305,7 +3300,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
3305 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, 3300 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
3306 tx, frame_buf); 3301 tx, frame_buf);
3307 3302
3308 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); 3303 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
3304 IEEE80211_DEAUTH_FRAME_LEN);
3309} 3305}
3310 3306
3311static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) 3307static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3496,15 +3492,14 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3496 3492
3497 ieee80211_destroy_auth_data(sdata, false); 3493 ieee80211_destroy_auth_data(sdata, false);
3498 3494
3499 cfg80211_send_auth_timeout(sdata->dev, bssid); 3495 cfg80211_auth_timeout(sdata->dev, bssid);
3500 } 3496 }
3501 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started) 3497 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
3502 run_again(sdata, ifmgd->auth_data->timeout); 3498 run_again(sdata, ifmgd->auth_data->timeout);
3503 3499
3504 if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started && 3500 if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
3505 time_after(jiffies, ifmgd->assoc_data->timeout)) { 3501 time_after(jiffies, ifmgd->assoc_data->timeout)) {
3506 if ((ifmgd->assoc_data->need_beacon && 3502 if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) ||
3507 !ifmgd->assoc_data->have_beacon) ||
3508 ieee80211_do_assoc(sdata)) { 3503 ieee80211_do_assoc(sdata)) {
3509 u8 bssid[ETH_ALEN]; 3504 u8 bssid[ETH_ALEN];
3510 3505
@@ -3512,7 +3507,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3512 3507
3513 ieee80211_destroy_assoc_data(sdata, false); 3508 ieee80211_destroy_assoc_data(sdata, false);
3514 3509
3515 cfg80211_send_assoc_timeout(sdata->dev, bssid); 3510 cfg80211_assoc_timeout(sdata->dev, bssid);
3516 } 3511 }
3517 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) 3512 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
3518 run_again(sdata, ifmgd->assoc_data->timeout); 3513 run_again(sdata, ifmgd->assoc_data->timeout);
@@ -4061,8 +4056,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4061 WLAN_REASON_UNSPECIFIED, 4056 WLAN_REASON_UNSPECIFIED,
4062 false, frame_buf); 4057 false, frame_buf);
4063 4058
4064 cfg80211_send_deauth(sdata->dev, frame_buf, 4059 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4065 sizeof(frame_buf)); 4060 sizeof(frame_buf));
4066 } 4061 }
4067 4062
4068 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 4063 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4124,8 +4119,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4124 WLAN_REASON_UNSPECIFIED, 4119 WLAN_REASON_UNSPECIFIED,
4125 false, frame_buf); 4120 false, frame_buf);
4126 4121
4127 cfg80211_send_deauth(sdata->dev, frame_buf, 4122 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4128 sizeof(frame_buf)); 4123 sizeof(frame_buf));
4129 } 4124 }
4130 4125
4131 if (ifmgd->auth_data && !ifmgd->auth_data->done) { 4126 if (ifmgd->auth_data && !ifmgd->auth_data->done) {
@@ -4272,6 +4267,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4272 4267
4273 ifmgd->assoc_data = assoc_data; 4268 ifmgd->assoc_data = assoc_data;
4274 ifmgd->dtim_period = 0; 4269 ifmgd->dtim_period = 0;
4270 ifmgd->have_beacon = false;
4275 4271
4276 err = ieee80211_prep_connection(sdata, req->bss, true); 4272 err = ieee80211_prep_connection(sdata, req->bss, true);
4277 if (err) 4273 if (err)
@@ -4303,7 +4299,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4303 ifmgd->dtim_period = tim->dtim_period; 4299 ifmgd->dtim_period = tim->dtim_period;
4304 dtim_count = tim->dtim_count; 4300 dtim_count = tim->dtim_count;
4305 } 4301 }
4306 assoc_data->have_beacon = true; 4302 ifmgd->have_beacon = true;
4307 assoc_data->timeout = jiffies; 4303 assoc_data->timeout = jiffies;
4308 assoc_data->timeout_started = true; 4304 assoc_data->timeout_started = true;
4309 4305
@@ -4378,8 +4374,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4378 4374
4379 out: 4375 out:
4380 if (report_frame) 4376 if (report_frame)
4381 cfg80211_send_deauth(sdata->dev, frame_buf, 4377 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4382 IEEE80211_DEAUTH_FRAME_LEN); 4378 IEEE80211_DEAUTH_FRAME_LEN);
4383 4379
4384 return 0; 4380 return 0;
4385} 4381}
@@ -4409,8 +4405,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
4409 req->reason_code, !req->local_state_change, 4405 req->reason_code, !req->local_state_change,
4410 frame_buf); 4406 frame_buf);
4411 4407
4412 cfg80211_send_disassoc(sdata->dev, frame_buf, 4408 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
4413 IEEE80211_DEAUTH_FRAME_LEN); 4409 IEEE80211_DEAUTH_FRAME_LEN);
4414 4410
4415 return 0; 4411 return 0;
4416} 4412}
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 c75d3db2a31c..22654452a561 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);