aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-07-09 08:40:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-14 14:30:07 -0400
commit9d139c810a2aa17365cc548d0cd2a189d8433c65 (patch)
treeef10ca55f93689ab97368376d277102d2527c961 /drivers/net/wireless
parentf3947e2dfa3b18f375b7acd03b7ee2877d0751fc (diff)
mac80211: revamp beacon configuration
This patch changes mac80211's beacon configuration handling to never pass skbs to the driver directly but rather always require the driver to use ieee80211_beacon_get(). Additionally, it introduces "change flags" on the config_interface() call to enable drivers to figure out what is changing. Finally, it removes the beacon_update() driver callback in favour of having IBSS beacon delivered by ieee80211_beacon_get() as well. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath5k/base.c13
-rw-r--r--drivers/net/wireless/b43/main.c48
-rw-r--r--drivers/net/wireless/b43legacy/main.c45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c18
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c22
14 files changed, 115 insertions, 94 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index a43e9b25169b..217d506527a9 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops = {
207 .get_tx_stats = ath5k_get_tx_stats, 207 .get_tx_stats = ath5k_get_tx_stats,
208 .get_tsf = ath5k_get_tsf, 208 .get_tsf = ath5k_get_tsf,
209 .reset_tsf = ath5k_reset_tsf, 209 .reset_tsf = ath5k_reset_tsf,
210 .beacon_update = ath5k_beacon_update,
211}; 210};
212 211
213/* 212/*
@@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
2785 * a clean way of letting us retrieve this yet. */ 2784 * a clean way of letting us retrieve this yet. */
2786 ath5k_hw_set_associd(ah, ah->ah_bssid, 0); 2785 ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
2787 } 2786 }
2787
2788 if (conf->changed & IEEE80211_IFCC_BEACON &&
2789 vif->type == IEEE80211_IF_TYPE_IBSS) {
2790 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
2791 if (!beacon) {
2792 ret = -ENOMEM;
2793 goto unlock;
2794 }
2795 /* call old handler for now */
2796 ath5k_beacon_update(hw, beacon);
2797 }
2798
2788 mutex_unlock(&sc->lock); 2799 mutex_unlock(&sc->lock);
2789 2800
2790 return ath5k_reset(hw); 2801 return ath5k_reset(hw);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 9d2eb273b726..381dbd33dfc2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
1675 1675
1676/* Asynchronously update the packet templates in template RAM. 1676/* Asynchronously update the packet templates in template RAM.
1677 * Locking: Requires wl->irq_lock to be locked. */ 1677 * Locking: Requires wl->irq_lock to be locked. */
1678static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) 1678static void b43_update_templates(struct b43_wl *wl)
1679{ 1679{
1680 struct sk_buff *beacon;
1681
1680 /* This is the top half of the ansynchronous beacon update. 1682 /* This is the top half of the ansynchronous beacon update.
1681 * The bottom half is the beacon IRQ. 1683 * The bottom half is the beacon IRQ.
1682 * Beacon update must be asynchronous to avoid sending an 1684 * Beacon update must be asynchronous to avoid sending an
1683 * invalid beacon. This can happen for example, if the firmware 1685 * invalid beacon. This can happen for example, if the firmware
1684 * transmits a beacon while we are updating it. */ 1686 * transmits a beacon while we are updating it. */
1685 1687
1688 /* We could modify the existing beacon and set the aid bit in
1689 * the TIM field, but that would probably require resizing and
1690 * moving of data within the beacon template.
1691 * Simply request a new beacon and let mac80211 do the hard work. */
1692 beacon = ieee80211_beacon_get(wl->hw, wl->vif);
1693 if (unlikely(!beacon))
1694 return;
1695
1686 if (wl->current_beacon) 1696 if (wl->current_beacon)
1687 dev_kfree_skb_any(wl->current_beacon); 1697 dev_kfree_skb_any(wl->current_beacon);
1688 wl->current_beacon = beacon; 1698 wl->current_beacon = beacon;
@@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
3645 if (b43_status(dev) >= B43_STAT_INITIALIZED) { 3655 if (b43_status(dev) >= B43_STAT_INITIALIZED) {
3646 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) || 3656 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
3647 b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) { 3657 b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) {
3648 B43_WARN_ON(conf->type != wl->if_type); 3658 B43_WARN_ON(vif->type != wl->if_type);
3649 b43_set_ssid(dev, conf->ssid, conf->ssid_len); 3659 if (conf->changed & IEEE80211_IFCC_SSID)
3650 if (conf->beacon) 3660 b43_set_ssid(dev, conf->ssid, conf->ssid_len);
3651 b43_update_templates(wl, conf->beacon); 3661 if (conf->changed & IEEE80211_IFCC_BEACON)
3662 b43_update_templates(wl);
3663 } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
3664 if (conf->changed & IEEE80211_IFCC_BEACON)
3665 b43_update_templates(wl);
3652 } 3666 }
3653 b43_write_mac_bssid_templates(dev); 3667 b43_write_mac_bssid_templates(dev);
3654 } 3668 }
@@ -4336,31 +4350,10 @@ out_unlock:
4336static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) 4350static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
4337{ 4351{
4338 struct b43_wl *wl = hw_to_b43_wl(hw); 4352 struct b43_wl *wl = hw_to_b43_wl(hw);
4339 struct sk_buff *beacon;
4340 unsigned long flags;
4341
4342 /* We could modify the existing beacon and set the aid bit in
4343 * the TIM field, but that would probably require resizing and
4344 * moving of data within the beacon template.
4345 * Simply request a new beacon and let mac80211 do the hard work. */
4346 beacon = ieee80211_beacon_get(hw, wl->vif);
4347 if (unlikely(!beacon))
4348 return -ENOMEM;
4349 spin_lock_irqsave(&wl->irq_lock, flags);
4350 b43_update_templates(wl, beacon);
4351 spin_unlock_irqrestore(&wl->irq_lock, flags);
4352
4353 return 0;
4354}
4355
4356static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
4357 struct sk_buff *beacon)
4358{
4359 struct b43_wl *wl = hw_to_b43_wl(hw);
4360 unsigned long flags; 4353 unsigned long flags;
4361 4354
4362 spin_lock_irqsave(&wl->irq_lock, flags); 4355 spin_lock_irqsave(&wl->irq_lock, flags);
4363 b43_update_templates(wl, beacon); 4356 b43_update_templates(wl);
4364 spin_unlock_irqrestore(&wl->irq_lock, flags); 4357 spin_unlock_irqrestore(&wl->irq_lock, flags);
4365 4358
4366 return 0; 4359 return 0;
@@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw_ops = {
4391 .stop = b43_op_stop, 4384 .stop = b43_op_stop,
4392 .set_retry_limit = b43_op_set_retry_limit, 4385 .set_retry_limit = b43_op_set_retry_limit,
4393 .set_tim = b43_op_beacon_set_tim, 4386 .set_tim = b43_op_beacon_set_tim,
4394 .beacon_update = b43_op_ibss_beacon_update,
4395 .sta_notify = b43_op_sta_notify, 4387 .sta_notify = b43_op_sta_notify,
4396}; 4388};
4397 4389
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 069157eea05c..a1b8bf3ee732 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -1138,14 +1138,22 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
1138 1138
1139/* Asynchronously update the packet templates in template RAM. 1139/* Asynchronously update the packet templates in template RAM.
1140 * Locking: Requires wl->irq_lock to be locked. */ 1140 * Locking: Requires wl->irq_lock to be locked. */
1141static void b43legacy_update_templates(struct b43legacy_wl *wl, 1141static void b43legacy_update_templates(struct b43legacy_wl *wl)
1142 struct sk_buff *beacon)
1143{ 1142{
1143 struct sk_buff *beacon;
1144 /* This is the top half of the ansynchronous beacon update. The bottom 1144 /* This is the top half of the ansynchronous beacon update. The bottom
1145 * half is the beacon IRQ. Beacon update must be asynchronous to avoid 1145 * half is the beacon IRQ. Beacon update must be asynchronous to avoid
1146 * sending an invalid beacon. This can happen for example, if the 1146 * sending an invalid beacon. This can happen for example, if the
1147 * firmware transmits a beacon while we are updating it. */ 1147 * firmware transmits a beacon while we are updating it. */
1148 1148
1149 /* We could modify the existing beacon and set the aid bit in the TIM
1150 * field, but that would probably require resizing and moving of data
1151 * within the beacon template. Simply request a new beacon and let
1152 * mac80211 do the hard work. */
1153 beacon = ieee80211_beacon_get(wl->hw, wl->vif);
1154 if (unlikely(!beacon))
1155 return;
1156
1149 if (wl->current_beacon) 1157 if (wl->current_beacon)
1150 dev_kfree_skb_any(wl->current_beacon); 1158 dev_kfree_skb_any(wl->current_beacon);
1151 wl->current_beacon = beacon; 1159 wl->current_beacon = beacon;
@@ -2727,10 +2735,13 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
2727 memset(wl->bssid, 0, ETH_ALEN); 2735 memset(wl->bssid, 0, ETH_ALEN);
2728 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { 2736 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
2729 if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { 2737 if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
2730 B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); 2738 B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
2731 b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len); 2739 b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
2732 if (conf->beacon) 2740 if (conf->changed & IEEE80211_IFCC_BEACON)
2733 b43legacy_update_templates(wl, conf->beacon); 2741 b43legacy_update_templates(wl);
2742 } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
2743 if (conf->changed & IEEE80211_IFCC_BEACON)
2744 b43legacy_update_templates(wl);
2734 } 2745 }
2735 b43legacy_write_mac_bssid_templates(dev); 2746 b43legacy_write_mac_bssid_templates(dev);
2736 } 2747 }
@@ -3396,31 +3407,10 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
3396 int aid, int set) 3407 int aid, int set)
3397{ 3408{
3398 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); 3409 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3399 struct sk_buff *beacon;
3400 unsigned long flags;
3401
3402 /* We could modify the existing beacon and set the aid bit in the TIM
3403 * field, but that would probably require resizing and moving of data
3404 * within the beacon template. Simply request a new beacon and let
3405 * mac80211 do the hard work. */
3406 beacon = ieee80211_beacon_get(hw, wl->vif);
3407 if (unlikely(!beacon))
3408 return -ENOMEM;
3409 spin_lock_irqsave(&wl->irq_lock, flags);
3410 b43legacy_update_templates(wl, beacon);
3411 spin_unlock_irqrestore(&wl->irq_lock, flags);
3412
3413 return 0;
3414}
3415
3416static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
3417 struct sk_buff *beacon)
3418{
3419 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3420 unsigned long flags; 3410 unsigned long flags;
3421 3411
3422 spin_lock_irqsave(&wl->irq_lock, flags); 3412 spin_lock_irqsave(&wl->irq_lock, flags);
3423 b43legacy_update_templates(wl, beacon); 3413 b43legacy_update_templates(wl);
3424 spin_unlock_irqrestore(&wl->irq_lock, flags); 3414 spin_unlock_irqrestore(&wl->irq_lock, flags);
3425 3415
3426 return 0; 3416 return 0;
@@ -3440,7 +3430,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
3440 .stop = b43legacy_op_stop, 3430 .stop = b43legacy_op_stop,
3441 .set_retry_limit = b43legacy_op_set_retry_limit, 3431 .set_retry_limit = b43legacy_op_set_retry_limit,
3442 .set_tim = b43legacy_op_beacon_set_tim, 3432 .set_tim = b43legacy_op_beacon_set_tim,
3443 .beacon_update = b43legacy_op_ibss_beacon_update,
3444}; 3433};
3445 3434
3446/* Hard-reset the chip. Do not call this directly. 3435/* Hard-reset the chip. Do not call this directly.
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 1a7d18fea89d..7d015f86ee8c 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6907,6 +6907,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
6907 * clear sta table, add BCAST sta... */ 6907 * clear sta table, add BCAST sta... */
6908} 6908}
6909 6909
6910/* temporary */
6911static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
6912
6910static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, 6913static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
6911 struct ieee80211_vif *vif, 6914 struct ieee80211_vif *vif,
6912 struct ieee80211_if_conf *conf) 6915 struct ieee80211_if_conf *conf)
@@ -6924,10 +6927,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
6924 return 0; 6927 return 0;
6925 } 6928 }
6926 6929
6930 /* handle this temporarily here */
6931 if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
6932 conf->changed & IEEE80211_IFCC_BEACON) {
6933 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
6934 if (!beacon)
6935 return -ENOMEM;
6936 rc = iwl3945_mac_beacon_update(hw, beacon);
6937 if (rc)
6938 return rc;
6939 }
6940
6927 /* XXX: this MUST use conf->mac_addr */ 6941 /* XXX: this MUST use conf->mac_addr */
6928 6942
6929 if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && 6943 if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
6930 (!conf->beacon || !conf->ssid_len)) { 6944 (!conf->ssid_len)) {
6931 IWL_DEBUG_MAC80211 6945 IWL_DEBUG_MAC80211
6932 ("Leaving in AP mode because HostAPD is not ready.\n"); 6946 ("Leaving in AP mode because HostAPD is not ready.\n");
6933 return 0; 6947 return 0;
@@ -6959,7 +6973,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
6959 if (priv->ibss_beacon) 6973 if (priv->ibss_beacon)
6960 dev_kfree_skb(priv->ibss_beacon); 6974 dev_kfree_skb(priv->ibss_beacon);
6961 6975
6962 priv->ibss_beacon = conf->beacon; 6976 priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
6963 } 6977 }
6964 6978
6965 if (iwl3945_is_rfkill(priv)) 6979 if (iwl3945_is_rfkill(priv))
@@ -7940,7 +7954,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
7940 .conf_tx = iwl3945_mac_conf_tx, 7954 .conf_tx = iwl3945_mac_conf_tx,
7941 .get_tsf = iwl3945_mac_get_tsf, 7955 .get_tsf = iwl3945_mac_get_tsf,
7942 .reset_tsf = iwl3945_mac_reset_tsf, 7956 .reset_tsf = iwl3945_mac_reset_tsf,
7943 .beacon_update = iwl3945_mac_beacon_update,
7944 .hw_scan = iwl3945_mac_hw_scan 7957 .hw_scan = iwl3945_mac_hw_scan
7945}; 7958};
7946 7959
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 7f65d9123b2a..d6fe0ded59d7 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2912,6 +2912,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
2912 * clear sta table, add BCAST sta... */ 2912 * clear sta table, add BCAST sta... */
2913} 2913}
2914 2914
2915/* temporary */
2916static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
2917
2915static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, 2918static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
2916 struct ieee80211_vif *vif, 2919 struct ieee80211_vif *vif,
2917 struct ieee80211_if_conf *conf) 2920 struct ieee80211_if_conf *conf)
@@ -2929,8 +2932,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
2929 return 0; 2932 return 0;
2930 } 2933 }
2931 2934
2935 if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
2936 conf->changed & IEEE80211_IFCC_BEACON) {
2937 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
2938 if (!beacon)
2939 return -ENOMEM;
2940 rc = iwl4965_mac_beacon_update(hw, beacon);
2941 if (rc)
2942 return rc;
2943 }
2944
2932 if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && 2945 if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
2933 (!conf->beacon || !conf->ssid_len)) { 2946 (!conf->ssid_len)) {
2934 IWL_DEBUG_MAC80211 2947 IWL_DEBUG_MAC80211
2935 ("Leaving in AP mode because HostAPD is not ready.\n"); 2948 ("Leaving in AP mode because HostAPD is not ready.\n");
2936 return 0; 2949 return 0;
@@ -2962,7 +2975,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
2962 if (priv->ibss_beacon) 2975 if (priv->ibss_beacon)
2963 dev_kfree_skb(priv->ibss_beacon); 2976 dev_kfree_skb(priv->ibss_beacon);
2964 2977
2965 priv->ibss_beacon = conf->beacon; 2978 priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
2966 } 2979 }
2967 2980
2968 if (iwl_is_rfkill(priv)) 2981 if (iwl_is_rfkill(priv))
@@ -4090,7 +4103,6 @@ static struct ieee80211_ops iwl4965_hw_ops = {
4090 .get_tx_stats = iwl4965_mac_get_tx_stats, 4103 .get_tx_stats = iwl4965_mac_get_tx_stats,
4091 .conf_tx = iwl4965_mac_conf_tx, 4104 .conf_tx = iwl4965_mac_conf_tx,
4092 .reset_tsf = iwl4965_mac_reset_tsf, 4105 .reset_tsf = iwl4965_mac_reset_tsf,
4093 .beacon_update = iwl4965_mac_beacon_update,
4094 .bss_info_changed = iwl4965_bss_info_changed, 4106 .bss_info_changed = iwl4965_bss_info_changed,
4095 .ampdu_action = iwl4965_mac_ampdu_action, 4107 .ampdu_action = iwl4965_mac_ampdu_action,
4096 .hw_scan = iwl4965_mac_hw_scan 4108 .hw_scan = iwl4965_mac_hw_scan
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index ee953ca0c6a3..89b874ca6107 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1581,7 +1581,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
1581 .conf_tx = rt2400pci_conf_tx, 1581 .conf_tx = rt2400pci_conf_tx,
1582 .get_tx_stats = rt2x00mac_get_tx_stats, 1582 .get_tx_stats = rt2x00mac_get_tx_stats,
1583 .get_tsf = rt2400pci_get_tsf, 1583 .get_tsf = rt2400pci_get_tsf,
1584 .beacon_update = rt2400pci_beacon_update,
1585 .tx_last_beacon = rt2400pci_tx_last_beacon, 1584 .tx_last_beacon = rt2400pci_tx_last_beacon,
1586}; 1585};
1587 1586
@@ -1601,6 +1600,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
1601 .write_tx_data = rt2x00pci_write_tx_data, 1600 .write_tx_data = rt2x00pci_write_tx_data,
1602 .kick_tx_queue = rt2400pci_kick_tx_queue, 1601 .kick_tx_queue = rt2400pci_kick_tx_queue,
1603 .fill_rxdone = rt2400pci_fill_rxdone, 1602 .fill_rxdone = rt2400pci_fill_rxdone,
1603 .beacon_update = rt2400pci_beacon_update,
1604 .config_filter = rt2400pci_config_filter, 1604 .config_filter = rt2400pci_config_filter,
1605 .config_intf = rt2400pci_config_intf, 1605 .config_intf = rt2400pci_config_intf,
1606 .config_erp = rt2400pci_config_erp, 1606 .config_erp = rt2400pci_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 0423c251c78e..a64bb18322e9 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1875,7 +1875,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
1875 .conf_tx = rt2x00mac_conf_tx, 1875 .conf_tx = rt2x00mac_conf_tx,
1876 .get_tx_stats = rt2x00mac_get_tx_stats, 1876 .get_tx_stats = rt2x00mac_get_tx_stats,
1877 .get_tsf = rt2500pci_get_tsf, 1877 .get_tsf = rt2500pci_get_tsf,
1878 .beacon_update = rt2500pci_beacon_update,
1879 .tx_last_beacon = rt2500pci_tx_last_beacon, 1878 .tx_last_beacon = rt2500pci_tx_last_beacon,
1880}; 1879};
1881 1880
@@ -1895,6 +1894,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
1895 .write_tx_data = rt2x00pci_write_tx_data, 1894 .write_tx_data = rt2x00pci_write_tx_data,
1896 .kick_tx_queue = rt2500pci_kick_tx_queue, 1895 .kick_tx_queue = rt2500pci_kick_tx_queue,
1897 .fill_rxdone = rt2500pci_fill_rxdone, 1896 .fill_rxdone = rt2500pci_fill_rxdone,
1897 .beacon_update = rt2500pci_beacon_update,
1898 .config_filter = rt2500pci_config_filter, 1898 .config_filter = rt2500pci_config_filter,
1899 .config_intf = rt2500pci_config_intf, 1899 .config_intf = rt2500pci_config_intf,
1900 .config_erp = rt2500pci_config_erp, 1900 .config_erp = rt2500pci_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 0dd1cb537b92..8ce1726d7508 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1775,7 +1775,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
1775 .bss_info_changed = rt2x00mac_bss_info_changed, 1775 .bss_info_changed = rt2x00mac_bss_info_changed,
1776 .conf_tx = rt2x00mac_conf_tx, 1776 .conf_tx = rt2x00mac_conf_tx,
1777 .get_tx_stats = rt2x00mac_get_tx_stats, 1777 .get_tx_stats = rt2x00mac_get_tx_stats,
1778 .beacon_update = rt2500usb_beacon_update,
1779}; 1778};
1780 1779
1781static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { 1780static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1793,6 +1792,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
1793 .get_tx_data_len = rt2500usb_get_tx_data_len, 1792 .get_tx_data_len = rt2500usb_get_tx_data_len,
1794 .kick_tx_queue = rt2500usb_kick_tx_queue, 1793 .kick_tx_queue = rt2500usb_kick_tx_queue,
1795 .fill_rxdone = rt2500usb_fill_rxdone, 1794 .fill_rxdone = rt2500usb_fill_rxdone,
1795 .beacon_update = rt2500usb_beacon_update,
1796 .config_filter = rt2500usb_config_filter, 1796 .config_filter = rt2500usb_config_filter,
1797 .config_intf = rt2500usb_config_intf, 1797 .config_intf = rt2500usb_config_intf,
1798 .config_erp = rt2500usb_config_erp, 1798 .config_erp = rt2500usb_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c07d9ef383f0..9ad3ce43e6cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -534,6 +534,8 @@ struct rt2x00lib_ops {
534 /* 534 /*
535 * Configuration handlers. 535 * Configuration handlers.
536 */ 536 */
537 int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn);
538
537 void (*config_filter) (struct rt2x00_dev *rt2x00dev, 539 void (*config_filter) (struct rt2x00_dev *rt2x00dev,
538 const unsigned int filter_flags); 540 const unsigned int filter_flags);
539 void (*config_intf) (struct rt2x00_dev *rt2x00dev, 541 void (*config_intf) (struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index b48c04e80a38..1b7f87799a7e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
409{ 409{
410 struct rt2x00_dev *rt2x00dev = data; 410 struct rt2x00_dev *rt2x00dev = data;
411 struct rt2x00_intf *intf = vif_to_intf(vif); 411 struct rt2x00_intf *intf = vif_to_intf(vif);
412 struct sk_buff *skb;
413 struct ieee80211_bss_conf conf; 412 struct ieee80211_bss_conf conf;
414 int delayed_flags; 413 int delayed_flags;
415 414
@@ -436,10 +435,11 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
436 return; 435 return;
437 436
438 if (delayed_flags & DELAYED_UPDATE_BEACON) { 437 if (delayed_flags & DELAYED_UPDATE_BEACON) {
439 skb = ieee80211_beacon_get(rt2x00dev->hw, vif); 438 struct ieee80211_if_conf conf;
440 if (skb && 439 conf.bssid = conf.ssid = NULL;
441 rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb)) 440 conf.ssid_len = 0;
442 dev_kfree_skb(skb); 441 conf.changed = IEEE80211_IFCC_BEACON;
442 rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf);
443 } 443 }
444 444
445 if (delayed_flags & DELAYED_CONFIG_ERP) 445 if (delayed_flags & DELAYED_CONFIG_ERP)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 3a1fb6d47e5d..84b51f49175e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -348,6 +348,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
348{ 348{
349 struct rt2x00_dev *rt2x00dev = hw->priv; 349 struct rt2x00_dev *rt2x00dev = hw->priv;
350 struct rt2x00_intf *intf = vif_to_intf(vif); 350 struct rt2x00_intf *intf = vif_to_intf(vif);
351 struct sk_buff *beacon;
351 int status; 352 int status;
352 353
353 /* 354 /*
@@ -363,8 +364,11 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
363 * If the interface does not work in master mode, 364 * If the interface does not work in master mode,
364 * then the bssid value in the interface structure 365 * then the bssid value in the interface structure
365 * should now be set. 366 * should now be set.
367 *
368 * conf->bssid can be NULL if coming from the internal
369 * beacon update routine.
366 */ 370 */
367 if (conf->type != IEEE80211_IF_TYPE_AP) 371 if (conf->bssid && vif->type != IEEE80211_IF_TYPE_AP)
368 memcpy(&intf->bssid, conf->bssid, ETH_ALEN); 372 memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
369 373
370 spin_unlock(&intf->lock); 374 spin_unlock(&intf->lock);
@@ -375,17 +379,23 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
375 * values as arguments we make keep access to rt2x00_intf thread safe 379 * values as arguments we make keep access to rt2x00_intf thread safe
376 * even without the lock. 380 * even without the lock.
377 */ 381 */
378 rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid); 382 rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, conf->bssid);
379 383
380 /* 384 /*
381 * We only need to initialize the beacon when master mode is enabled. 385 * We only need to initialize the beacon when in master/ibss mode.
382 */ 386 */
383 if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) 387 if ((vif->type != IEEE80211_IF_TYPE_AP &&
388 vif->type != IEEE80211_IF_TYPE_IBSS) ||
389 !(conf->changed & IEEE80211_IFCC_BEACON))
384 return 0; 390 return 0;
385 391
386 status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon); 392 beacon = ieee80211_beacon_get(rt2x00dev->hw, vif);
393 if (!beacon)
394 return -ENOMEM;
395
396 status = rt2x00dev->ops->lib->beacon_update(rt2x00dev->hw, beacon);
387 if (status) 397 if (status)
388 dev_kfree_skb(conf->beacon); 398 dev_kfree_skb(beacon);
389 399
390 return status; 400 return status;
391} 401}
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index bbf1048f6400..852d193a11a9 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2427,7 +2427,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
2427 .conf_tx = rt2x00mac_conf_tx, 2427 .conf_tx = rt2x00mac_conf_tx,
2428 .get_tx_stats = rt2x00mac_get_tx_stats, 2428 .get_tx_stats = rt2x00mac_get_tx_stats,
2429 .get_tsf = rt61pci_get_tsf, 2429 .get_tsf = rt61pci_get_tsf,
2430 .beacon_update = rt61pci_beacon_update,
2431}; 2430};
2432 2431
2433static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { 2432static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -2449,6 +2448,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
2449 .write_tx_data = rt2x00pci_write_tx_data, 2448 .write_tx_data = rt2x00pci_write_tx_data,
2450 .kick_tx_queue = rt61pci_kick_tx_queue, 2449 .kick_tx_queue = rt61pci_kick_tx_queue,
2451 .fill_rxdone = rt61pci_fill_rxdone, 2450 .fill_rxdone = rt61pci_fill_rxdone,
2451 .beacon_update = rt61pci_beacon_update,
2452 .config_filter = rt61pci_config_filter, 2452 .config_filter = rt61pci_config_filter,
2453 .config_intf = rt61pci_config_intf, 2453 .config_intf = rt61pci_config_intf,
2454 .config_erp = rt61pci_config_erp, 2454 .config_erp = rt61pci_config_erp,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 3ef318e098e7..657200972424 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2031,7 +2031,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
2031 .conf_tx = rt2x00mac_conf_tx, 2031 .conf_tx = rt2x00mac_conf_tx,
2032 .get_tx_stats = rt2x00mac_get_tx_stats, 2032 .get_tx_stats = rt2x00mac_get_tx_stats,
2033 .get_tsf = rt73usb_get_tsf, 2033 .get_tsf = rt73usb_get_tsf,
2034 .beacon_update = rt73usb_beacon_update,
2035}; 2034};
2036 2035
2037static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { 2036static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2052,6 +2051,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
2052 .get_tx_data_len = rt73usb_get_tx_data_len, 2051 .get_tx_data_len = rt73usb_get_tx_data_len,
2053 .kick_tx_queue = rt73usb_kick_tx_queue, 2052 .kick_tx_queue = rt73usb_kick_tx_queue,
2054 .fill_rxdone = rt73usb_fill_rxdone, 2053 .fill_rxdone = rt73usb_fill_rxdone,
2054 .beacon_update = rt73usb_beacon_update,
2055 .config_filter = rt73usb_config_filter, 2055 .config_filter = rt73usb_config_filter,
2056 .config_intf = rt73usb_config_intf, 2056 .config_intf = rt73usb_config_intf,
2057 .config_erp = rt73usb_config_erp, 2057 .config_erp = rt73usb_config_erp,
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 665f76af2fec..68e2749b2ce8 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -727,15 +727,19 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
727 if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || 727 if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
728 mac->type == IEEE80211_IF_TYPE_IBSS) { 728 mac->type == IEEE80211_IF_TYPE_IBSS) {
729 associated = true; 729 associated = true;
730 if (conf->beacon) { 730 if (conf->changed & IEEE80211_IFCC_BEACON) {
731 r = zd_mac_config_beacon(hw, conf->beacon); 731 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
732
733 if (!beacon)
734 return -ENOMEM;
735 r = zd_mac_config_beacon(hw, beacon);
732 if (r < 0) 736 if (r < 0)
733 return r; 737 return r;
734 r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | 738 r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
735 hw->conf.beacon_int); 739 hw->conf.beacon_int);
736 if (r < 0) 740 if (r < 0)
737 return r; 741 return r;
738 kfree_skb(conf->beacon); 742 kfree_skb(beacon);
739 } 743 }
740 } else 744 } else
741 associated = is_valid_ether_addr(conf->bssid); 745 associated = is_valid_ether_addr(conf->bssid);
@@ -889,17 +893,6 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
889 } 893 }
890} 894}
891 895
892static int zd_op_beacon_update(struct ieee80211_hw *hw,
893 struct sk_buff *skb)
894{
895 struct zd_mac *mac = zd_hw_mac(hw);
896 zd_mac_config_beacon(hw, skb);
897 kfree_skb(skb);
898 zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
899 hw->conf.beacon_int);
900 return 0;
901}
902
903static const struct ieee80211_ops zd_ops = { 896static const struct ieee80211_ops zd_ops = {
904 .tx = zd_op_tx, 897 .tx = zd_op_tx,
905 .start = zd_op_start, 898 .start = zd_op_start,
@@ -910,7 +903,6 @@ static const struct ieee80211_ops zd_ops = {
910 .config_interface = zd_op_config_interface, 903 .config_interface = zd_op_config_interface,
911 .configure_filter = zd_op_configure_filter, 904 .configure_filter = zd_op_configure_filter,
912 .bss_info_changed = zd_op_bss_info_changed, 905 .bss_info_changed = zd_op_bss_info_changed,
913 .beacon_update = zd_op_beacon_update,
914}; 906};
915 907
916struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) 908struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)