diff options
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/b43legacy/main.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_mac.c | 22 | ||||
-rw-r--r-- | include/net/mac80211.h | 49 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/main.c | 59 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 112 | ||||
-rw-r--r-- | net/mac80211/tx.c | 36 | ||||
-rw-r--r-- | net/mac80211/wext.c | 2 |
21 files changed, 226 insertions, 248 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. */ |
1678 | static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) | 1678 | static 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: | |||
4336 | static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) | 4350 | static 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 | |||
4356 | static 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. */ |
1141 | static void b43legacy_update_templates(struct b43legacy_wl *wl, | 1141 | static 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 | |||
3416 | static 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 */ | ||
6911 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
6912 | |||
6910 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | 6913 | static 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 */ | ||
2916 | static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
2917 | |||
2915 | static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | 2918 | static 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 | ||
1781 | static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | 1780 | static 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 | ||
2433 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | 2432 | static 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 | ||
2037 | static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | 2036 | static 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 | ||
892 | static 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 | |||
903 | static const struct ieee80211_ops zd_ops = { | 896 | static 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 | ||
916 | struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | 908 | struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9672a04c4f7b..47c072eab42c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -529,33 +529,38 @@ struct ieee80211_if_init_conf { | |||
529 | }; | 529 | }; |
530 | 530 | ||
531 | /** | 531 | /** |
532 | * enum ieee80211_if_conf_change - interface config change flags | ||
533 | * | ||
534 | * @IEEE80211_IFCC_BSSID: The BSSID changed. | ||
535 | * @IEEE80211_IFCC_SSID: The SSID changed. | ||
536 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed | ||
537 | * (currently AP and MESH only), use ieee80211_beacon_get(). | ||
538 | */ | ||
539 | enum ieee80211_if_conf_change { | ||
540 | IEEE80211_IFCC_BSSID = BIT(0), | ||
541 | IEEE80211_IFCC_SSID = BIT(1), | ||
542 | IEEE80211_IFCC_BEACON = BIT(2), | ||
543 | }; | ||
544 | |||
545 | /** | ||
532 | * struct ieee80211_if_conf - configuration of an interface | 546 | * struct ieee80211_if_conf - configuration of an interface |
533 | * | 547 | * |
534 | * @type: type of the interface. This is always the same as was specified in | 548 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. |
535 | * &struct ieee80211_if_init_conf. The type of an interface never changes | ||
536 | * during the life of the interface; this field is present only for | ||
537 | * convenience. | ||
538 | * @bssid: BSSID of the network we are associated to/creating. | 549 | * @bssid: BSSID of the network we are associated to/creating. |
539 | * @ssid: used (together with @ssid_len) by drivers for hardware that | 550 | * @ssid: used (together with @ssid_len) by drivers for hardware that |
540 | * generate beacons independently. The pointer is valid only during the | 551 | * generate beacons independently. The pointer is valid only during the |
541 | * config_interface() call, so copy the value somewhere if you need | 552 | * config_interface() call, so copy the value somewhere if you need |
542 | * it. | 553 | * it. |
543 | * @ssid_len: length of the @ssid field. | 554 | * @ssid_len: length of the @ssid field. |
544 | * @beacon: beacon template. Valid only if @host_gen_beacon_template in | ||
545 | * &struct ieee80211_hw is set. The driver is responsible of freeing | ||
546 | * the sk_buff. | ||
547 | * @beacon_control: tx_control for the beacon template, this field is only | ||
548 | * valid when the @beacon field was set. | ||
549 | * | 555 | * |
550 | * This structure is passed to the config_interface() callback of | 556 | * This structure is passed to the config_interface() callback of |
551 | * &struct ieee80211_hw. | 557 | * &struct ieee80211_hw. |
552 | */ | 558 | */ |
553 | struct ieee80211_if_conf { | 559 | struct ieee80211_if_conf { |
554 | int type; | 560 | u32 changed; |
555 | u8 *bssid; | 561 | u8 *bssid; |
556 | u8 *ssid; | 562 | u8 *ssid; |
557 | size_t ssid_len; | 563 | size_t ssid_len; |
558 | struct sk_buff *beacon; | ||
559 | }; | 564 | }; |
560 | 565 | ||
561 | /** | 566 | /** |
@@ -683,15 +688,6 @@ enum ieee80211_tkip_key_type { | |||
683 | * any particular flags. There are some exceptions to this rule, | 688 | * any particular flags. There are some exceptions to this rule, |
684 | * however, so you are advised to review these flags carefully. | 689 | * however, so you are advised to review these flags carefully. |
685 | * | 690 | * |
686 | * @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE: | ||
687 | * The device only needs to be supplied with a beacon template. | ||
688 | * If you need the host to generate each beacon then don't use | ||
689 | * this flag and call ieee80211_beacon_get() when you need the | ||
690 | * next beacon frame. Note that if you set this flag, you must | ||
691 | * implement the set_tim() callback for powersave mode to work | ||
692 | * properly. | ||
693 | * This flag is only relevant for access-point mode. | ||
694 | * | ||
695 | * @IEEE80211_HW_RX_INCLUDES_FCS: | 691 | * @IEEE80211_HW_RX_INCLUDES_FCS: |
696 | * Indicates that received frames passed to the stack include | 692 | * Indicates that received frames passed to the stack include |
697 | * the FCS at the end. | 693 | * the FCS at the end. |
@@ -1151,17 +1147,6 @@ enum ieee80211_ampdu_mlme_action { | |||
1151 | * function is optional if the firmware/hardware takes full care of | 1147 | * function is optional if the firmware/hardware takes full care of |
1152 | * TSF synchronization. | 1148 | * TSF synchronization. |
1153 | * | 1149 | * |
1154 | * @beacon_update: Setup beacon data for IBSS beacons. Unlike access point, | ||
1155 | * IBSS uses a fixed beacon frame which is configured using this | ||
1156 | * function. | ||
1157 | * If the driver returns success (0) from this callback, it owns | ||
1158 | * the skb. That means the driver is responsible to kfree_skb() it. | ||
1159 | * The control structure is not dynamically allocated. That means the | ||
1160 | * driver does not own the pointer and if it needs it somewhere | ||
1161 | * outside of the context of this function, it must copy it | ||
1162 | * somewhere else. | ||
1163 | * This handler is required only for IBSS mode. | ||
1164 | * | ||
1165 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. | 1150 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. |
1166 | * This is needed only for IBSS mode and the result of this function is | 1151 | * This is needed only for IBSS mode and the result of this function is |
1167 | * used to determine whether to reply to Probe Requests. | 1152 | * used to determine whether to reply to Probe Requests. |
@@ -1219,8 +1204,6 @@ struct ieee80211_ops { | |||
1219 | struct ieee80211_tx_queue_stats *stats); | 1204 | struct ieee80211_tx_queue_stats *stats); |
1220 | u64 (*get_tsf)(struct ieee80211_hw *hw); | 1205 | u64 (*get_tsf)(struct ieee80211_hw *hw); |
1221 | void (*reset_tsf)(struct ieee80211_hw *hw); | 1206 | void (*reset_tsf)(struct ieee80211_hw *hw); |
1222 | int (*beacon_update)(struct ieee80211_hw *hw, | ||
1223 | struct sk_buff *skb); | ||
1224 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 1207 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
1225 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1208 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1226 | enum ieee80211_ampdu_mlme_action action, | 1209 | enum ieee80211_ampdu_mlme_action action, |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ea0301025c15..8e7ba0e62cf5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -469,7 +469,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
469 | 469 | ||
470 | kfree(old); | 470 | kfree(old); |
471 | 471 | ||
472 | return ieee80211_if_config_beacon(sdata->dev); | 472 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
473 | } | 473 | } |
474 | 474 | ||
475 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 475 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -523,7 +523,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
523 | synchronize_rcu(); | 523 | synchronize_rcu(); |
524 | kfree(old); | 524 | kfree(old); |
525 | 525 | ||
526 | return ieee80211_if_config_beacon(dev); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
527 | } | 527 | } |
528 | 528 | ||
529 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 529 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 2146c0c436d2..934c3ef4f0bc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -854,8 +854,7 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
854 | 854 | ||
855 | /* ieee80211.c */ | 855 | /* ieee80211.c */ |
856 | int ieee80211_hw_config(struct ieee80211_local *local); | 856 | int ieee80211_hw_config(struct ieee80211_local *local); |
857 | int ieee80211_if_config(struct net_device *dev); | 857 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
858 | int ieee80211_if_config_beacon(struct net_device *dev); | ||
859 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 858 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
860 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | 859 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, |
861 | struct ieee80211_ht_info *req_ht_cap, | 860 | struct ieee80211_ht_info *req_ht_cap, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0759ab2ca3ff..36859e794928 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -307,7 +307,8 @@ static int ieee80211_open(struct net_device *dev) | |||
307 | if (res) | 307 | if (res) |
308 | goto err_stop; | 308 | goto err_stop; |
309 | 309 | ||
310 | ieee80211_if_config(dev); | 310 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
311 | ieee80211_start_mesh(sdata->dev); | ||
311 | changed |= ieee80211_reset_erp_info(dev); | 312 | changed |= ieee80211_reset_erp_info(dev); |
312 | ieee80211_bss_info_change_notify(sdata, changed); | 313 | ieee80211_bss_info_change_notify(sdata, changed); |
313 | ieee80211_enable_keys(sdata); | 314 | ieee80211_enable_keys(sdata); |
@@ -985,57 +986,47 @@ void ieee80211_if_setup(struct net_device *dev) | |||
985 | 986 | ||
986 | /* everything else */ | 987 | /* everything else */ |
987 | 988 | ||
988 | static int __ieee80211_if_config(struct net_device *dev, | 989 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) |
989 | struct sk_buff *beacon) | ||
990 | { | 990 | { |
991 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 991 | struct ieee80211_local *local = sdata->local; |
992 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
993 | struct ieee80211_if_conf conf; | 992 | struct ieee80211_if_conf conf; |
994 | 993 | ||
995 | if (!local->ops->config_interface || !netif_running(dev)) | 994 | if (WARN_ON(!netif_running(sdata->dev))) |
995 | return 0; | ||
996 | |||
997 | if (!local->ops->config_interface) | ||
996 | return 0; | 998 | return 0; |
997 | 999 | ||
998 | memset(&conf, 0, sizeof(conf)); | 1000 | memset(&conf, 0, sizeof(conf)); |
999 | conf.type = sdata->vif.type; | 1001 | conf.changed = changed; |
1002 | |||
1000 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1003 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || |
1001 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1004 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
1002 | conf.bssid = sdata->u.sta.bssid; | 1005 | conf.bssid = sdata->u.sta.bssid; |
1003 | conf.ssid = sdata->u.sta.ssid; | 1006 | conf.ssid = sdata->u.sta.ssid; |
1004 | conf.ssid_len = sdata->u.sta.ssid_len; | 1007 | conf.ssid_len = sdata->u.sta.ssid_len; |
1005 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1006 | conf.beacon = beacon; | ||
1007 | ieee80211_start_mesh(dev); | ||
1008 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 1008 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { |
1009 | conf.bssid = sdata->dev->dev_addr; | ||
1009 | conf.ssid = sdata->u.ap.ssid; | 1010 | conf.ssid = sdata->u.ap.ssid; |
1010 | conf.ssid_len = sdata->u.ap.ssid_len; | 1011 | conf.ssid_len = sdata->u.ap.ssid_len; |
1011 | conf.beacon = beacon; | 1012 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1013 | u8 zero[ETH_ALEN] = { 0 }; | ||
1014 | conf.bssid = zero; | ||
1015 | conf.ssid = zero; | ||
1016 | conf.ssid_len = 0; | ||
1017 | } else { | ||
1018 | WARN_ON(1); | ||
1019 | return -EINVAL; | ||
1012 | } | 1020 | } |
1013 | return local->ops->config_interface(local_to_hw(local), | ||
1014 | &sdata->vif, &conf); | ||
1015 | } | ||
1016 | 1021 | ||
1017 | int ieee80211_if_config(struct net_device *dev) | 1022 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) |
1018 | { | 1023 | return -EINVAL; |
1019 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1020 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1021 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | ||
1022 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | ||
1023 | return ieee80211_if_config_beacon(dev); | ||
1024 | return __ieee80211_if_config(dev, NULL); | ||
1025 | } | ||
1026 | 1024 | ||
1027 | int ieee80211_if_config_beacon(struct net_device *dev) | 1025 | if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID))) |
1028 | { | 1026 | return -EINVAL; |
1029 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1030 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1031 | struct sk_buff *skb; | ||
1032 | 1027 | ||
1033 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1028 | return local->ops->config_interface(local_to_hw(local), |
1034 | return 0; | 1029 | &sdata->vif, &conf); |
1035 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); | ||
1036 | if (!skb) | ||
1037 | return -ENOMEM; | ||
1038 | return __ieee80211_if_config(dev, skb); | ||
1039 | } | 1030 | } |
1040 | 1031 | ||
1041 | int ieee80211_hw_config(struct ieee80211_local *local) | 1032 | int ieee80211_hw_config(struct ieee80211_local *local) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 64d710a88b86..61d7f81bf45e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2406,8 +2406,6 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2406 | int res, rates, i, j; | 2406 | int res, rates, i, j; |
2407 | struct sk_buff *skb; | 2407 | struct sk_buff *skb; |
2408 | struct ieee80211_mgmt *mgmt; | 2408 | struct ieee80211_mgmt *mgmt; |
2409 | struct ieee80211_tx_info *control; | ||
2410 | struct rate_selection ratesel; | ||
2411 | u8 *pos; | 2409 | u8 *pos; |
2412 | struct ieee80211_sub_if_data *sdata; | 2410 | struct ieee80211_sub_if_data *sdata; |
2413 | struct ieee80211_supported_band *sband; | 2411 | struct ieee80211_supported_band *sband; |
@@ -2425,7 +2423,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2425 | local->ops->reset_tsf(local_to_hw(local)); | 2423 | local->ops->reset_tsf(local_to_hw(local)); |
2426 | } | 2424 | } |
2427 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 2425 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); |
2428 | res = ieee80211_if_config(dev); | 2426 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
2429 | if (res) | 2427 | if (res) |
2430 | return res; | 2428 | return res; |
2431 | 2429 | ||
@@ -2439,19 +2437,16 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2439 | if (res) | 2437 | if (res) |
2440 | return res; | 2438 | return res; |
2441 | 2439 | ||
2442 | /* Set beacon template */ | 2440 | /* Build IBSS probe response */ |
2443 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 2441 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
2444 | do { | 2442 | if (skb) { |
2445 | if (!skb) | ||
2446 | break; | ||
2447 | |||
2448 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2443 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2449 | 2444 | ||
2450 | mgmt = (struct ieee80211_mgmt *) | 2445 | mgmt = (struct ieee80211_mgmt *) |
2451 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 2446 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
2452 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 2447 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
2453 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 2448 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, |
2454 | IEEE80211_STYPE_BEACON); | 2449 | IEEE80211_STYPE_PROBE_RESP); |
2455 | memset(mgmt->da, 0xff, ETH_ALEN); | 2450 | memset(mgmt->da, 0xff, ETH_ALEN); |
2456 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 2451 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); |
2457 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 2452 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
@@ -2495,61 +2490,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2495 | memcpy(pos, &bss->supp_rates[8], rates); | 2490 | memcpy(pos, &bss->supp_rates[8], rates); |
2496 | } | 2491 | } |
2497 | 2492 | ||
2498 | control = IEEE80211_SKB_CB(skb); | 2493 | ifsta->probe_resp = skb; |
2499 | |||
2500 | rate_control_get_rate(dev, sband, skb, &ratesel); | ||
2501 | if (ratesel.rate_idx < 0) { | ||
2502 | printk(KERN_DEBUG "%s: Failed to determine TX rate " | ||
2503 | "for IBSS beacon\n", dev->name); | ||
2504 | break; | ||
2505 | } | ||
2506 | control->control.vif = &sdata->vif; | ||
2507 | control->tx_rate_idx = ratesel.rate_idx; | ||
2508 | if (sdata->bss_conf.use_short_preamble && | ||
2509 | sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | ||
2510 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | ||
2511 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
2512 | control->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
2513 | control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
2514 | control->control.retry_limit = 1; | ||
2515 | |||
2516 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); | ||
2517 | if (ifsta->probe_resp) { | ||
2518 | mgmt = (struct ieee80211_mgmt *) | ||
2519 | ifsta->probe_resp->data; | ||
2520 | mgmt->frame_control = | ||
2521 | IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
2522 | IEEE80211_STYPE_PROBE_RESP); | ||
2523 | } else { | ||
2524 | printk(KERN_DEBUG "%s: Could not allocate ProbeResp " | ||
2525 | "template for IBSS\n", dev->name); | ||
2526 | } | ||
2527 | |||
2528 | if (local->ops->beacon_update && | ||
2529 | local->ops->beacon_update(local_to_hw(local), skb) == 0) { | ||
2530 | printk(KERN_DEBUG "%s: Configured IBSS beacon " | ||
2531 | "template\n", dev->name); | ||
2532 | skb = NULL; | ||
2533 | } | ||
2534 | |||
2535 | rates = 0; | ||
2536 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2537 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
2538 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; | ||
2539 | for (j = 0; j < sband->n_bitrates; j++) | ||
2540 | if (sband->bitrates[j].bitrate == bitrate) | ||
2541 | rates |= BIT(j); | ||
2542 | } | ||
2543 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2544 | 2494 | ||
2545 | ieee80211_sta_def_wmm_params(dev, bss, 1); | 2495 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
2546 | } while (0); | 2496 | } |
2547 | 2497 | ||
2548 | if (skb) { | 2498 | rates = 0; |
2549 | printk(KERN_DEBUG "%s: Failed to configure IBSS beacon " | 2499 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2550 | "template\n", dev->name); | 2500 | for (i = 0; i < bss->supp_rates_len; i++) { |
2551 | dev_kfree_skb(skb); | 2501 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; |
2502 | for (j = 0; j < sband->n_bitrates; j++) | ||
2503 | if (sband->bitrates[j].bitrate == bitrate) | ||
2504 | rates |= BIT(j); | ||
2552 | } | 2505 | } |
2506 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2507 | |||
2508 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2553 | 2509 | ||
2554 | ifsta->state = IEEE80211_IBSS_JOINED; | 2510 | ifsta->state = IEEE80211_IBSS_JOINED; |
2555 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 2511 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
@@ -3333,7 +3289,7 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, | |||
3333 | 3289 | ||
3334 | free_plinks = mesh_plink_availables(sdata); | 3290 | free_plinks = mesh_plink_availables(sdata); |
3335 | if (free_plinks != sdata->u.sta.accepting_plinks) | 3291 | if (free_plinks != sdata->u.sta.accepting_plinks) |
3336 | ieee80211_if_config_beacon(dev); | 3292 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
3337 | 3293 | ||
3338 | mod_timer(&ifsta->timer, jiffies + | 3294 | mod_timer(&ifsta->timer, jiffies + |
3339 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | 3295 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); |
@@ -3757,28 +3713,45 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | |||
3757 | { | 3713 | { |
3758 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3714 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3759 | struct ieee80211_if_sta *ifsta; | 3715 | struct ieee80211_if_sta *ifsta; |
3716 | int res; | ||
3760 | 3717 | ||
3761 | if (len > IEEE80211_MAX_SSID_LEN) | 3718 | if (len > IEEE80211_MAX_SSID_LEN) |
3762 | return -EINVAL; | 3719 | return -EINVAL; |
3763 | 3720 | ||
3764 | ifsta = &sdata->u.sta; | 3721 | ifsta = &sdata->u.sta; |
3765 | 3722 | ||
3766 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) | 3723 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { |
3724 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); | ||
3725 | memcpy(ifsta->ssid, ssid, len); | ||
3726 | ifsta->ssid_len = len; | ||
3767 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | 3727 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
3768 | memcpy(ifsta->ssid, ssid, len); | 3728 | |
3769 | memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len); | 3729 | res = 0; |
3770 | ifsta->ssid_len = len; | 3730 | /* |
3731 | * Hack! MLME code needs to be cleaned up to have different | ||
3732 | * entry points for configuration and internal selection change | ||
3733 | */ | ||
3734 | if (netif_running(sdata->dev)) | ||
3735 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
3736 | if (res) { | ||
3737 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
3738 | "the low-level driver\n", dev->name); | ||
3739 | return res; | ||
3740 | } | ||
3741 | } | ||
3771 | 3742 | ||
3772 | if (len) | 3743 | if (len) |
3773 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 3744 | ifsta->flags |= IEEE80211_STA_SSID_SET; |
3774 | else | 3745 | else |
3775 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | 3746 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; |
3747 | |||
3776 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | 3748 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && |
3777 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | 3749 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { |
3778 | ifsta->ibss_join_req = jiffies; | 3750 | ifsta->ibss_join_req = jiffies; |
3779 | ifsta->state = IEEE80211_IBSS_SEARCH; | 3751 | ifsta->state = IEEE80211_IBSS_SEARCH; |
3780 | return ieee80211_sta_find_ibss(dev, ifsta); | 3752 | return ieee80211_sta_find_ibss(dev, ifsta); |
3781 | } | 3753 | } |
3754 | |||
3782 | return 0; | 3755 | return 0; |
3783 | } | 3756 | } |
3784 | 3757 | ||
@@ -3804,7 +3777,12 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) | |||
3804 | 3777 | ||
3805 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 3778 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
3806 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 3779 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
3807 | res = ieee80211_if_config(dev); | 3780 | res = 0; |
3781 | /* | ||
3782 | * Hack! See also ieee80211_sta_set_ssid. | ||
3783 | */ | ||
3784 | if (netif_running(sdata->dev)) | ||
3785 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | ||
3808 | if (res) { | 3786 | if (res) { |
3809 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | 3787 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
3810 | "the low-level driver\n", dev->name); | 3788 | "the low-level driver\n", dev->name); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a757dcc1208d..8843416e1460 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1788,17 +1788,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1788 | struct ieee80211_vif *vif) | 1788 | struct ieee80211_vif *vif) |
1789 | { | 1789 | { |
1790 | struct ieee80211_local *local = hw_to_local(hw); | 1790 | struct ieee80211_local *local = hw_to_local(hw); |
1791 | struct sk_buff *skb; | 1791 | struct sk_buff *skb = NULL; |
1792 | struct ieee80211_tx_info *info; | 1792 | struct ieee80211_tx_info *info; |
1793 | struct net_device *bdev; | 1793 | struct net_device *bdev; |
1794 | struct ieee80211_sub_if_data *sdata = NULL; | 1794 | struct ieee80211_sub_if_data *sdata = NULL; |
1795 | struct ieee80211_if_ap *ap = NULL; | 1795 | struct ieee80211_if_ap *ap = NULL; |
1796 | struct ieee80211_if_sta *ifsta = NULL; | ||
1796 | struct rate_selection rsel; | 1797 | struct rate_selection rsel; |
1797 | struct beacon_data *beacon; | 1798 | struct beacon_data *beacon; |
1798 | struct ieee80211_supported_band *sband; | 1799 | struct ieee80211_supported_band *sband; |
1799 | struct ieee80211_mgmt *mgmt; | 1800 | struct ieee80211_mgmt *mgmt; |
1800 | int *num_beacons; | 1801 | int *num_beacons; |
1801 | bool err = true; | ||
1802 | enum ieee80211_band band = local->hw.conf.channel->band; | 1802 | enum ieee80211_band band = local->hw.conf.channel->band; |
1803 | u8 *pos; | 1803 | u8 *pos; |
1804 | 1804 | ||
@@ -1852,9 +1852,24 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1852 | beacon->tail, beacon->tail_len); | 1852 | beacon->tail, beacon->tail_len); |
1853 | 1853 | ||
1854 | num_beacons = &ap->num_beacons; | 1854 | num_beacons = &ap->num_beacons; |
1855 | } else | ||
1856 | goto out; | ||
1857 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
1858 | struct ieee80211_hdr *hdr; | ||
1859 | ifsta = &sdata->u.sta; | ||
1855 | 1860 | ||
1856 | err = false; | 1861 | if (!ifsta->probe_resp) |
1857 | } | 1862 | goto out; |
1863 | |||
1864 | skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); | ||
1865 | if (!skb) | ||
1866 | goto out; | ||
1867 | |||
1868 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1869 | hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1870 | IEEE80211_STYPE_BEACON); | ||
1871 | |||
1872 | num_beacons = &ifsta->num_beacons; | ||
1858 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1873 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1859 | /* headroom, head length, tail length and maximum TIM length */ | 1874 | /* headroom, head length, tail length and maximum TIM length */ |
1860 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1875 | skb = dev_alloc_skb(local->tx_headroom + 400); |
@@ -1881,17 +1896,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1881 | mesh_mgmt_ies_add(skb, sdata->dev); | 1896 | mesh_mgmt_ies_add(skb, sdata->dev); |
1882 | 1897 | ||
1883 | num_beacons = &sdata->u.sta.num_beacons; | 1898 | num_beacons = &sdata->u.sta.num_beacons; |
1884 | 1899 | } else { | |
1885 | err = false; | 1900 | WARN_ON(1); |
1886 | } | ||
1887 | |||
1888 | if (err) { | ||
1889 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1890 | if (net_ratelimit()) | ||
1891 | printk(KERN_DEBUG "no beacon data avail for %s\n", | ||
1892 | bdev->name); | ||
1893 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
1894 | skb = NULL; | ||
1895 | goto out; | 1901 | goto out; |
1896 | } | 1902 | } |
1897 | 1903 | ||
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index c041db9556c7..34fa8ed1e784 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -444,7 +444,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
444 | memset(sdata->u.ap.ssid + len, 0, | 444 | memset(sdata->u.ap.ssid + len, 0, |
445 | IEEE80211_MAX_SSID_LEN - len); | 445 | IEEE80211_MAX_SSID_LEN - len); |
446 | sdata->u.ap.ssid_len = len; | 446 | sdata->u.ap.ssid_len = len; |
447 | return ieee80211_if_config(dev); | 447 | return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); |
448 | } | 448 | } |
449 | return -EOPNOTSUPP; | 449 | return -EOPNOTSUPP; |
450 | } | 450 | } |