diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-14 23:40:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-14 23:40:34 -0400 |
commit | fc943b12e48f9341bce48c2fadf094cc721aab93 (patch) | |
tree | 8c3244d7f5fae4edbfe0a5103789b0bc5c64f478 | |
parent | 72d9794f444734af56ef12833b496326643e2964 (diff) | |
parent | 4c9adafff7d910f142fe44fae37ed12c6b99f20f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
62 files changed, 1458 insertions, 1724 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 8319c462c9f0..db300e09c9ac 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -333,3 +333,13 @@ Why: This option was introduced just to allow older lm-sensors userspace | |||
333 | to keep working over the upgrade to 2.6.26. At the scheduled time of | 333 | to keep working over the upgrade to 2.6.26. At the scheduled time of |
334 | removal fixed lm-sensors (2.x or 3.x) should be readily available. | 334 | removal fixed lm-sensors (2.x or 3.x) should be readily available. |
335 | Who: Rene Herman <rene.herman@gmail.com> | 335 | Who: Rene Herman <rene.herman@gmail.com> |
336 | |||
337 | --------------------------- | ||
338 | |||
339 | What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS | ||
340 | (in net/core/net-sysfs.c) | ||
341 | When: After the only user (hal) has seen a release with the patches | ||
342 | for enough time, probably some time in 2010. | ||
343 | Why: Over 1K .text/.data size reduction, data is available in other | ||
344 | ways (ioctls) | ||
345 | Who: Johannes Berg <johannes@sipsolutions.net> | ||
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/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index bf6f6c1ed4cf..8d54502222a6 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -317,7 +317,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
317 | /* MAC control */ | 317 | /* MAC control */ |
318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
319 | mac_ctl |= B43_TXH_MAC_ACK; | 319 | mac_ctl |= B43_TXH_MAC_ACK; |
320 | if (!ieee80211_is_pspoll(fctl)) | 320 | /* use hardware sequence counter as the non-TID counter */ |
321 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) | ||
321 | mac_ctl |= B43_TXH_MAC_HWSEQ; | 322 | mac_ctl |= B43_TXH_MAC_HWSEQ; |
322 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 323 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
323 | mac_ctl |= B43_TXH_MAC_STMSDU; | 324 | mac_ctl |= B43_TXH_MAC_STMSDU; |
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/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index a3540787eb50..e969ed8d412d 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -295,8 +295,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
295 | /* MAC control */ | 295 | /* MAC control */ |
296 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 296 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
297 | mac_ctl |= B43legacy_TX4_MAC_ACK; | 297 | mac_ctl |= B43legacy_TX4_MAC_ACK; |
298 | if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && | 298 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) |
299 | ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) | ||
300 | mac_ctl |= B43legacy_TX4_MAC_HWSEQ; | 299 | mac_ctl |= B43legacy_TX4_MAC_HWSEQ; |
301 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 300 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
302 | mac_ctl |= B43legacy_TX4_MAC_STMSDU; | 301 | mac_ctl |= B43legacy_TX4_MAC_STMSDU; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 8b1528e52d43..6be1fe13fa57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -42,14 +42,11 @@ | |||
42 | #include "iwl-3945.h" | 42 | #include "iwl-3945.h" |
43 | #include "iwl-helpers.h" | 43 | #include "iwl-helpers.h" |
44 | 44 | ||
45 | #define IWL_1MB_RATE (128 * 1024) | ||
46 | #define IWL_LED_THRESHOLD (16) | ||
47 | #define IWL_MAX_BLINK_TBL (10) | ||
48 | 45 | ||
49 | static const struct { | 46 | static const struct { |
50 | u16 brightness; | 47 | u16 brightness; |
51 | u8 on_time; | 48 | u8 on_time; |
52 | u8 of_time; | 49 | u8 off_time; |
53 | } blink_tbl[] = | 50 | } blink_tbl[] = |
54 | { | 51 | { |
55 | {300, 25, 25}, | 52 | {300, 25, 25}, |
@@ -61,9 +58,16 @@ static const struct { | |||
61 | {15, 95, 95 }, | 58 | {15, 95, 95 }, |
62 | {10, 110, 110}, | 59 | {10, 110, 110}, |
63 | {5, 130, 130}, | 60 | {5, 130, 130}, |
64 | {0, 167, 167} | 61 | {0, 167, 167}, |
62 | /*SOLID_ON*/ | ||
63 | {-1, IWL_LED_SOLID, 0} | ||
65 | }; | 64 | }; |
66 | 65 | ||
66 | #define IWL_1MB_RATE (128 * 1024) | ||
67 | #define IWL_LED_THRESHOLD (16) | ||
68 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ | ||
69 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | ||
70 | |||
67 | static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, | 71 | static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, |
68 | struct iwl3945_cmd *cmd, | 72 | struct iwl3945_cmd *cmd, |
69 | struct sk_buff *skb) | 73 | struct sk_buff *skb) |
@@ -71,6 +75,10 @@ static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, | |||
71 | return 1; | 75 | return 1; |
72 | } | 76 | } |
73 | 77 | ||
78 | static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) | ||
79 | { | ||
80 | return fls(0x000000FF & (u32)brightness); | ||
81 | } | ||
74 | 82 | ||
75 | /* Send led command */ | 83 | /* Send led command */ |
76 | static int iwl_send_led_cmd(struct iwl3945_priv *priv, | 84 | static int iwl_send_led_cmd(struct iwl3945_priv *priv, |
@@ -81,49 +89,45 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv, | |||
81 | .len = sizeof(struct iwl3945_led_cmd), | 89 | .len = sizeof(struct iwl3945_led_cmd), |
82 | .data = led_cmd, | 90 | .data = led_cmd, |
83 | .meta.flags = CMD_ASYNC, | 91 | .meta.flags = CMD_ASYNC, |
84 | .meta.u.callback = iwl3945_led_cmd_callback | 92 | .meta.u.callback = iwl3945_led_cmd_callback, |
85 | }; | 93 | }; |
86 | 94 | ||
87 | return iwl3945_send_cmd(priv, &cmd); | 95 | return iwl3945_send_cmd(priv, &cmd); |
88 | } | 96 | } |
89 | 97 | ||
90 | 98 | ||
99 | |||
91 | /* Set led on command */ | 100 | /* Set led on command */ |
92 | static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) | 101 | static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, |
102 | unsigned int idx) | ||
93 | { | 103 | { |
94 | struct iwl3945_led_cmd led_cmd = { | 104 | struct iwl3945_led_cmd led_cmd = { |
95 | .id = led_id, | 105 | .id = led_id, |
96 | .on = IWL_LED_SOLID, | ||
97 | .off = 0, | ||
98 | .interval = IWL_DEF_LED_INTRVL | 106 | .interval = IWL_DEF_LED_INTRVL |
99 | }; | 107 | }; |
108 | |||
109 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | ||
110 | |||
111 | led_cmd.on = blink_tbl[idx].on_time; | ||
112 | led_cmd.off = blink_tbl[idx].off_time; | ||
113 | |||
100 | return iwl_send_led_cmd(priv, &led_cmd); | 114 | return iwl_send_led_cmd(priv, &led_cmd); |
101 | } | 115 | } |
102 | 116 | ||
117 | |||
118 | #if 1 | ||
103 | /* Set led on command */ | 119 | /* Set led on command */ |
104 | static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, | 120 | static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) |
105 | enum led_brightness brightness) | ||
106 | { | 121 | { |
107 | struct iwl3945_led_cmd led_cmd = { | 122 | struct iwl3945_led_cmd led_cmd = { |
108 | .id = led_id, | 123 | .id = led_id, |
109 | .on = brightness, | 124 | .on = IWL_LED_SOLID, |
110 | .off = brightness, | 125 | .off = 0, |
111 | .interval = IWL_DEF_LED_INTRVL | 126 | .interval = IWL_DEF_LED_INTRVL |
112 | }; | 127 | }; |
113 | if (brightness == LED_FULL) { | ||
114 | led_cmd.on = IWL_LED_SOLID; | ||
115 | led_cmd.off = 0; | ||
116 | } | ||
117 | return iwl_send_led_cmd(priv, &led_cmd); | 128 | return iwl_send_led_cmd(priv, &led_cmd); |
118 | } | 129 | } |
119 | 130 | ||
120 | /* Set led register off */ | ||
121 | static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id) | ||
122 | { | ||
123 | IWL_DEBUG_LED("led on %d\n", led_id); | ||
124 | return iwl3945_led_on(priv, led_id); | ||
125 | } | ||
126 | |||
127 | /* Set led off command */ | 131 | /* Set led off command */ |
128 | static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) | 132 | static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) |
129 | { | 133 | { |
@@ -136,27 +140,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) | |||
136 | IWL_DEBUG_LED("led off %d\n", led_id); | 140 | IWL_DEBUG_LED("led off %d\n", led_id); |
137 | return iwl_send_led_cmd(priv, &led_cmd); | 141 | return iwl_send_led_cmd(priv, &led_cmd); |
138 | } | 142 | } |
139 | 143 | #endif | |
140 | /* Set led register off */ | ||
141 | static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id) | ||
142 | { | ||
143 | iwl3945_led_off(priv, led_id); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /* Set led blink command */ | ||
148 | static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id, | ||
149 | u8 brightness) | ||
150 | { | ||
151 | struct iwl3945_led_cmd led_cmd = { | ||
152 | .id = led_id, | ||
153 | .on = brightness, | ||
154 | .off = brightness, | ||
155 | .interval = IWL_DEF_LED_INTRVL | ||
156 | }; | ||
157 | |||
158 | return iwl_send_led_cmd(priv, &led_cmd); | ||
159 | } | ||
160 | 144 | ||
161 | 145 | ||
162 | /* | 146 | /* |
@@ -206,8 +190,10 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, | |||
206 | led->led_off(priv, IWL_LED_LINK); | 190 | led->led_off(priv, IWL_LED_LINK); |
207 | break; | 191 | break; |
208 | default: | 192 | default: |
209 | if (led->led_pattern) | 193 | if (led->led_pattern) { |
210 | led->led_pattern(priv, IWL_LED_LINK, brightness); | 194 | int idx = iwl3945_brightness_to_idx(brightness); |
195 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
196 | } | ||
211 | break; | 197 | break; |
212 | } | 198 | } |
213 | } | 199 | } |
@@ -252,24 +238,20 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, | |||
252 | static inline u8 get_blink_rate(struct iwl3945_priv *priv) | 238 | static inline u8 get_blink_rate(struct iwl3945_priv *priv) |
253 | { | 239 | { |
254 | int index; | 240 | int index; |
255 | u8 blink_rate; | 241 | u64 current_tpt = priv->rxtxpackets; |
256 | 242 | s64 tpt = current_tpt - priv->led_tpt; | |
257 | if (priv->rxtxpackets < IWL_LED_THRESHOLD) | ||
258 | index = 10; | ||
259 | else { | ||
260 | for (index = 0; index < IWL_MAX_BLINK_TBL; index++) { | ||
261 | if (priv->rxtxpackets > (blink_tbl[index].brightness * | ||
262 | IWL_1MB_RATE)) | ||
263 | break; | ||
264 | } | ||
265 | } | ||
266 | /* if 0 frame is transfered */ | ||
267 | if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) | ||
268 | blink_rate = IWL_LED_SOLID; | ||
269 | else | ||
270 | blink_rate = blink_tbl[index].on_time; | ||
271 | 243 | ||
272 | return blink_rate; | 244 | if (tpt < 0) |
245 | tpt = -tpt; | ||
246 | priv->led_tpt = current_tpt; | ||
247 | |||
248 | if (!priv->allow_blinking) | ||
249 | index = IWL_MAX_BLINK_TBL; | ||
250 | else | ||
251 | for (index = 0; index < IWL_MAX_BLINK_TBL; index++) | ||
252 | if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) | ||
253 | break; | ||
254 | return index; | ||
273 | } | 255 | } |
274 | 256 | ||
275 | static inline int is_rf_kill(struct iwl3945_priv *priv) | 257 | static inline int is_rf_kill(struct iwl3945_priv *priv) |
@@ -285,7 +267,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv) | |||
285 | */ | 267 | */ |
286 | void iwl3945_led_background(struct iwl3945_priv *priv) | 268 | void iwl3945_led_background(struct iwl3945_priv *priv) |
287 | { | 269 | { |
288 | u8 blink_rate; | 270 | u8 blink_idx; |
289 | 271 | ||
290 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 272 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
291 | priv->last_blink_time = 0; | 273 | priv->last_blink_time = 0; |
@@ -298,9 +280,10 @@ void iwl3945_led_background(struct iwl3945_priv *priv) | |||
298 | 280 | ||
299 | if (!priv->allow_blinking) { | 281 | if (!priv->allow_blinking) { |
300 | priv->last_blink_time = 0; | 282 | priv->last_blink_time = 0; |
301 | if (priv->last_blink_rate != IWL_LED_SOLID) { | 283 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { |
302 | priv->last_blink_rate = IWL_LED_SOLID; | 284 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; |
303 | iwl3945_led_on(priv, IWL_LED_LINK); | 285 | iwl3945_led_pattern(priv, IWL_LED_LINK, |
286 | IWL_SOLID_BLINK_IDX); | ||
304 | } | 287 | } |
305 | return; | 288 | return; |
306 | } | 289 | } |
@@ -309,21 +292,14 @@ void iwl3945_led_background(struct iwl3945_priv *priv) | |||
309 | msecs_to_jiffies(1000))) | 292 | msecs_to_jiffies(1000))) |
310 | return; | 293 | return; |
311 | 294 | ||
312 | blink_rate = get_blink_rate(priv); | 295 | blink_idx = get_blink_rate(priv); |
313 | 296 | ||
314 | /* call only if blink rate change */ | 297 | /* call only if blink rate change */ |
315 | if (blink_rate != priv->last_blink_rate) { | 298 | if (blink_idx != priv->last_blink_rate) |
316 | if (blink_rate != IWL_LED_SOLID) { | 299 | iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); |
317 | priv->last_blink_time = jiffies + | ||
318 | msecs_to_jiffies(1000); | ||
319 | iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate); | ||
320 | } else { | ||
321 | priv->last_blink_time = 0; | ||
322 | iwl3945_led_on(priv, IWL_LED_LINK); | ||
323 | } | ||
324 | } | ||
325 | 300 | ||
326 | priv->last_blink_rate = blink_rate; | 301 | priv->last_blink_time = jiffies; |
302 | priv->last_blink_rate = blink_idx; | ||
327 | priv->rxtxpackets = 0; | 303 | priv->rxtxpackets = 0; |
328 | } | 304 | } |
329 | 305 | ||
@@ -337,6 +313,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) | |||
337 | 313 | ||
338 | priv->last_blink_rate = 0; | 314 | priv->last_blink_rate = 0; |
339 | priv->rxtxpackets = 0; | 315 | priv->rxtxpackets = 0; |
316 | priv->led_tpt = 0; | ||
340 | priv->last_blink_time = 0; | 317 | priv->last_blink_time = 0; |
341 | priv->allow_blinking = 0; | 318 | priv->allow_blinking = 0; |
342 | 319 | ||
@@ -344,8 +321,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) | |||
344 | snprintf(name, sizeof(name), "iwl-%s:radio", | 321 | snprintf(name, sizeof(name), "iwl-%s:radio", |
345 | wiphy_name(priv->hw->wiphy)); | 322 | wiphy_name(priv->hw->wiphy)); |
346 | 323 | ||
347 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg; | 324 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; |
348 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg; | 325 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; |
349 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | 326 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; |
350 | 327 | ||
351 | ret = iwl3945_led_register_led(priv, | 328 | ret = iwl3945_led_register_led(priv, |
@@ -364,8 +341,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) | |||
364 | IWL_LED_TRG_ASSOC, 0, | 341 | IWL_LED_TRG_ASSOC, 0, |
365 | name, trigger); | 342 | name, trigger); |
366 | /* for assoc always turn led on */ | 343 | /* for assoc always turn led on */ |
367 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg; | 344 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; |
368 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg; | 345 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; |
369 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; | 346 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; |
370 | 347 | ||
371 | if (ret) | 348 | if (ret) |
@@ -391,6 +368,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv) | |||
391 | trigger = ieee80211_get_tx_led_name(priv->hw); | 368 | trigger = ieee80211_get_tx_led_name(priv->hw); |
392 | snprintf(name, sizeof(name), "iwl-%s:TX", | 369 | snprintf(name, sizeof(name), "iwl-%s:TX", |
393 | wiphy_name(priv->hw->wiphy)); | 370 | wiphy_name(priv->hw->wiphy)); |
371 | |||
394 | ret = iwl3945_led_register_led(priv, | 372 | ret = iwl3945_led_register_led(priv, |
395 | &priv->led[IWL_LED_TRG_TX], | 373 | &priv->led[IWL_LED_TRG_TX], |
396 | IWL_LED_TRG_TX, 0, | 374 | IWL_LED_TRG_TX, 0, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index b1d2f6b8b259..47b7e0bac802 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h | |||
@@ -54,7 +54,7 @@ struct iwl3945_led { | |||
54 | int (*led_on) (struct iwl3945_priv *priv, int led_id); | 54 | int (*led_on) (struct iwl3945_priv *priv, int led_id); |
55 | int (*led_off) (struct iwl3945_priv *priv, int led_id); | 55 | int (*led_off) (struct iwl3945_priv *priv, int led_id); |
56 | int (*led_pattern) (struct iwl3945_priv *priv, int led_id, | 56 | int (*led_pattern) (struct iwl3945_priv *priv, int led_id, |
57 | enum led_brightness brightness); | 57 | unsigned int idx); |
58 | 58 | ||
59 | enum led_type type; | 59 | enum led_type type; |
60 | unsigned int registered; | 60 | unsigned int registered; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 94e177a9f51c..c2a76785b665 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -514,6 +514,23 @@ static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, | |||
514 | } | 514 | } |
515 | #endif | 515 | #endif |
516 | 516 | ||
517 | /* This is necessary only for a number of statistics, see the caller. */ | ||
518 | static int iwl3945_is_network_packet(struct iwl3945_priv *priv, | ||
519 | struct ieee80211_hdr *header) | ||
520 | { | ||
521 | /* Filter incoming packets to determine if they are targeted toward | ||
522 | * this network, discarding packets coming from ourselves */ | ||
523 | switch (priv->iw_mode) { | ||
524 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | ||
525 | /* packets to our IBSS update information */ | ||
526 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
527 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | ||
528 | /* packets to our IBSS update information */ | ||
529 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
530 | default: | ||
531 | return 1; | ||
532 | } | ||
533 | } | ||
517 | 534 | ||
518 | static void iwl3945_add_radiotap(struct iwl3945_priv *priv, | 535 | static void iwl3945_add_radiotap(struct iwl3945_priv *priv, |
519 | struct sk_buff *skb, | 536 | struct sk_buff *skb, |
@@ -608,12 +625,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, | |||
608 | stats->flag |= RX_FLAG_RADIOTAP; | 625 | stats->flag |= RX_FLAG_RADIOTAP; |
609 | } | 626 | } |
610 | 627 | ||
611 | static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, | 628 | static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv, |
612 | struct iwl3945_rx_mem_buffer *rxb, | 629 | struct iwl3945_rx_mem_buffer *rxb, |
613 | struct ieee80211_rx_status *stats) | 630 | struct ieee80211_rx_status *stats) |
614 | { | 631 | { |
615 | struct ieee80211_hdr *hdr; | ||
616 | struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; | 632 | struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data; |
633 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | ||
617 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 634 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
618 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 635 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
619 | short len = le16_to_cpu(rx_hdr->len); | 636 | short len = le16_to_cpu(rx_hdr->len); |
@@ -635,8 +652,6 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, | |||
635 | /* Set the size of the skb to the size of the frame */ | 652 | /* Set the size of the skb to the size of the frame */ |
636 | skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); | 653 | skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); |
637 | 654 | ||
638 | hdr = (void *)rxb->skb->data; | ||
639 | |||
640 | if (iwl3945_param_hwcrypto) | 655 | if (iwl3945_param_hwcrypto) |
641 | iwl3945_set_decrypted_flag(priv, rxb->skb, | 656 | iwl3945_set_decrypted_flag(priv, rxb->skb, |
642 | le32_to_cpu(rx_end->status), stats); | 657 | le32_to_cpu(rx_end->status), stats); |
@@ -645,7 +660,7 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, | |||
645 | iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); | 660 | iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); |
646 | 661 | ||
647 | #ifdef CONFIG_IWL3945_LEDS | 662 | #ifdef CONFIG_IWL3945_LEDS |
648 | if (is_data) | 663 | if (ieee80211_is_data(hdr->frame_control)) |
649 | priv->rxtxpackets += len; | 664 | priv->rxtxpackets += len; |
650 | #endif | 665 | #endif |
651 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); | 666 | ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); |
@@ -694,7 +709,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
694 | } | 709 | } |
695 | 710 | ||
696 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { | 711 | if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { |
697 | iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); | 712 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); |
698 | return; | 713 | return; |
699 | } | 714 | } |
700 | 715 | ||
@@ -842,27 +857,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, | |||
842 | } | 857 | } |
843 | } | 858 | } |
844 | 859 | ||
845 | iwl3945_handle_data_packet(priv, 0, rxb, &rx_status); | 860 | case IEEE80211_FTYPE_DATA: |
846 | break; | 861 | /* fall through */ |
847 | 862 | default: | |
848 | case IEEE80211_FTYPE_CTL: | 863 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); |
849 | break; | ||
850 | |||
851 | case IEEE80211_FTYPE_DATA: { | ||
852 | DECLARE_MAC_BUF(mac1); | ||
853 | DECLARE_MAC_BUF(mac2); | ||
854 | DECLARE_MAC_BUF(mac3); | ||
855 | |||
856 | if (unlikely(iwl3945_is_duplicate_packet(priv, header))) | ||
857 | IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n", | ||
858 | print_mac(mac1, header->addr1), | ||
859 | print_mac(mac2, header->addr2), | ||
860 | print_mac(mac3, header->addr3)); | ||
861 | else | ||
862 | iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); | ||
863 | break; | 864 | break; |
864 | } | 865 | } |
865 | } | ||
866 | } | 866 | } |
867 | 867 | ||
868 | int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, | 868 | int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 9c0a09eaca6f..fa81ba1af3d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -510,8 +510,6 @@ struct iwl3945_ucode { | |||
510 | u8 data[0]; /* data in same order as "size" elements */ | 510 | u8 data[0]; /* data in same order as "size" elements */ |
511 | }; | 511 | }; |
512 | 512 | ||
513 | #define IWL_IBSS_MAC_HASH_SIZE 32 | ||
514 | |||
515 | struct iwl3945_ibss_seq { | 513 | struct iwl3945_ibss_seq { |
516 | u8 mac[ETH_ALEN]; | 514 | u8 mac[ETH_ALEN]; |
517 | u16 seq_num; | 515 | u16 seq_num; |
@@ -569,17 +567,8 @@ extern int iwl3945_send_add_station(struct iwl3945_priv *priv, | |||
569 | struct iwl3945_addsta_cmd *sta, u8 flags); | 567 | struct iwl3945_addsta_cmd *sta, u8 flags); |
570 | extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid, | 568 | extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid, |
571 | int is_ap, u8 flags); | 569 | int is_ap, u8 flags); |
572 | extern int iwl3945_is_network_packet(struct iwl3945_priv *priv, | ||
573 | struct ieee80211_hdr *header); | ||
574 | extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); | 570 | extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); |
575 | extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); | 571 | extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); |
576 | extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, | ||
577 | struct iwl3945_rx_mem_buffer *rxb, | ||
578 | void *data, short len, | ||
579 | struct ieee80211_rx_status *stats, | ||
580 | u16 phy_flags); | ||
581 | extern int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, | ||
582 | struct ieee80211_hdr *header); | ||
583 | extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); | 572 | extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv); |
584 | extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, | 573 | extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, |
585 | struct iwl3945_rx_queue *rxq); | 574 | struct iwl3945_rx_queue *rxq); |
@@ -805,6 +794,7 @@ struct iwl3945_priv { | |||
805 | u8 last_blink_rate; | 794 | u8 last_blink_rate; |
806 | u8 allow_blinking; | 795 | u8 allow_blinking; |
807 | unsigned int rxtxpackets; | 796 | unsigned int rxtxpackets; |
797 | u64 led_tpt; | ||
808 | #endif | 798 | #endif |
809 | 799 | ||
810 | 800 | ||
@@ -859,14 +849,6 @@ struct iwl3945_priv { | |||
859 | u32 last_beacon_time; | 849 | u32 last_beacon_time; |
860 | u64 last_tsf; | 850 | u64 last_tsf; |
861 | 851 | ||
862 | /* Duplicate packet detection */ | ||
863 | u16 last_seq_num; | ||
864 | u16 last_frag_num; | ||
865 | unsigned long last_packet_time; | ||
866 | |||
867 | /* Hash table for finding stations in IBSS network */ | ||
868 | struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE]; | ||
869 | |||
870 | /* eeprom */ | 852 | /* eeprom */ |
871 | struct iwl3945_eeprom eeprom; | 853 | struct iwl3945_eeprom eeprom; |
872 | 854 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 10f630e1afa6..fce950f4163c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -819,6 +819,7 @@ enum { | |||
819 | #define IWL49_NUM_FIFOS 7 | 819 | #define IWL49_NUM_FIFOS 7 |
820 | #define IWL49_CMD_FIFO_NUM 4 | 820 | #define IWL49_CMD_FIFO_NUM 4 |
821 | #define IWL49_NUM_QUEUES 16 | 821 | #define IWL49_NUM_QUEUES 16 |
822 | #define IWL49_NUM_AMPDU_QUEUES 8 | ||
822 | 823 | ||
823 | /** | 824 | /** |
824 | * struct iwl_tfd_frame_data | 825 | * struct iwl_tfd_frame_data |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index c7ebb3bf06f5..3ccb84aa5dbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c | |||
@@ -2265,9 +2265,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2265 | 2265 | ||
2266 | /* as default allow aggregation for all tids */ | 2266 | /* as default allow aggregation for all tids */ |
2267 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2267 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
2268 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
2269 | lq_sta->drv = priv; | 2268 | lq_sta->drv = priv; |
2270 | #endif | ||
2271 | 2269 | ||
2272 | rs_initialize_lq(priv, conf, sta); | 2270 | rs_initialize_lq(priv, conf, sta); |
2273 | } | 2271 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04365b39279c..9afecb813716 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -49,9 +49,17 @@ | |||
49 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 49 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
50 | static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); | 50 | static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); |
51 | 51 | ||
52 | /* Change firmware file name, using "-" and incrementing number, | ||
53 | * *only* when uCode interface or architecture changes so that it | ||
54 | * is not compatible with earlier drivers. | ||
55 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
56 | #define IWL4965_UCODE_API "-2" | ||
57 | |||
58 | |||
52 | /* module parameters */ | 59 | /* module parameters */ |
53 | static struct iwl_mod_params iwl4965_mod_params = { | 60 | static struct iwl_mod_params iwl4965_mod_params = { |
54 | .num_of_queues = IWL49_NUM_QUEUES, | 61 | .num_of_queues = IWL49_NUM_QUEUES, |
62 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
55 | .enable_qos = 1, | 63 | .enable_qos = 1, |
56 | .amsdu_size_8K = 1, | 64 | .amsdu_size_8K = 1, |
57 | .restart_fw = 1, | 65 | .restart_fw = 1, |
@@ -642,6 +650,18 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
642 | data->beacon_count = 0; | 650 | data->beacon_count = 0; |
643 | } | 651 | } |
644 | 652 | ||
653 | static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
654 | __le32 *tx_flags) | ||
655 | { | ||
656 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { | ||
657 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
658 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
659 | } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { | ||
660 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
661 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
662 | } | ||
663 | } | ||
664 | |||
645 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 665 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
646 | { | 666 | { |
647 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 667 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
@@ -1931,9 +1951,11 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1931 | { | 1951 | { |
1932 | int ret = 0; | 1952 | int ret = 0; |
1933 | 1953 | ||
1934 | if (IWL49_FIRST_AMPDU_QUEUE > txq_id) { | 1954 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1935 | IWL_WARNING("queue number too small: %d, must be > %d\n", | 1955 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { |
1936 | txq_id, IWL49_FIRST_AMPDU_QUEUE); | 1956 | IWL_WARNING("queue number out of range: %d, must be %d to %d\n", |
1957 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | ||
1958 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | ||
1937 | return -EINVAL; | 1959 | return -EINVAL; |
1938 | } | 1960 | } |
1939 | 1961 | ||
@@ -2000,9 +2022,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
2000 | int ret; | 2022 | int ret; |
2001 | u16 ra_tid; | 2023 | u16 ra_tid; |
2002 | 2024 | ||
2003 | if (IWL49_FIRST_AMPDU_QUEUE > txq_id) | 2025 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
2004 | IWL_WARNING("queue number too small: %d, must be > %d\n", | 2026 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { |
2005 | txq_id, IWL49_FIRST_AMPDU_QUEUE); | 2027 | IWL_WARNING("queue number out of range: %d, must be %d to %d\n", |
2028 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | ||
2029 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | ||
2030 | return -EINVAL; | ||
2031 | } | ||
2006 | 2032 | ||
2007 | ra_tid = BUILD_RAxTID(sta_id, tid); | 2033 | ra_tid = BUILD_RAxTID(sta_id, tid); |
2008 | 2034 | ||
@@ -2372,6 +2398,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2372 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2398 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
2373 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2399 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2374 | .gain_computation = iwl4965_gain_computation, | 2400 | .gain_computation = iwl4965_gain_computation, |
2401 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, | ||
2375 | }; | 2402 | }; |
2376 | 2403 | ||
2377 | static struct iwl_lib_ops iwl4965_lib = { | 2404 | static struct iwl_lib_ops iwl4965_lib = { |
@@ -2434,6 +2461,9 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2434 | .mod_params = &iwl4965_mod_params, | 2461 | .mod_params = &iwl4965_mod_params, |
2435 | }; | 2462 | }; |
2436 | 2463 | ||
2464 | /* Module firmware */ | ||
2465 | MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode"); | ||
2466 | |||
2437 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2467 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); |
2438 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2468 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
2439 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); | 2469 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 4efe0c06b5b2..17d4f31c5934 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define IWL50_QUEUE_SIZE 256 | 81 | #define IWL50_QUEUE_SIZE 256 |
82 | #define IWL50_CMD_FIFO_NUM 7 | 82 | #define IWL50_CMD_FIFO_NUM 7 |
83 | #define IWL50_NUM_QUEUES 20 | 83 | #define IWL50_NUM_QUEUES 20 |
84 | #define IWL50_NUM_AMPDU_QUEUES 10 | ||
84 | #define IWL50_FIRST_AMPDU_QUEUE 10 | 85 | #define IWL50_FIRST_AMPDU_QUEUE 10 |
85 | 86 | ||
86 | #define IWL_sta_id_POS 12 | 87 | #define IWL_sta_id_POS 12 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 717db0d5ffb3..878d6193b232 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -370,6 +370,16 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) | |||
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
373 | static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
374 | __le32 *tx_flags) | ||
375 | { | ||
376 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | ||
377 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) | ||
378 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
379 | else | ||
380 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
381 | } | ||
382 | |||
373 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | 383 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
374 | .min_nrg_cck = 95, | 384 | .min_nrg_cck = 95, |
375 | .max_nrg_cck = 0, | 385 | .max_nrg_cck = 0, |
@@ -1006,9 +1016,13 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1006 | int ret; | 1016 | int ret; |
1007 | u16 ra_tid; | 1017 | u16 ra_tid; |
1008 | 1018 | ||
1009 | if (IWL50_FIRST_AMPDU_QUEUE > txq_id) | 1019 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
1010 | IWL_WARNING("queue number too small: %d, must be > %d\n", | 1020 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { |
1011 | txq_id, IWL50_FIRST_AMPDU_QUEUE); | 1021 | IWL_WARNING("queue number out of range: %d, must be %d to %d\n", |
1022 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
1023 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1012 | 1026 | ||
1013 | ra_tid = BUILD_RAxTID(sta_id, tid); | 1027 | ra_tid = BUILD_RAxTID(sta_id, tid); |
1014 | 1028 | ||
@@ -1067,9 +1081,11 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1067 | { | 1081 | { |
1068 | int ret; | 1082 | int ret; |
1069 | 1083 | ||
1070 | if (IWL50_FIRST_AMPDU_QUEUE > txq_id) { | 1084 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
1071 | IWL_WARNING("queue number too small: %d, must be > %d\n", | 1085 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { |
1072 | txq_id, IWL50_FIRST_AMPDU_QUEUE); | 1086 | IWL_WARNING("queue number out of range: %d, must be %d to %d\n", |
1087 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
1088 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | ||
1073 | return -EINVAL; | 1089 | return -EINVAL; |
1074 | } | 1090 | } |
1075 | 1091 | ||
@@ -1437,6 +1453,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | |||
1437 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | 1453 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, |
1438 | .gain_computation = iwl5000_gain_computation, | 1454 | .gain_computation = iwl5000_gain_computation, |
1439 | .chain_noise_reset = iwl5000_chain_noise_reset, | 1455 | .chain_noise_reset = iwl5000_chain_noise_reset, |
1456 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
1440 | }; | 1457 | }; |
1441 | 1458 | ||
1442 | static struct iwl_lib_ops iwl5000_lib = { | 1459 | static struct iwl_lib_ops iwl5000_lib = { |
@@ -1490,6 +1507,7 @@ static struct iwl_ops iwl5000_ops = { | |||
1490 | 1507 | ||
1491 | static struct iwl_mod_params iwl50_mod_params = { | 1508 | static struct iwl_mod_params iwl50_mod_params = { |
1492 | .num_of_queues = IWL50_NUM_QUEUES, | 1509 | .num_of_queues = IWL50_NUM_QUEUES, |
1510 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1493 | .enable_qos = 1, | 1511 | .enable_qos = 1, |
1494 | .amsdu_size_8K = 1, | 1512 | .amsdu_size_8K = 1, |
1495 | .restart_fw = 1, | 1513 | .restart_fw = 1, |
@@ -1506,6 +1524,24 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1506 | .mod_params = &iwl50_mod_params, | 1524 | .mod_params = &iwl50_mod_params, |
1507 | }; | 1525 | }; |
1508 | 1526 | ||
1527 | struct iwl_cfg iwl5100_bg_cfg = { | ||
1528 | .name = "5100BG", | ||
1529 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | ||
1530 | .sku = IWL_SKU_G, | ||
1531 | .ops = &iwl5000_ops, | ||
1532 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | ||
1533 | .mod_params = &iwl50_mod_params, | ||
1534 | }; | ||
1535 | |||
1536 | struct iwl_cfg iwl5100_abg_cfg = { | ||
1537 | .name = "5100ABG", | ||
1538 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | ||
1539 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
1540 | .ops = &iwl5000_ops, | ||
1541 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | ||
1542 | .mod_params = &iwl50_mod_params, | ||
1543 | }; | ||
1544 | |||
1509 | struct iwl_cfg iwl5100_agn_cfg = { | 1545 | struct iwl_cfg iwl5100_agn_cfg = { |
1510 | .name = "5100AGN", | 1546 | .name = "5100AGN", |
1511 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | 1547 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index fe05d60ebe63..e9bb1de0ce3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -556,6 +556,8 @@ enum { | |||
556 | #define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25) | 556 | #define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25) |
557 | #define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25) | 557 | #define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25) |
558 | #define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25) | 558 | #define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25) |
559 | /* CTS to self (if spec allows) flag */ | ||
560 | #define RXON_FLG_SELF_CTS_EN __constant_cpu_to_le32(0x1<<30) | ||
559 | 561 | ||
560 | /* rx_config filter flags */ | 562 | /* rx_config filter flags */ |
561 | /* accept all data frames */ | 563 | /* accept all data frames */ |
@@ -723,7 +725,7 @@ struct iwl4965_csa_notification { | |||
723 | * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW | 725 | * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW |
724 | * value, to cap the CW value. | 726 | * value, to cap the CW value. |
725 | */ | 727 | */ |
726 | struct iwl4965_ac_qos { | 728 | struct iwl_ac_qos { |
727 | __le16 cw_min; | 729 | __le16 cw_min; |
728 | __le16 cw_max; | 730 | __le16 cw_max; |
729 | u8 aifsn; | 731 | u8 aifsn; |
@@ -745,9 +747,9 @@ struct iwl4965_ac_qos { | |||
745 | * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs | 747 | * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs |
746 | * 0: Background, 1: Best Effort, 2: Video, 3: Voice. | 748 | * 0: Background, 1: Best Effort, 2: Video, 3: Voice. |
747 | */ | 749 | */ |
748 | struct iwl4965_qosparam_cmd { | 750 | struct iwl_qosparam_cmd { |
749 | __le32 qos_flags; | 751 | __le32 qos_flags; |
750 | struct iwl4965_ac_qos ac[AC_NUM]; | 752 | struct iwl_ac_qos ac[AC_NUM]; |
751 | } __attribute__ ((packed)); | 753 | } __attribute__ ((packed)); |
752 | 754 | ||
753 | /****************************************************************************** | 755 | /****************************************************************************** |
@@ -1139,6 +1141,11 @@ struct iwl4965_rx_mpdu_res_start { | |||
1139 | 1141 | ||
1140 | /* REPLY_TX Tx flags field */ | 1142 | /* REPLY_TX Tx flags field */ |
1141 | 1143 | ||
1144 | /* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it | ||
1145 | * before this frame. if CTS-to-self required check | ||
1146 | * RXON_FLG_SELF_CTS_EN status. */ | ||
1147 | #define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0) | ||
1148 | |||
1142 | /* 1: Use Request-To-Send protocol before this frame. | 1149 | /* 1: Use Request-To-Send protocol before this frame. |
1143 | * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ | 1150 | * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ |
1144 | #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) | 1151 | #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1) |
@@ -2092,6 +2099,9 @@ struct iwl_ct_kill_config { | |||
2092 | * | 2099 | * |
2093 | *****************************************************************************/ | 2100 | *****************************************************************************/ |
2094 | 2101 | ||
2102 | #define SCAN_CHANNEL_TYPE_PASSIVE __constant_cpu_to_le32(0) | ||
2103 | #define SCAN_CHANNEL_TYPE_ACTIVE __constant_cpu_to_le32(1) | ||
2104 | |||
2095 | /** | 2105 | /** |
2096 | * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table | 2106 | * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table |
2097 | * | 2107 | * |
@@ -2115,12 +2125,12 @@ struct iwl_scan_channel { | |||
2115 | /* | 2125 | /* |
2116 | * type is defined as: | 2126 | * type is defined as: |
2117 | * 0:0 1 = active, 0 = passive | 2127 | * 0:0 1 = active, 0 = passive |
2118 | * 1:4 SSID direct bit map; if a bit is set, then corresponding | 2128 | * 1:20 SSID direct bit map; if a bit is set, then corresponding |
2119 | * SSID IE is transmitted in probe request. | 2129 | * SSID IE is transmitted in probe request. |
2120 | * 5:7 reserved | 2130 | * 21:31 reserved |
2121 | */ | 2131 | */ |
2122 | u8 type; | 2132 | __le32 type; |
2123 | u8 channel; /* band is selected by iwl4965_scan_cmd "flags" field */ | 2133 | __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */ |
2124 | u8 tx_gain; /* gain for analog radio */ | 2134 | u8 tx_gain; /* gain for analog radio */ |
2125 | u8 dsp_atten; /* gain for DSP */ | 2135 | u8 dsp_atten; /* gain for DSP */ |
2126 | __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ | 2136 | __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ |
@@ -2140,9 +2150,9 @@ struct iwl_ssid_ie { | |||
2140 | u8 ssid[32]; | 2150 | u8 ssid[32]; |
2141 | } __attribute__ ((packed)); | 2151 | } __attribute__ ((packed)); |
2142 | 2152 | ||
2143 | #define PROBE_OPTION_MAX 0x4 | 2153 | #define PROBE_OPTION_MAX 0x14 |
2144 | #define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF) | 2154 | #define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF) |
2145 | #define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) | 2155 | #define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1) |
2146 | #define IWL_MAX_SCAN_SIZE 1024 | 2156 | #define IWL_MAX_SCAN_SIZE 1024 |
2147 | 2157 | ||
2148 | /* | 2158 | /* |
@@ -2919,7 +2929,7 @@ struct iwl5000_calibration_chain_noise_gain_cmd { | |||
2919 | * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), | 2929 | * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), |
2920 | * this command turns it on or off, or sets up a periodic blinking cycle. | 2930 | * this command turns it on or off, or sets up a periodic blinking cycle. |
2921 | */ | 2931 | */ |
2922 | struct iwl4965_led_cmd { | 2932 | struct iwl_led_cmd { |
2923 | __le32 interval; /* "interval" in uSec */ | 2933 | __le32 interval; /* "interval" in uSec */ |
2924 | u8 id; /* 1: Activity, 2: Link, 3: Tech */ | 2934 | u8 id; /* 1: Activity, 2: Link, 3: Tech */ |
2925 | u8 off; /* # intervals off while blinking; | 2935 | u8 off; /* # intervals off while blinking; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eee220cf52a2..a44188bf4459 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -825,7 +825,7 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
825 | hw->queues = 4; | 825 | hw->queues = 4; |
826 | /* queues to support 11n aggregation */ | 826 | /* queues to support 11n aggregation */ |
827 | if (priv->cfg->sku & IWL_SKU_N) | 827 | if (priv->cfg->sku & IWL_SKU_N) |
828 | hw->ampdu_queues = 12; | 828 | hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; |
829 | 829 | ||
830 | hw->conf.beacon_int = 100; | 830 | hw->conf.beacon_int = 100; |
831 | 831 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index dafd62c7dfd6..db66114f1e56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -70,7 +70,7 @@ struct iwl_host_cmd; | |||
70 | struct iwl_cmd; | 70 | struct iwl_cmd; |
71 | 71 | ||
72 | 72 | ||
73 | #define IWLWIFI_VERSION "1.2.26k" | 73 | #define IWLWIFI_VERSION "1.3.27k" |
74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" | 74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" |
75 | 75 | ||
76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | 76 | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ |
@@ -93,6 +93,8 @@ struct iwl_hcmd_utils_ops { | |||
93 | u16 min_average_noise_antennat_i, | 93 | u16 min_average_noise_antennat_i, |
94 | u32 min_average_noise); | 94 | u32 min_average_noise); |
95 | void (*chain_noise_reset)(struct iwl_priv *priv); | 95 | void (*chain_noise_reset)(struct iwl_priv *priv); |
96 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, | ||
97 | __le32 *tx_flags); | ||
96 | }; | 98 | }; |
97 | 99 | ||
98 | struct iwl_lib_ops { | 100 | struct iwl_lib_ops { |
@@ -157,6 +159,7 @@ struct iwl_mod_params { | |||
157 | int debug; /* def: 0 = minimal debug log messages */ | 159 | int debug; /* def: 0 = minimal debug log messages */ |
158 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 160 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
159 | int num_of_queues; /* def: HW dependent */ | 161 | int num_of_queues; /* def: HW dependent */ |
162 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
160 | int enable_qos; /* def: 1 = use quality of service */ | 163 | int enable_qos; /* def: 1 = use quality of service */ |
161 | int disable_11n; /* def: 0 = disable 11n capabilities */ | 164 | int disable_11n; /* def: 0 = disable 11n capabilities */ |
162 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ | 165 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c8d3d97cf48d..4d789e353e3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -51,12 +51,8 @@ extern struct iwl_cfg iwl4965_agn_cfg; | |||
51 | extern struct iwl_cfg iwl5300_agn_cfg; | 51 | extern struct iwl_cfg iwl5300_agn_cfg; |
52 | extern struct iwl_cfg iwl5100_agn_cfg; | 52 | extern struct iwl_cfg iwl5100_agn_cfg; |
53 | extern struct iwl_cfg iwl5350_agn_cfg; | 53 | extern struct iwl_cfg iwl5350_agn_cfg; |
54 | 54 | extern struct iwl_cfg iwl5100_bg_cfg; | |
55 | /* Change firmware file name, using "-" and incrementing number, | 55 | extern struct iwl_cfg iwl5100_abg_cfg; |
56 | * *only* when uCode interface or architecture changes so that it | ||
57 | * is not compatible with earlier drivers. | ||
58 | * This number will also appear in << 8 position of 1st dword of uCode file */ | ||
59 | #define IWL4965_UCODE_API "-1" | ||
60 | 56 | ||
61 | /* CT-KILL constants */ | 57 | /* CT-KILL constants */ |
62 | #define CT_KILL_THRESHOLD 110 /* in Celsius */ | 58 | #define CT_KILL_THRESHOLD 110 /* in Celsius */ |
@@ -280,7 +276,7 @@ struct iwl_cmd { | |||
280 | struct iwl_cmd_header hdr; /* uCode API */ | 276 | struct iwl_cmd_header hdr; /* uCode API */ |
281 | union { | 277 | union { |
282 | struct iwl_addsta_cmd addsta; | 278 | struct iwl_addsta_cmd addsta; |
283 | struct iwl4965_led_cmd led; | 279 | struct iwl_led_cmd led; |
284 | u32 flags; | 280 | u32 flags; |
285 | u8 val8; | 281 | u8 val8; |
286 | u16 val16; | 282 | u16 val16; |
@@ -288,7 +284,7 @@ struct iwl_cmd { | |||
288 | struct iwl4965_bt_cmd bt; | 284 | struct iwl4965_bt_cmd bt; |
289 | struct iwl4965_rxon_time_cmd rxon_time; | 285 | struct iwl4965_rxon_time_cmd rxon_time; |
290 | struct iwl4965_powertable_cmd powertable; | 286 | struct iwl4965_powertable_cmd powertable; |
291 | struct iwl4965_qosparam_cmd qosparam; | 287 | struct iwl_qosparam_cmd qosparam; |
292 | struct iwl_tx_cmd tx; | 288 | struct iwl_tx_cmd tx; |
293 | struct iwl4965_tx_beacon_cmd tx_beacon; | 289 | struct iwl4965_tx_beacon_cmd tx_beacon; |
294 | struct iwl4965_rxon_assoc_cmd rxon_assoc; | 290 | struct iwl4965_rxon_assoc_cmd rxon_assoc; |
@@ -433,7 +429,7 @@ struct iwl_ht_info { | |||
433 | u8 non_GF_STA_present; | 429 | u8 non_GF_STA_present; |
434 | }; | 430 | }; |
435 | 431 | ||
436 | union iwl4965_qos_capabity { | 432 | union iwl_qos_capabity { |
437 | struct { | 433 | struct { |
438 | u8 edca_count:4; /* bit 0-3 */ | 434 | u8 edca_count:4; /* bit 0-3 */ |
439 | u8 q_ack:1; /* bit 4 */ | 435 | u8 q_ack:1; /* bit 4 */ |
@@ -454,11 +450,11 @@ union iwl4965_qos_capabity { | |||
454 | }; | 450 | }; |
455 | 451 | ||
456 | /* QoS structures */ | 452 | /* QoS structures */ |
457 | struct iwl4965_qos_info { | 453 | struct iwl_qos_info { |
458 | int qos_enable; | 454 | int qos_enable; |
459 | int qos_active; | 455 | int qos_active; |
460 | union iwl4965_qos_capabity qos_cap; | 456 | union iwl_qos_capabity qos_cap; |
461 | struct iwl4965_qosparam_cmd def_qos_parm; | 457 | struct iwl_qosparam_cmd def_qos_parm; |
462 | }; | 458 | }; |
463 | 459 | ||
464 | #define STA_PS_STATUS_WAKE 0 | 460 | #define STA_PS_STATUS_WAKE 0 |
@@ -490,8 +486,6 @@ struct iwl_ucode { | |||
490 | u8 data[0]; /* data in same order as "size" elements */ | 486 | u8 data[0]; /* data in same order as "size" elements */ |
491 | }; | 487 | }; |
492 | 488 | ||
493 | #define IWL_IBSS_MAC_HASH_SIZE 32 | ||
494 | |||
495 | struct iwl4965_ibss_seq { | 489 | struct iwl4965_ibss_seq { |
496 | u8 mac[ETH_ALEN]; | 490 | u8 mac[ETH_ALEN]; |
497 | u16 seq_num; | 491 | u16 seq_num; |
@@ -933,7 +927,7 @@ struct iwl_priv { | |||
933 | #endif | 927 | #endif |
934 | 928 | ||
935 | #ifdef CONFIG_IWLWIFI_LEDS | 929 | #ifdef CONFIG_IWLWIFI_LEDS |
936 | struct iwl4965_led led[IWL_LED_TRG_MAX]; | 930 | struct iwl_led led[IWL_LED_TRG_MAX]; |
937 | unsigned long last_blink_time; | 931 | unsigned long last_blink_time; |
938 | u8 last_blink_rate; | 932 | u8 last_blink_rate; |
939 | u8 allow_blinking; | 933 | u8 allow_blinking; |
@@ -1042,7 +1036,7 @@ struct iwl_priv { | |||
1042 | u16 assoc_capability; | 1036 | u16 assoc_capability; |
1043 | u8 ps_mode; | 1037 | u8 ps_mode; |
1044 | 1038 | ||
1045 | struct iwl4965_qos_info qos_data; | 1039 | struct iwl_qos_info qos_data; |
1046 | 1040 | ||
1047 | struct workqueue_struct *workqueue; | 1041 | struct workqueue_struct *workqueue; |
1048 | 1042 | ||
@@ -1065,7 +1059,6 @@ struct iwl_priv { | |||
1065 | struct delayed_work init_alive_start; | 1059 | struct delayed_work init_alive_start; |
1066 | struct delayed_work alive_start; | 1060 | struct delayed_work alive_start; |
1067 | struct delayed_work scan_check; | 1061 | struct delayed_work scan_check; |
1068 | struct delayed_work post_associate; | ||
1069 | /* TX Power */ | 1062 | /* TX Power */ |
1070 | s8 tx_power_user_lmt; | 1063 | s8 tx_power_user_lmt; |
1071 | s8 tx_power_channel_lmt; | 1064 | s8 tx_power_channel_lmt; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index aa6ad18494ce..899d7a2567a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -44,14 +44,21 @@ | |||
44 | #include "iwl-io.h" | 44 | #include "iwl-io.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | 46 | ||
47 | #define IWL_1MB_RATE (128 * 1024) | 47 | #ifdef CONFIG_IWLWIFI_DEBUG |
48 | #define IWL_LED_THRESHOLD (16) | 48 | static const char *led_type_str[] = { |
49 | #define IWL_MAX_BLINK_TBL (10) | 49 | __stringify(IWL_LED_TRG_TX), |
50 | __stringify(IWL_LED_TRG_RX), | ||
51 | __stringify(IWL_LED_TRG_ASSOC), | ||
52 | __stringify(IWL_LED_TRG_RADIO), | ||
53 | NULL | ||
54 | }; | ||
55 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
56 | |||
50 | 57 | ||
51 | static const struct { | 58 | static const struct { |
52 | u16 tpt; | 59 | u16 tpt; |
53 | u8 on_time; | 60 | u8 on_time; |
54 | u8 of_time; | 61 | u8 off_time; |
55 | } blink_tbl[] = | 62 | } blink_tbl[] = |
56 | { | 63 | { |
57 | {300, 25, 25}, | 64 | {300, 25, 25}, |
@@ -63,26 +70,31 @@ static const struct { | |||
63 | {15, 95, 95 }, | 70 | {15, 95, 95 }, |
64 | {10, 110, 110}, | 71 | {10, 110, 110}, |
65 | {5, 130, 130}, | 72 | {5, 130, 130}, |
66 | {0, 167, 167} | 73 | {0, 167, 167}, |
74 | /* SOLID_ON */ | ||
75 | {-1, IWL_LED_SOLID, 0} | ||
67 | }; | 76 | }; |
68 | 77 | ||
69 | static int iwl_led_cmd_callback(struct iwl_priv *priv, | 78 | #define IWL_1MB_RATE (128 * 1024) |
70 | struct iwl_cmd *cmd, struct sk_buff *skb) | 79 | #define IWL_LED_THRESHOLD (16) |
80 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ | ||
81 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | ||
82 | |||
83 | /* [0-256] -> [0..8] FIXME: we need [0..10] */ | ||
84 | static inline int iwl_brightness_to_idx(enum led_brightness brightness) | ||
71 | { | 85 | { |
72 | return 1; | 86 | return fls(0x000000FF & (u32)brightness); |
73 | } | 87 | } |
74 | 88 | ||
75 | |||
76 | /* Send led command */ | 89 | /* Send led command */ |
77 | static int iwl_send_led_cmd(struct iwl_priv *priv, | 90 | static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) |
78 | struct iwl4965_led_cmd *led_cmd) | ||
79 | { | 91 | { |
80 | struct iwl_host_cmd cmd = { | 92 | struct iwl_host_cmd cmd = { |
81 | .id = REPLY_LEDS_CMD, | 93 | .id = REPLY_LEDS_CMD, |
82 | .len = sizeof(struct iwl4965_led_cmd), | 94 | .len = sizeof(struct iwl_led_cmd), |
83 | .data = led_cmd, | 95 | .data = led_cmd, |
84 | .meta.flags = CMD_ASYNC, | 96 | .meta.flags = CMD_ASYNC, |
85 | .meta.u.callback = iwl_led_cmd_callback | 97 | .meta.u.callback = NULL, |
86 | }; | 98 | }; |
87 | u32 reg; | 99 | u32 reg; |
88 | 100 | ||
@@ -93,33 +105,20 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, | |||
93 | return iwl_send_cmd(priv, &cmd); | 105 | return iwl_send_cmd(priv, &cmd); |
94 | } | 106 | } |
95 | 107 | ||
96 | 108 | /* Set led pattern command */ | |
97 | /* Set led on command */ | ||
98 | static int iwl4965_led_on(struct iwl_priv *priv, int led_id) | ||
99 | { | ||
100 | struct iwl4965_led_cmd led_cmd = { | ||
101 | .id = led_id, | ||
102 | .on = IWL_LED_SOLID, | ||
103 | .off = 0, | ||
104 | .interval = IWL_DEF_LED_INTRVL | ||
105 | }; | ||
106 | return iwl_send_led_cmd(priv, &led_cmd); | ||
107 | } | ||
108 | |||
109 | /* Set led on command */ | ||
110 | static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, | 109 | static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, |
111 | enum led_brightness brightness) | 110 | unsigned int idx) |
112 | { | 111 | { |
113 | struct iwl4965_led_cmd led_cmd = { | 112 | struct iwl_led_cmd led_cmd = { |
114 | .id = led_id, | 113 | .id = led_id, |
115 | .on = brightness, | ||
116 | .off = brightness, | ||
117 | .interval = IWL_DEF_LED_INTRVL | 114 | .interval = IWL_DEF_LED_INTRVL |
118 | }; | 115 | }; |
119 | if (brightness == LED_FULL) { | 116 | |
120 | led_cmd.on = IWL_LED_SOLID; | 117 | BUG_ON(idx > IWL_MAX_BLINK_TBL); |
121 | led_cmd.off = 0; | 118 | |
122 | } | 119 | led_cmd.on = blink_tbl[idx].on_time; |
120 | led_cmd.off = blink_tbl[idx].off_time; | ||
121 | |||
123 | return iwl_send_led_cmd(priv, &led_cmd); | 122 | return iwl_send_led_cmd(priv, &led_cmd); |
124 | } | 123 | } |
125 | 124 | ||
@@ -132,10 +131,22 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) | |||
132 | } | 131 | } |
133 | 132 | ||
134 | #if 0 | 133 | #if 0 |
134 | /* Set led on command */ | ||
135 | static int iwl4965_led_on(struct iwl_priv *priv, int led_id) | ||
136 | { | ||
137 | struct iwl_led_cmd led_cmd = { | ||
138 | .id = led_id, | ||
139 | .on = IWL_LED_SOLID, | ||
140 | .off = 0, | ||
141 | .interval = IWL_DEF_LED_INTRVL | ||
142 | }; | ||
143 | return iwl_send_led_cmd(priv, &led_cmd); | ||
144 | } | ||
145 | |||
135 | /* Set led off command */ | 146 | /* Set led off command */ |
136 | int iwl4965_led_off(struct iwl_priv *priv, int led_id) | 147 | int iwl4965_led_off(struct iwl_priv *priv, int led_id) |
137 | { | 148 | { |
138 | struct iwl4965_led_cmd led_cmd = { | 149 | struct iwl_led_cmd led_cmd = { |
139 | .id = led_id, | 150 | .id = led_id, |
140 | .on = 0, | 151 | .on = 0, |
141 | .off = 0, | 152 | .off = 0, |
@@ -155,25 +166,10 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) | |||
155 | return 0; | 166 | return 0; |
156 | } | 167 | } |
157 | 168 | ||
158 | /* Set led blink command */ | ||
159 | static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id, | ||
160 | u8 brightness) | ||
161 | { | ||
162 | struct iwl4965_led_cmd led_cmd = { | ||
163 | .id = led_id, | ||
164 | .on = brightness, | ||
165 | .off = brightness, | ||
166 | .interval = IWL_DEF_LED_INTRVL | ||
167 | }; | ||
168 | |||
169 | return iwl_send_led_cmd(priv, &led_cmd); | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | 169 | /* |
174 | * brightness call back function for Tx/Rx LED | 170 | * brightness call back function for Tx/Rx LED |
175 | */ | 171 | */ |
176 | static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) | 172 | static int iwl_led_associated(struct iwl_priv *priv, int led_id) |
177 | { | 173 | { |
178 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | 174 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || |
179 | !test_bit(STATUS_READY, &priv->status)) | 175 | !test_bit(STATUS_READY, &priv->status)) |
@@ -189,16 +185,18 @@ static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) | |||
189 | /* | 185 | /* |
190 | * brightness call back for association and radio | 186 | * brightness call back for association and radio |
191 | */ | 187 | */ |
192 | static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, | 188 | static void iwl_led_brightness_set(struct led_classdev *led_cdev, |
193 | enum led_brightness brightness) | 189 | enum led_brightness brightness) |
194 | { | 190 | { |
195 | struct iwl4965_led *led = container_of(led_cdev, | 191 | struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); |
196 | struct iwl4965_led, led_dev); | ||
197 | struct iwl_priv *priv = led->priv; | 192 | struct iwl_priv *priv = led->priv; |
198 | 193 | ||
199 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 194 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
200 | return; | 195 | return; |
201 | 196 | ||
197 | |||
198 | IWL_DEBUG_LED("Led type = %s brightness = %d\n", | ||
199 | led_type_str[led->type], brightness); | ||
202 | switch (brightness) { | 200 | switch (brightness) { |
203 | case LED_FULL: | 201 | case LED_FULL: |
204 | if (led->type == IWL_LED_TRG_ASSOC) | 202 | if (led->type == IWL_LED_TRG_ASSOC) |
@@ -215,8 +213,10 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, | |||
215 | led->led_off(priv, IWL_LED_LINK); | 213 | led->led_off(priv, IWL_LED_LINK); |
216 | break; | 214 | break; |
217 | default: | 215 | default: |
218 | if (led->led_pattern) | 216 | if (led->led_pattern) { |
219 | led->led_pattern(priv, IWL_LED_LINK, brightness); | 217 | int idx = iwl_brightness_to_idx(brightness); |
218 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
219 | } | ||
220 | break; | 220 | break; |
221 | } | 221 | } |
222 | } | 222 | } |
@@ -226,8 +226,7 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, | |||
226 | /* | 226 | /* |
227 | * Register led class with the system | 227 | * Register led class with the system |
228 | */ | 228 | */ |
229 | static int iwl_leds_register_led(struct iwl_priv *priv, | 229 | static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, |
230 | struct iwl4965_led *led, | ||
231 | enum led_type type, u8 set_led, | 230 | enum led_type type, u8 set_led, |
232 | const char *name, char *trigger) | 231 | const char *name, char *trigger) |
233 | { | 232 | { |
@@ -235,7 +234,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv, | |||
235 | int ret; | 234 | int ret; |
236 | 235 | ||
237 | led->led_dev.name = name; | 236 | led->led_dev.name = name; |
238 | led->led_dev.brightness_set = iwl4965_led_brightness_set; | 237 | led->led_dev.brightness_set = iwl_led_brightness_set; |
239 | led->led_dev.default_trigger = trigger; | 238 | led->led_dev.default_trigger = trigger; |
240 | 239 | ||
241 | led->priv = priv; | 240 | led->priv = priv; |
@@ -259,32 +258,28 @@ static int iwl_leds_register_led(struct iwl_priv *priv, | |||
259 | /* | 258 | /* |
260 | * calculate blink rate according to last 2 sec Tx/Rx activities | 259 | * calculate blink rate according to last 2 sec Tx/Rx activities |
261 | */ | 260 | */ |
262 | static inline u8 get_blink_rate(struct iwl_priv *priv) | 261 | static int iwl_get_blink_rate(struct iwl_priv *priv) |
263 | { | 262 | { |
264 | int i; | 263 | int i; |
265 | u8 blink_rate; | 264 | u64 current_tpt = priv->tx_stats[2].bytes; |
266 | u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; | 265 | /* FIXME: + priv->rx_stats[2].bytes; */ |
267 | s64 tpt = current_tpt - priv->led_tpt; | 266 | s64 tpt = current_tpt - priv->led_tpt; |
268 | 267 | ||
269 | if (tpt < 0) /* wrapparound */ | 268 | if (tpt < 0) /* wrapparound */ |
270 | tpt = -tpt; | 269 | tpt = -tpt; |
271 | 270 | ||
271 | IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt); | ||
272 | priv->led_tpt = current_tpt; | 272 | priv->led_tpt = current_tpt; |
273 | 273 | ||
274 | if (tpt < IWL_LED_THRESHOLD) { | 274 | if (!priv->allow_blinking) |
275 | i = IWL_MAX_BLINK_TBL; | 275 | i = IWL_MAX_BLINK_TBL; |
276 | } else { | 276 | else |
277 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) | 277 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) |
278 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) | 278 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) |
279 | break; | 279 | break; |
280 | } | ||
281 | /* if 0 frame is transfered */ | ||
282 | if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) | ||
283 | blink_rate = IWL_LED_SOLID; | ||
284 | else | ||
285 | blink_rate = blink_tbl[i].on_time; | ||
286 | 280 | ||
287 | return blink_rate; | 281 | IWL_DEBUG_LED("LED BLINK IDX=%d", i); |
282 | return i; | ||
288 | } | 283 | } |
289 | 284 | ||
290 | static inline int is_rf_kill(struct iwl_priv *priv) | 285 | static inline int is_rf_kill(struct iwl_priv *priv) |
@@ -300,7 +295,7 @@ static inline int is_rf_kill(struct iwl_priv *priv) | |||
300 | */ | 295 | */ |
301 | void iwl_leds_background(struct iwl_priv *priv) | 296 | void iwl_leds_background(struct iwl_priv *priv) |
302 | { | 297 | { |
303 | u8 blink_rate; | 298 | u8 blink_idx; |
304 | 299 | ||
305 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 300 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
306 | priv->last_blink_time = 0; | 301 | priv->last_blink_time = 0; |
@@ -313,9 +308,10 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
313 | 308 | ||
314 | if (!priv->allow_blinking) { | 309 | if (!priv->allow_blinking) { |
315 | priv->last_blink_time = 0; | 310 | priv->last_blink_time = 0; |
316 | if (priv->last_blink_rate != IWL_LED_SOLID) { | 311 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { |
317 | priv->last_blink_rate = IWL_LED_SOLID; | 312 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; |
318 | iwl4965_led_on(priv, IWL_LED_LINK); | 313 | iwl4965_led_pattern(priv, IWL_LED_LINK, |
314 | IWL_SOLID_BLINK_IDX); | ||
319 | } | 315 | } |
320 | return; | 316 | return; |
321 | } | 317 | } |
@@ -324,21 +320,14 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
324 | msecs_to_jiffies(1000))) | 320 | msecs_to_jiffies(1000))) |
325 | return; | 321 | return; |
326 | 322 | ||
327 | blink_rate = get_blink_rate(priv); | 323 | blink_idx = iwl_get_blink_rate(priv); |
328 | 324 | ||
329 | /* call only if blink rate change */ | 325 | /* call only if blink rate change */ |
330 | if (blink_rate != priv->last_blink_rate) { | 326 | if (blink_idx != priv->last_blink_rate) |
331 | if (blink_rate != IWL_LED_SOLID) { | 327 | iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx); |
332 | priv->last_blink_time = jiffies + | ||
333 | msecs_to_jiffies(1000); | ||
334 | iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate); | ||
335 | } else { | ||
336 | priv->last_blink_time = 0; | ||
337 | iwl4965_led_on(priv, IWL_LED_LINK); | ||
338 | } | ||
339 | } | ||
340 | 328 | ||
341 | priv->last_blink_rate = blink_rate; | 329 | priv->last_blink_time = jiffies; |
330 | priv->last_blink_rate = blink_idx; | ||
342 | } | 331 | } |
343 | EXPORT_SYMBOL(iwl_leds_background); | 332 | EXPORT_SYMBOL(iwl_leds_background); |
344 | 333 | ||
@@ -362,10 +351,8 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
362 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; | 351 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; |
363 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | 352 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; |
364 | 353 | ||
365 | ret = iwl_leds_register_led(priv, | 354 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], |
366 | &priv->led[IWL_LED_TRG_RADIO], | 355 | IWL_LED_TRG_RADIO, 1, name, trigger); |
367 | IWL_LED_TRG_RADIO, 1, | ||
368 | name, trigger); | ||
369 | if (ret) | 356 | if (ret) |
370 | goto exit_fail; | 357 | goto exit_fail; |
371 | 358 | ||
@@ -373,10 +360,9 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
373 | snprintf(name, sizeof(name), "iwl-%s:assoc", | 360 | snprintf(name, sizeof(name), "iwl-%s:assoc", |
374 | wiphy_name(priv->hw->wiphy)); | 361 | wiphy_name(priv->hw->wiphy)); |
375 | 362 | ||
376 | ret = iwl_leds_register_led(priv, | 363 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], |
377 | &priv->led[IWL_LED_TRG_ASSOC], | 364 | IWL_LED_TRG_ASSOC, 0, name, trigger); |
378 | IWL_LED_TRG_ASSOC, 0, | 365 | |
379 | name, trigger); | ||
380 | /* for assoc always turn led on */ | 366 | /* for assoc always turn led on */ |
381 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; | 367 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; |
382 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; | 368 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; |
@@ -386,31 +372,26 @@ int iwl_leds_register(struct iwl_priv *priv) | |||
386 | goto exit_fail; | 372 | goto exit_fail; |
387 | 373 | ||
388 | trigger = ieee80211_get_rx_led_name(priv->hw); | 374 | trigger = ieee80211_get_rx_led_name(priv->hw); |
389 | snprintf(name, sizeof(name), "iwl-%s:RX", | 375 | snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); |
390 | wiphy_name(priv->hw->wiphy)); | ||
391 | 376 | ||
392 | 377 | ||
393 | ret = iwl_leds_register_led(priv, | 378 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], |
394 | &priv->led[IWL_LED_TRG_RX], | 379 | IWL_LED_TRG_RX, 0, name, trigger); |
395 | IWL_LED_TRG_RX, 0, | ||
396 | name, trigger); | ||
397 | 380 | ||
398 | priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated; | 381 | priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; |
399 | priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated; | 382 | priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; |
400 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; | 383 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; |
401 | 384 | ||
402 | if (ret) | 385 | if (ret) |
403 | goto exit_fail; | 386 | goto exit_fail; |
404 | 387 | ||
405 | trigger = ieee80211_get_tx_led_name(priv->hw); | 388 | trigger = ieee80211_get_tx_led_name(priv->hw); |
406 | snprintf(name, sizeof(name), "iwl-%s:TX", | 389 | snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); |
407 | wiphy_name(priv->hw->wiphy)); | 390 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], |
408 | ret = iwl_leds_register_led(priv, | 391 | IWL_LED_TRG_TX, 0, name, trigger); |
409 | &priv->led[IWL_LED_TRG_TX], | 392 | |
410 | IWL_LED_TRG_TX, 0, | 393 | priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; |
411 | name, trigger); | 394 | priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; |
412 | priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated; | ||
413 | priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated; | ||
414 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; | 395 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; |
415 | 396 | ||
416 | if (ret) | 397 | if (ret) |
@@ -425,7 +406,7 @@ exit_fail: | |||
425 | EXPORT_SYMBOL(iwl_leds_register); | 406 | EXPORT_SYMBOL(iwl_leds_register); |
426 | 407 | ||
427 | /* unregister led class */ | 408 | /* unregister led class */ |
428 | static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led) | 409 | static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) |
429 | { | 410 | { |
430 | if (!led->registered) | 411 | if (!led->registered) |
431 | return; | 412 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 5bb04128cd65..1980ae5a7e82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h | |||
@@ -49,14 +49,13 @@ enum led_type { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | 51 | ||
52 | struct iwl4965_led { | 52 | struct iwl_led { |
53 | struct iwl_priv *priv; | 53 | struct iwl_priv *priv; |
54 | struct led_classdev led_dev; | 54 | struct led_classdev led_dev; |
55 | 55 | ||
56 | int (*led_on) (struct iwl_priv *priv, int led_id); | 56 | int (*led_on) (struct iwl_priv *priv, int led_id); |
57 | int (*led_off) (struct iwl_priv *priv, int led_id); | 57 | int (*led_off) (struct iwl_priv *priv, int led_id); |
58 | int (*led_pattern) (struct iwl_priv *priv, int led_id, | 58 | int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); |
59 | enum led_brightness brightness); | ||
60 | 59 | ||
61 | enum led_type type; | 60 | enum led_type type; |
62 | unsigned int registered; | 61 | unsigned int registered; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 3e8500ecf598..e2d9afba38a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <net/mac80211.h> | 31 | #include <net/mac80211.h> |
32 | #include <asm/unaligned.h> | ||
32 | #include "iwl-eeprom.h" | 33 | #include "iwl-eeprom.h" |
33 | #include "iwl-dev.h" | 34 | #include "iwl-dev.h" |
34 | #include "iwl-core.h" | 35 | #include "iwl-core.h" |
@@ -829,23 +830,22 @@ static void iwl_add_radiotap(struct iwl_priv *priv, | |||
829 | iwl4965_rt->rt_hdr.it_pad = 0; | 830 | iwl4965_rt->rt_hdr.it_pad = 0; |
830 | 831 | ||
831 | /* total header + data */ | 832 | /* total header + data */ |
832 | put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)), | 833 | put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len); |
833 | &iwl4965_rt->rt_hdr.it_len); | ||
834 | 834 | ||
835 | /* Indicate all the fields we add to the radiotap header */ | 835 | /* Indicate all the fields we add to the radiotap header */ |
836 | put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | | 836 | put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) | |
837 | (1 << IEEE80211_RADIOTAP_FLAGS) | | 837 | (1 << IEEE80211_RADIOTAP_FLAGS) | |
838 | (1 << IEEE80211_RADIOTAP_RATE) | | 838 | (1 << IEEE80211_RADIOTAP_RATE) | |
839 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 839 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
840 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | 840 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | |
841 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | | 841 | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | |
842 | (1 << IEEE80211_RADIOTAP_ANTENNA)), | 842 | (1 << IEEE80211_RADIOTAP_ANTENNA), |
843 | &iwl4965_rt->rt_hdr.it_present); | 843 | &(iwl4965_rt->rt_hdr.it_present)); |
844 | 844 | ||
845 | /* Zero the flags, we'll add to them as we go */ | 845 | /* Zero the flags, we'll add to them as we go */ |
846 | iwl4965_rt->rt_flags = 0; | 846 | iwl4965_rt->rt_flags = 0; |
847 | 847 | ||
848 | put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf); | 848 | put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf); |
849 | 849 | ||
850 | iwl4965_rt->rt_dbmsignal = signal; | 850 | iwl4965_rt->rt_dbmsignal = signal; |
851 | iwl4965_rt->rt_dbmnoise = noise; | 851 | iwl4965_rt->rt_dbmnoise = noise; |
@@ -853,17 +853,14 @@ static void iwl_add_radiotap(struct iwl_priv *priv, | |||
853 | /* Convert the channel frequency and set the flags */ | 853 | /* Convert the channel frequency and set the flags */ |
854 | put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); | 854 | put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz); |
855 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) | 855 | if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK)) |
856 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | 856 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, |
857 | IEEE80211_CHAN_5GHZ), | 857 | &iwl4965_rt->rt_chbitmask); |
858 | &iwl4965_rt->rt_chbitmask); | ||
859 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) | 858 | else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK) |
860 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK | | 859 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, |
861 | IEEE80211_CHAN_2GHZ), | 860 | &iwl4965_rt->rt_chbitmask); |
862 | &iwl4965_rt->rt_chbitmask); | ||
863 | else /* 802.11g */ | 861 | else /* 802.11g */ |
864 | put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM | | 862 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, |
865 | IEEE80211_CHAN_2GHZ), | 863 | &iwl4965_rt->rt_chbitmask); |
866 | &iwl4965_rt->rt_chbitmask); | ||
867 | 864 | ||
868 | if (rate == -1) | 865 | if (rate == -1) |
869 | iwl4965_rt->rt_rate = 0; | 866 | iwl4965_rt->rt_rate = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5b420b43af5c..efc750d2fc5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -38,8 +38,11 @@ | |||
38 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after | 38 | /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after |
39 | * sending probe req. This should be set long enough to hear probe responses | 39 | * sending probe req. This should be set long enough to hear probe responses |
40 | * from more than one AP. */ | 40 | * from more than one AP. */ |
41 | #define IWL_ACTIVE_DWELL_TIME_24 (20) /* all times in msec */ | 41 | #define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ |
42 | #define IWL_ACTIVE_DWELL_TIME_52 (10) | 42 | #define IWL_ACTIVE_DWELL_TIME_52 (20) |
43 | |||
44 | #define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) | ||
45 | #define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) | ||
43 | 46 | ||
44 | /* For faster active scanning, scan will move to the next channel if fewer than | 47 | /* For faster active scanning, scan will move to the next channel if fewer than |
45 | * PLCP_QUIET_THRESH packets are heard on this channel within | 48 | * PLCP_QUIET_THRESH packets are heard on this channel within |
@@ -48,7 +51,7 @@ | |||
48 | * no other traffic). | 51 | * no other traffic). |
49 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ | 52 | * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ |
50 | #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ | 53 | #define IWL_PLCP_QUIET_THRESH __constant_cpu_to_le16(1) /* packets */ |
51 | #define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(5) /* msec */ | 54 | #define IWL_ACTIVE_QUIET_TIME __constant_cpu_to_le16(10) /* msec */ |
52 | 55 | ||
53 | /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. | 56 | /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. |
54 | * Must be set longer than active dwell time. | 57 | * Must be set longer than active dwell time. |
@@ -58,10 +61,15 @@ | |||
58 | #define IWL_PASSIVE_DWELL_BASE (100) | 61 | #define IWL_PASSIVE_DWELL_BASE (100) |
59 | #define IWL_CHANNEL_TUNE_TIME 5 | 62 | #define IWL_CHANNEL_TUNE_TIME 5 |
60 | 63 | ||
64 | #define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) | ||
65 | |||
66 | |||
61 | static int scan_tx_ant[3] = { | 67 | static int scan_tx_ant[3] = { |
62 | RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK | 68 | RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK |
63 | }; | 69 | }; |
64 | 70 | ||
71 | |||
72 | |||
65 | static int iwl_is_empty_essid(const char *essid, int essid_len) | 73 | static int iwl_is_empty_essid(const char *essid, int essid_len) |
66 | { | 74 | { |
67 | /* Single white space is for Linksys APs */ | 75 | /* Single white space is for Linksys APs */ |
@@ -226,8 +234,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | |||
226 | "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", | 234 | "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", |
227 | notif->channel, | 235 | notif->channel, |
228 | notif->band ? "bg" : "a", | 236 | notif->band ? "bg" : "a", |
229 | notif->tsf_high, | 237 | le32_to_cpu(notif->tsf_high), |
230 | notif->tsf_low, notif->status, notif->beacon_timer); | 238 | le32_to_cpu(notif->tsf_low), |
239 | notif->status, notif->beacon_timer); | ||
231 | } | 240 | } |
232 | 241 | ||
233 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ | 242 | /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ |
@@ -332,19 +341,21 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) | |||
332 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); | 341 | EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); |
333 | 342 | ||
334 | static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | 343 | static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, |
335 | enum ieee80211_band band) | 344 | enum ieee80211_band band, |
345 | u8 n_probes) | ||
336 | { | 346 | { |
337 | if (band == IEEE80211_BAND_5GHZ) | 347 | if (band == IEEE80211_BAND_5GHZ) |
338 | return IWL_ACTIVE_DWELL_TIME_52; | 348 | return IWL_ACTIVE_DWELL_TIME_52 + |
349 | IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); | ||
339 | else | 350 | else |
340 | return IWL_ACTIVE_DWELL_TIME_24; | 351 | return IWL_ACTIVE_DWELL_TIME_24 + |
352 | IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); | ||
341 | } | 353 | } |
342 | 354 | ||
343 | static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 355 | static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
344 | enum ieee80211_band band) | 356 | enum ieee80211_band band) |
345 | { | 357 | { |
346 | u16 active = iwl_get_active_dwell_time(priv, band); | 358 | u16 passive = (band == IEEE80211_BAND_2GHZ) ? |
347 | u16 passive = (band != IEEE80211_BAND_5GHZ) ? | ||
348 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : | 359 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : |
349 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; | 360 | IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; |
350 | 361 | ||
@@ -358,15 +369,12 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
358 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; | 369 | passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; |
359 | } | 370 | } |
360 | 371 | ||
361 | if (passive <= active) | ||
362 | passive = active + 1; | ||
363 | |||
364 | return passive; | 372 | return passive; |
365 | } | 373 | } |
366 | 374 | ||
367 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | 375 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, |
368 | enum ieee80211_band band, | 376 | enum ieee80211_band band, |
369 | u8 is_active, u8 direct_mask, | 377 | u8 is_active, u8 n_probes, |
370 | struct iwl_scan_channel *scan_ch) | 378 | struct iwl_scan_channel *scan_ch) |
371 | { | 379 | { |
372 | const struct ieee80211_channel *channels = NULL; | 380 | const struct ieee80211_channel *channels = NULL; |
@@ -375,6 +383,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
375 | u16 passive_dwell = 0; | 383 | u16 passive_dwell = 0; |
376 | u16 active_dwell = 0; | 384 | u16 active_dwell = 0; |
377 | int added, i; | 385 | int added, i; |
386 | u16 channel; | ||
378 | 387 | ||
379 | sband = iwl_get_hw_mode(priv, band); | 388 | sband = iwl_get_hw_mode(priv, band); |
380 | if (!sband) | 389 | if (!sband) |
@@ -382,31 +391,35 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
382 | 391 | ||
383 | channels = sband->channels; | 392 | channels = sband->channels; |
384 | 393 | ||
385 | active_dwell = iwl_get_active_dwell_time(priv, band); | 394 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); |
386 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | 395 | passive_dwell = iwl_get_passive_dwell_time(priv, band); |
387 | 396 | ||
397 | if (passive_dwell <= active_dwell) | ||
398 | passive_dwell = active_dwell + 1; | ||
399 | |||
388 | for (i = 0, added = 0; i < sband->n_channels; i++) { | 400 | for (i = 0, added = 0; i < sband->n_channels; i++) { |
389 | if (channels[i].flags & IEEE80211_CHAN_DISABLED) | 401 | if (channels[i].flags & IEEE80211_CHAN_DISABLED) |
390 | continue; | 402 | continue; |
391 | 403 | ||
392 | scan_ch->channel = | 404 | channel = |
393 | ieee80211_frequency_to_channel(channels[i].center_freq); | 405 | ieee80211_frequency_to_channel(channels[i].center_freq); |
406 | scan_ch->channel = cpu_to_le16(channel); | ||
394 | 407 | ||
395 | ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); | 408 | ch_info = iwl_get_channel_info(priv, band, channel); |
396 | if (!is_channel_valid(ch_info)) { | 409 | if (!is_channel_valid(ch_info)) { |
397 | IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", | 410 | IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", |
398 | scan_ch->channel); | 411 | channel); |
399 | continue; | 412 | continue; |
400 | } | 413 | } |
401 | 414 | ||
402 | if (!is_active || is_channel_passive(ch_info) || | 415 | if (!is_active || is_channel_passive(ch_info) || |
403 | (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) | 416 | (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) |
404 | scan_ch->type = 0; | 417 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; |
405 | else | 418 | else |
406 | scan_ch->type = 1; | 419 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; |
407 | 420 | ||
408 | if (scan_ch->type & 1) | 421 | if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes) |
409 | scan_ch->type |= (direct_mask << 1); | 422 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); |
410 | 423 | ||
411 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | 424 | scan_ch->active_dwell = cpu_to_le16(active_dwell); |
412 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | 425 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); |
@@ -414,20 +427,20 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
414 | /* Set txpower levels to defaults */ | 427 | /* Set txpower levels to defaults */ |
415 | scan_ch->dsp_atten = 110; | 428 | scan_ch->dsp_atten = 110; |
416 | 429 | ||
430 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
431 | * power level: | ||
432 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
433 | */ | ||
417 | if (band == IEEE80211_BAND_5GHZ) | 434 | if (band == IEEE80211_BAND_5GHZ) |
418 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | 435 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; |
419 | else { | 436 | else |
420 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | 437 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); |
421 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
422 | * power level: | ||
423 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
424 | */ | ||
425 | } | ||
426 | 438 | ||
427 | IWL_DEBUG_SCAN("Scanning %d [%s %d]\n", | 439 | IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n", |
428 | scan_ch->channel, | 440 | channel, le32_to_cpu(scan_ch->type), |
429 | (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", | 441 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? |
430 | (scan_ch->type & 1) ? | 442 | "ACTIVE" : "PASSIVE", |
443 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
431 | active_dwell : passive_dwell); | 444 | active_dwell : passive_dwell); |
432 | 445 | ||
433 | scan_ch++; | 446 | scan_ch++; |
@@ -673,7 +686,7 @@ static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band) | |||
673 | break; | 686 | break; |
674 | } | 687 | } |
675 | } | 688 | } |
676 | 689 | IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind); | |
677 | return scan_tx_ant[ind]; | 690 | return scan_tx_ant[ind]; |
678 | } | 691 | } |
679 | 692 | ||
@@ -693,7 +706,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
693 | u32 tx_ant; | 706 | u32 tx_ant; |
694 | u16 cmd_len; | 707 | u16 cmd_len; |
695 | enum ieee80211_band band; | 708 | enum ieee80211_band band; |
696 | u8 direct_mask; | 709 | u8 n_probes = 2; |
697 | u8 rx_chain = 0x7; /* bitmap: ABC chains */ | 710 | u8 rx_chain = 0x7; /* bitmap: ABC chains */ |
698 | 711 | ||
699 | conf = ieee80211_get_hw_conf(priv->hw); | 712 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -793,17 +806,16 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
793 | scan->direct_scan[0].len = priv->direct_ssid_len; | 806 | scan->direct_scan[0].len = priv->direct_ssid_len; |
794 | memcpy(scan->direct_scan[0].ssid, | 807 | memcpy(scan->direct_scan[0].ssid, |
795 | priv->direct_ssid, priv->direct_ssid_len); | 808 | priv->direct_ssid, priv->direct_ssid_len); |
796 | direct_mask = 1; | 809 | n_probes++; |
797 | } else if (!iwl_is_associated(priv) && priv->essid_len) { | 810 | } else if (!iwl_is_associated(priv) && priv->essid_len) { |
798 | IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", | 811 | IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n", |
799 | iwl_escape_essid(priv->essid, priv->essid_len)); | 812 | iwl_escape_essid(priv->essid, priv->essid_len)); |
800 | scan->direct_scan[0].id = WLAN_EID_SSID; | 813 | scan->direct_scan[0].id = WLAN_EID_SSID; |
801 | scan->direct_scan[0].len = priv->essid_len; | 814 | scan->direct_scan[0].len = priv->essid_len; |
802 | memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); | 815 | memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); |
803 | direct_mask = 1; | 816 | n_probes++; |
804 | } else { | 817 | } else { |
805 | IWL_DEBUG_SCAN("Start indirect scan.\n"); | 818 | IWL_DEBUG_SCAN("Start indirect scan.\n"); |
806 | direct_mask = 0; | ||
807 | } | 819 | } |
808 | 820 | ||
809 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 821 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
@@ -860,16 +872,11 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
860 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | 872 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | |
861 | RXON_FILTER_BCON_AWARE_MSK); | 873 | RXON_FILTER_BCON_AWARE_MSK); |
862 | 874 | ||
863 | if (direct_mask) | 875 | scan->channel_count = |
864 | scan->channel_count = | 876 | iwl_get_channels_for_scan(priv, band, 1, /* active */ |
865 | iwl_get_channels_for_scan(priv, band, 1, /* active */ | 877 | n_probes, |
866 | direct_mask, | 878 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); |
867 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | 879 | |
868 | else | ||
869 | scan->channel_count = | ||
870 | iwl_get_channels_for_scan(priv, band, 0, /* passive */ | ||
871 | direct_mask, | ||
872 | (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); | ||
873 | if (scan->channel_count == 0) { | 880 | if (scan->channel_count == 0) { |
874 | IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); | 881 | IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); |
875 | goto done; | 882 | goto done; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 0be2a71990b0..9b50b1052b09 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -601,13 +601,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, | |||
601 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 601 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
602 | } | 602 | } |
603 | 603 | ||
604 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { | 604 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); |
605 | tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
606 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
607 | } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { | ||
608 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
609 | tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
610 | } | ||
611 | 605 | ||
612 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | 606 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) |
613 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | 607 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 1a7d18fea89d..4a22d3fba75b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2035,36 +2035,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode) | |||
2035 | return rc; | 2035 | return rc; |
2036 | } | 2036 | } |
2037 | 2037 | ||
2038 | int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | ||
2039 | { | ||
2040 | /* Filter incoming packets to determine if they are targeted toward | ||
2041 | * this network, discarding packets coming from ourselves */ | ||
2042 | switch (priv->iw_mode) { | ||
2043 | case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */ | ||
2044 | /* packets from our adapter are dropped (echo) */ | ||
2045 | if (!compare_ether_addr(header->addr2, priv->mac_addr)) | ||
2046 | return 0; | ||
2047 | /* {broad,multi}cast packets to our IBSS go through */ | ||
2048 | if (is_multicast_ether_addr(header->addr1)) | ||
2049 | return !compare_ether_addr(header->addr3, priv->bssid); | ||
2050 | /* packets to our adapter go through */ | ||
2051 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2052 | case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */ | ||
2053 | /* packets from our adapter are dropped (echo) */ | ||
2054 | if (!compare_ether_addr(header->addr3, priv->mac_addr)) | ||
2055 | return 0; | ||
2056 | /* {broad,multi}cast packets to our BSS go through */ | ||
2057 | if (is_multicast_ether_addr(header->addr1)) | ||
2058 | return !compare_ether_addr(header->addr2, priv->bssid); | ||
2059 | /* packets to our adapter go through */ | ||
2060 | return !compare_ether_addr(header->addr1, priv->mac_addr); | ||
2061 | default: | ||
2062 | return 1; | ||
2063 | } | ||
2064 | |||
2065 | return 1; | ||
2066 | } | ||
2067 | |||
2068 | /** | 2038 | /** |
2069 | * iwl3945_scan_cancel - Cancel any currently executing HW scan | 2039 | * iwl3945_scan_cancel - Cancel any currently executing HW scan |
2070 | * | 2040 | * |
@@ -2117,20 +2087,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long | |||
2117 | return ret; | 2087 | return ret; |
2118 | } | 2088 | } |
2119 | 2089 | ||
2120 | static void iwl3945_sequence_reset(struct iwl3945_priv *priv) | ||
2121 | { | ||
2122 | /* Reset ieee stats */ | ||
2123 | |||
2124 | /* We don't reset the net_device_stats (ieee->stats) on | ||
2125 | * re-association */ | ||
2126 | |||
2127 | priv->last_seq_num = -1; | ||
2128 | priv->last_frag_num = -1; | ||
2129 | priv->last_packet_time = 0; | ||
2130 | |||
2131 | iwl3945_scan_cancel(priv); | ||
2132 | } | ||
2133 | |||
2134 | #define MAX_UCODE_BEACON_INTERVAL 1024 | 2090 | #define MAX_UCODE_BEACON_INTERVAL 1024 |
2135 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) | 2091 | #define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) |
2136 | 2092 | ||
@@ -2925,72 +2881,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb, | |||
2925 | } | 2881 | } |
2926 | } | 2882 | } |
2927 | 2883 | ||
2928 | #define IWL_PACKET_RETRY_TIME HZ | ||
2929 | |||
2930 | int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header) | ||
2931 | { | ||
2932 | u16 sc = le16_to_cpu(header->seq_ctrl); | ||
2933 | u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
2934 | u16 frag = sc & IEEE80211_SCTL_FRAG; | ||
2935 | u16 *last_seq, *last_frag; | ||
2936 | unsigned long *last_time; | ||
2937 | |||
2938 | switch (priv->iw_mode) { | ||
2939 | case IEEE80211_IF_TYPE_IBSS:{ | ||
2940 | struct list_head *p; | ||
2941 | struct iwl3945_ibss_seq *entry = NULL; | ||
2942 | u8 *mac = header->addr2; | ||
2943 | int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1); | ||
2944 | |||
2945 | __list_for_each(p, &priv->ibss_mac_hash[index]) { | ||
2946 | entry = list_entry(p, struct iwl3945_ibss_seq, list); | ||
2947 | if (!compare_ether_addr(entry->mac, mac)) | ||
2948 | break; | ||
2949 | } | ||
2950 | if (p == &priv->ibss_mac_hash[index]) { | ||
2951 | entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | ||
2952 | if (!entry) { | ||
2953 | IWL_ERROR("Cannot malloc new mac entry\n"); | ||
2954 | return 0; | ||
2955 | } | ||
2956 | memcpy(entry->mac, mac, ETH_ALEN); | ||
2957 | entry->seq_num = seq; | ||
2958 | entry->frag_num = frag; | ||
2959 | entry->packet_time = jiffies; | ||
2960 | list_add(&entry->list, &priv->ibss_mac_hash[index]); | ||
2961 | return 0; | ||
2962 | } | ||
2963 | last_seq = &entry->seq_num; | ||
2964 | last_frag = &entry->frag_num; | ||
2965 | last_time = &entry->packet_time; | ||
2966 | break; | ||
2967 | } | ||
2968 | case IEEE80211_IF_TYPE_STA: | ||
2969 | last_seq = &priv->last_seq_num; | ||
2970 | last_frag = &priv->last_frag_num; | ||
2971 | last_time = &priv->last_packet_time; | ||
2972 | break; | ||
2973 | default: | ||
2974 | return 0; | ||
2975 | } | ||
2976 | if ((*last_seq == seq) && | ||
2977 | time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) { | ||
2978 | if (*last_frag == frag) | ||
2979 | goto drop; | ||
2980 | if (*last_frag + 1 != frag) | ||
2981 | /* out-of-order fragment */ | ||
2982 | goto drop; | ||
2983 | } else | ||
2984 | *last_seq = seq; | ||
2985 | |||
2986 | *last_frag = frag; | ||
2987 | *last_time = jiffies; | ||
2988 | return 0; | ||
2989 | |||
2990 | drop: | ||
2991 | return 1; | ||
2992 | } | ||
2993 | |||
2994 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT | 2884 | #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT |
2995 | 2885 | ||
2996 | #include "iwl-spectrum.h" | 2886 | #include "iwl-spectrum.h" |
@@ -6531,8 +6421,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data) | |||
6531 | break; | 6421 | break; |
6532 | } | 6422 | } |
6533 | 6423 | ||
6534 | iwl3945_sequence_reset(priv); | ||
6535 | |||
6536 | iwl3945_activate_qos(priv, 0); | 6424 | iwl3945_activate_qos(priv, 0); |
6537 | 6425 | ||
6538 | /* we have just associated, don't start scan too early */ | 6426 | /* we have just associated, don't start scan too early */ |
@@ -6907,6 +6795,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv) | |||
6907 | * clear sta table, add BCAST sta... */ | 6795 | * clear sta table, add BCAST sta... */ |
6908 | } | 6796 | } |
6909 | 6797 | ||
6798 | /* temporary */ | ||
6799 | static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
6800 | |||
6910 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | 6801 | static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, |
6911 | struct ieee80211_vif *vif, | 6802 | struct ieee80211_vif *vif, |
6912 | struct ieee80211_if_conf *conf) | 6803 | struct ieee80211_if_conf *conf) |
@@ -6924,10 +6815,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
6924 | return 0; | 6815 | return 0; |
6925 | } | 6816 | } |
6926 | 6817 | ||
6818 | /* handle this temporarily here */ | ||
6819 | if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && | ||
6820 | conf->changed & IEEE80211_IFCC_BEACON) { | ||
6821 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
6822 | if (!beacon) | ||
6823 | return -ENOMEM; | ||
6824 | rc = iwl3945_mac_beacon_update(hw, beacon); | ||
6825 | if (rc) | ||
6826 | return rc; | ||
6827 | } | ||
6828 | |||
6927 | /* XXX: this MUST use conf->mac_addr */ | 6829 | /* XXX: this MUST use conf->mac_addr */ |
6928 | 6830 | ||
6929 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 6831 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
6930 | (!conf->beacon || !conf->ssid_len)) { | 6832 | (!conf->ssid_len)) { |
6931 | IWL_DEBUG_MAC80211 | 6833 | IWL_DEBUG_MAC80211 |
6932 | ("Leaving in AP mode because HostAPD is not ready.\n"); | 6834 | ("Leaving in AP mode because HostAPD is not ready.\n"); |
6933 | return 0; | 6835 | return 0; |
@@ -6959,7 +6861,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, | |||
6959 | if (priv->ibss_beacon) | 6861 | if (priv->ibss_beacon) |
6960 | dev_kfree_skb(priv->ibss_beacon); | 6862 | dev_kfree_skb(priv->ibss_beacon); |
6961 | 6863 | ||
6962 | priv->ibss_beacon = conf->beacon; | 6864 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
6963 | } | 6865 | } |
6964 | 6866 | ||
6965 | if (iwl3945_is_rfkill(priv)) | 6867 | if (iwl3945_is_rfkill(priv)) |
@@ -7940,7 +7842,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
7940 | .conf_tx = iwl3945_mac_conf_tx, | 7842 | .conf_tx = iwl3945_mac_conf_tx, |
7941 | .get_tsf = iwl3945_mac_get_tsf, | 7843 | .get_tsf = iwl3945_mac_get_tsf, |
7942 | .reset_tsf = iwl3945_mac_reset_tsf, | 7844 | .reset_tsf = iwl3945_mac_reset_tsf, |
7943 | .beacon_update = iwl3945_mac_beacon_update, | ||
7944 | .hw_scan = iwl3945_mac_hw_scan | 7845 | .hw_scan = iwl3945_mac_hw_scan |
7945 | }; | 7846 | }; |
7946 | 7847 | ||
@@ -7950,7 +7851,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7950 | struct iwl3945_priv *priv; | 7851 | struct iwl3945_priv *priv; |
7951 | struct ieee80211_hw *hw; | 7852 | struct ieee80211_hw *hw; |
7952 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); | 7853 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); |
7953 | int i; | ||
7954 | unsigned long flags; | 7854 | unsigned long flags; |
7955 | DECLARE_MAC_BUF(mac); | 7855 | DECLARE_MAC_BUF(mac); |
7956 | 7856 | ||
@@ -8011,9 +7911,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8011 | spin_lock_init(&priv->sta_lock); | 7911 | spin_lock_init(&priv->sta_lock); |
8012 | spin_lock_init(&priv->hcmd_lock); | 7912 | spin_lock_init(&priv->hcmd_lock); |
8013 | 7913 | ||
8014 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) | ||
8015 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | ||
8016 | |||
8017 | INIT_LIST_HEAD(&priv->free_frames); | 7914 | INIT_LIST_HEAD(&priv->free_frames); |
8018 | 7915 | ||
8019 | mutex_init(&priv->mutex); | 7916 | mutex_init(&priv->mutex); |
@@ -8186,8 +8083,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8186 | static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | 8083 | static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) |
8187 | { | 8084 | { |
8188 | struct iwl3945_priv *priv = pci_get_drvdata(pdev); | 8085 | struct iwl3945_priv *priv = pci_get_drvdata(pdev); |
8189 | struct list_head *p, *q; | ||
8190 | int i; | ||
8191 | unsigned long flags; | 8086 | unsigned long flags; |
8192 | 8087 | ||
8193 | if (!priv) | 8088 | if (!priv) |
@@ -8208,14 +8103,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
8208 | 8103 | ||
8209 | iwl_synchronize_irq(priv); | 8104 | iwl_synchronize_irq(priv); |
8210 | 8105 | ||
8211 | /* Free MAC hash list for ADHOC */ | ||
8212 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { | ||
8213 | list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { | ||
8214 | list_del(p); | ||
8215 | kfree(list_entry(p, struct iwl3945_ibss_seq, list)); | ||
8216 | } | ||
8217 | } | ||
8218 | |||
8219 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | 8106 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); |
8220 | 8107 | ||
8221 | iwl3945_rfkill_unregister(priv); | 8108 | iwl3945_rfkill_unregister(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 7f65d9123b2a..71f5da3fe5c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -250,6 +250,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
250 | 250 | ||
251 | /* always get timestamp with Rx frame */ | 251 | /* always get timestamp with Rx frame */ |
252 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; | 252 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; |
253 | /* allow CTS-to-self if possible. this is relevant only for | ||
254 | * 5000, but will not damage 4965 */ | ||
255 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | ||
253 | 256 | ||
254 | ret = iwl4965_check_rxon_cmd(&priv->staging_rxon); | 257 | ret = iwl4965_check_rxon_cmd(&priv->staging_rxon); |
255 | if (ret) { | 258 | if (ret) { |
@@ -325,16 +328,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
325 | if (!priv->error_recovering) | 328 | if (!priv->error_recovering) |
326 | priv->start_calib = 0; | 329 | priv->start_calib = 0; |
327 | 330 | ||
328 | iwl_init_sensitivity(priv); | ||
329 | |||
330 | /* If we issue a new RXON command which required a tune then we must | ||
331 | * send a new TXPOWER command or we won't be able to Tx any frames */ | ||
332 | ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
333 | if (ret) { | ||
334 | IWL_ERROR("Error sending TX power (%d)\n", ret); | ||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | /* Add the broadcast address so we can send broadcast frames */ | 331 | /* Add the broadcast address so we can send broadcast frames */ |
339 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == | 332 | if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == |
340 | IWL_INVALID_STATION) { | 333 | IWL_INVALID_STATION) { |
@@ -370,6 +363,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
370 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 363 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
371 | } | 364 | } |
372 | 365 | ||
366 | iwl_init_sensitivity(priv); | ||
367 | |||
368 | /* If we issue a new RXON command which required a tune then we must | ||
369 | * send a new TXPOWER command or we won't be able to Tx any frames */ | ||
370 | ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
371 | if (ret) { | ||
372 | IWL_ERROR("Error sending TX power (%d)\n", ret); | ||
373 | return ret; | ||
374 | } | ||
375 | |||
373 | return 0; | 376 | return 0; |
374 | } | 377 | } |
375 | 378 | ||
@@ -572,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv, | |||
572 | /* | 575 | /* |
573 | * QoS support | 576 | * QoS support |
574 | */ | 577 | */ |
575 | static int iwl4965_send_qos_params_command(struct iwl_priv *priv, | 578 | static void iwl_activate_qos(struct iwl_priv *priv, u8 force) |
576 | struct iwl4965_qosparam_cmd *qos) | ||
577 | { | ||
578 | |||
579 | return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, | ||
580 | sizeof(struct iwl4965_qosparam_cmd), qos); | ||
581 | } | ||
582 | |||
583 | static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) | ||
584 | { | 579 | { |
585 | unsigned long flags; | ||
586 | |||
587 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 580 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
588 | return; | 581 | return; |
589 | 582 | ||
590 | if (!priv->qos_data.qos_enable) | 583 | if (!priv->qos_data.qos_enable) |
591 | return; | 584 | return; |
592 | 585 | ||
593 | spin_lock_irqsave(&priv->lock, flags); | ||
594 | priv->qos_data.def_qos_parm.qos_flags = 0; | 586 | priv->qos_data.def_qos_parm.qos_flags = 0; |
595 | 587 | ||
596 | if (priv->qos_data.qos_cap.q_AP.queue_request && | 588 | if (priv->qos_data.qos_cap.q_AP.queue_request && |
@@ -604,15 +596,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) | |||
604 | if (priv->current_ht_config.is_ht) | 596 | if (priv->current_ht_config.is_ht) |
605 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 597 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
606 | 598 | ||
607 | spin_unlock_irqrestore(&priv->lock, flags); | ||
608 | |||
609 | if (force || iwl_is_associated(priv)) { | 599 | if (force || iwl_is_associated(priv)) { |
610 | IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 600 | IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
611 | priv->qos_data.qos_active, | 601 | priv->qos_data.qos_active, |
612 | priv->qos_data.def_qos_parm.qos_flags); | 602 | priv->qos_data.def_qos_parm.qos_flags); |
613 | 603 | ||
614 | iwl4965_send_qos_params_command(priv, | 604 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, |
615 | &(priv->qos_data.def_qos_parm)); | 605 | sizeof(struct iwl_qosparam_cmd), |
606 | &priv->qos_data.def_qos_parm, NULL); | ||
616 | } | 607 | } |
617 | } | 608 | } |
618 | 609 | ||
@@ -2421,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2421 | struct ieee80211_conf *conf = NULL; | 2412 | struct ieee80211_conf *conf = NULL; |
2422 | int ret = 0; | 2413 | int ret = 0; |
2423 | DECLARE_MAC_BUF(mac); | 2414 | DECLARE_MAC_BUF(mac); |
2415 | unsigned long flags; | ||
2424 | 2416 | ||
2425 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { | 2417 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { |
2426 | IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); | 2418 | IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); |
@@ -2510,25 +2502,15 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2510 | if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) | 2502 | if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) |
2511 | priv->assoc_station_added = 1; | 2503 | priv->assoc_station_added = 1; |
2512 | 2504 | ||
2513 | iwl4965_activate_qos(priv, 0); | 2505 | spin_lock_irqsave(&priv->lock, flags); |
2506 | iwl_activate_qos(priv, 0); | ||
2507 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2514 | 2508 | ||
2515 | iwl_power_update_mode(priv, 0); | 2509 | iwl_power_update_mode(priv, 0); |
2516 | /* we have just associated, don't start scan too early */ | 2510 | /* we have just associated, don't start scan too early */ |
2517 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | 2511 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; |
2518 | } | 2512 | } |
2519 | 2513 | ||
2520 | |||
2521 | static void iwl4965_bg_post_associate(struct work_struct *data) | ||
2522 | { | ||
2523 | struct iwl_priv *priv = container_of(data, struct iwl_priv, | ||
2524 | post_associate.work); | ||
2525 | |||
2526 | mutex_lock(&priv->mutex); | ||
2527 | iwl4965_post_associate(priv); | ||
2528 | mutex_unlock(&priv->mutex); | ||
2529 | |||
2530 | } | ||
2531 | |||
2532 | static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); | 2514 | static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); |
2533 | 2515 | ||
2534 | static void iwl_bg_scan_completed(struct work_struct *work) | 2516 | static void iwl_bg_scan_completed(struct work_struct *work) |
@@ -2659,7 +2641,6 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) | |||
2659 | */ | 2641 | */ |
2660 | mutex_lock(&priv->mutex); | 2642 | mutex_lock(&priv->mutex); |
2661 | iwl_scan_cancel_timeout(priv, 100); | 2643 | iwl_scan_cancel_timeout(priv, 100); |
2662 | cancel_delayed_work(&priv->post_associate); | ||
2663 | mutex_unlock(&priv->mutex); | 2644 | mutex_unlock(&priv->mutex); |
2664 | } | 2645 | } |
2665 | 2646 | ||
@@ -2855,6 +2836,7 @@ out: | |||
2855 | static void iwl4965_config_ap(struct iwl_priv *priv) | 2836 | static void iwl4965_config_ap(struct iwl_priv *priv) |
2856 | { | 2837 | { |
2857 | int ret = 0; | 2838 | int ret = 0; |
2839 | unsigned long flags; | ||
2858 | 2840 | ||
2859 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2841 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2860 | return; | 2842 | return; |
@@ -2902,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) | |||
2902 | /* restore RXON assoc */ | 2884 | /* restore RXON assoc */ |
2903 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2885 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2904 | iwl4965_commit_rxon(priv); | 2886 | iwl4965_commit_rxon(priv); |
2905 | iwl4965_activate_qos(priv, 1); | 2887 | spin_lock_irqsave(&priv->lock, flags); |
2888 | iwl_activate_qos(priv, 1); | ||
2889 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2906 | iwl_rxon_add_station(priv, iwl_bcast_addr, 0); | 2890 | iwl_rxon_add_station(priv, iwl_bcast_addr, 0); |
2907 | } | 2891 | } |
2908 | iwl4965_send_beacon_cmd(priv); | 2892 | iwl4965_send_beacon_cmd(priv); |
@@ -2912,6 +2896,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) | |||
2912 | * clear sta table, add BCAST sta... */ | 2896 | * clear sta table, add BCAST sta... */ |
2913 | } | 2897 | } |
2914 | 2898 | ||
2899 | /* temporary */ | ||
2900 | static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
2901 | |||
2915 | static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | 2902 | static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, |
2916 | struct ieee80211_vif *vif, | 2903 | struct ieee80211_vif *vif, |
2917 | struct ieee80211_if_conf *conf) | 2904 | struct ieee80211_if_conf *conf) |
@@ -2929,8 +2916,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | |||
2929 | return 0; | 2916 | return 0; |
2930 | } | 2917 | } |
2931 | 2918 | ||
2919 | if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && | ||
2920 | conf->changed & IEEE80211_IFCC_BEACON) { | ||
2921 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
2922 | if (!beacon) | ||
2923 | return -ENOMEM; | ||
2924 | rc = iwl4965_mac_beacon_update(hw, beacon); | ||
2925 | if (rc) | ||
2926 | return rc; | ||
2927 | } | ||
2928 | |||
2932 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && | 2929 | if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && |
2933 | (!conf->beacon || !conf->ssid_len)) { | 2930 | (!conf->ssid_len)) { |
2934 | IWL_DEBUG_MAC80211 | 2931 | IWL_DEBUG_MAC80211 |
2935 | ("Leaving in AP mode because HostAPD is not ready.\n"); | 2932 | ("Leaving in AP mode because HostAPD is not ready.\n"); |
2936 | return 0; | 2933 | return 0; |
@@ -2962,7 +2959,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, | |||
2962 | if (priv->ibss_beacon) | 2959 | if (priv->ibss_beacon) |
2963 | dev_kfree_skb(priv->ibss_beacon); | 2960 | dev_kfree_skb(priv->ibss_beacon); |
2964 | 2961 | ||
2965 | priv->ibss_beacon = conf->beacon; | 2962 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
2966 | } | 2963 | } |
2967 | 2964 | ||
2968 | if (iwl_is_rfkill(priv)) | 2965 | if (iwl_is_rfkill(priv)) |
@@ -3048,7 +3045,6 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, | |||
3048 | 3045 | ||
3049 | if (iwl_is_ready_rf(priv)) { | 3046 | if (iwl_is_ready_rf(priv)) { |
3050 | iwl_scan_cancel_timeout(priv, 100); | 3047 | iwl_scan_cancel_timeout(priv, 100); |
3051 | cancel_delayed_work(&priv->post_associate); | ||
3052 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3048 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3053 | iwl4965_commit_rxon(priv); | 3049 | iwl4965_commit_rxon(priv); |
3054 | } | 3050 | } |
@@ -3338,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
3338 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; | 3334 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
3339 | priv->qos_data.qos_active = 1; | 3335 | priv->qos_data.qos_active = 1; |
3340 | 3336 | ||
3341 | spin_unlock_irqrestore(&priv->lock, flags); | ||
3342 | |||
3343 | mutex_lock(&priv->mutex); | ||
3344 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) | 3337 | if (priv->iw_mode == IEEE80211_IF_TYPE_AP) |
3345 | iwl4965_activate_qos(priv, 1); | 3338 | iwl_activate_qos(priv, 1); |
3346 | else if (priv->assoc_id && iwl_is_associated(priv)) | 3339 | else if (priv->assoc_id && iwl_is_associated(priv)) |
3347 | iwl4965_activate_qos(priv, 0); | 3340 | iwl_activate_qos(priv, 0); |
3348 | 3341 | ||
3349 | mutex_unlock(&priv->mutex); | 3342 | spin_unlock_irqrestore(&priv->lock, flags); |
3350 | 3343 | ||
3351 | IWL_DEBUG_MAC80211("leave\n"); | 3344 | IWL_DEBUG_MAC80211("leave\n"); |
3352 | return 0; | 3345 | return 0; |
@@ -3413,8 +3406,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) | |||
3413 | 3406 | ||
3414 | iwl_reset_qos(priv); | 3407 | iwl_reset_qos(priv); |
3415 | 3408 | ||
3416 | cancel_delayed_work(&priv->post_associate); | ||
3417 | |||
3418 | spin_lock_irqsave(&priv->lock, flags); | 3409 | spin_lock_irqsave(&priv->lock, flags); |
3419 | priv->assoc_id = 0; | 3410 | priv->assoc_id = 0; |
3420 | priv->assoc_capability = 0; | 3411 | priv->assoc_capability = 0; |
@@ -4016,7 +4007,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
4016 | INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update); | 4007 | INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update); |
4017 | INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor); | 4008 | INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor); |
4018 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); | 4009 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); |
4019 | INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate); | ||
4020 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 4010 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
4021 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 4011 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
4022 | 4012 | ||
@@ -4043,7 +4033,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
4043 | cancel_delayed_work_sync(&priv->init_alive_start); | 4033 | cancel_delayed_work_sync(&priv->init_alive_start); |
4044 | cancel_delayed_work(&priv->scan_check); | 4034 | cancel_delayed_work(&priv->scan_check); |
4045 | cancel_delayed_work(&priv->alive_start); | 4035 | cancel_delayed_work(&priv->alive_start); |
4046 | cancel_delayed_work(&priv->post_associate); | ||
4047 | cancel_work_sync(&priv->beacon_update); | 4036 | cancel_work_sync(&priv->beacon_update); |
4048 | del_timer_sync(&priv->statistics_periodic); | 4037 | del_timer_sync(&priv->statistics_periodic); |
4049 | } | 4038 | } |
@@ -4090,7 +4079,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { | |||
4090 | .get_tx_stats = iwl4965_mac_get_tx_stats, | 4079 | .get_tx_stats = iwl4965_mac_get_tx_stats, |
4091 | .conf_tx = iwl4965_mac_conf_tx, | 4080 | .conf_tx = iwl4965_mac_conf_tx, |
4092 | .reset_tsf = iwl4965_mac_reset_tsf, | 4081 | .reset_tsf = iwl4965_mac_reset_tsf, |
4093 | .beacon_update = iwl4965_mac_beacon_update, | ||
4094 | .bss_info_changed = iwl4965_bss_info_changed, | 4082 | .bss_info_changed = iwl4965_bss_info_changed, |
4095 | .ampdu_action = iwl4965_mac_ampdu_action, | 4083 | .ampdu_action = iwl4965_mac_ampdu_action, |
4096 | .hw_scan = iwl4965_mac_hw_scan | 4084 | .hw_scan = iwl4965_mac_hw_scan |
@@ -4409,8 +4397,16 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
4409 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, | 4397 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, |
4410 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | 4398 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, |
4411 | #ifdef CONFIG_IWL5000 | 4399 | #ifdef CONFIG_IWL5000 |
4412 | {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, | 4400 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, |
4401 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, | ||
4402 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, | ||
4403 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, | ||
4404 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, | ||
4405 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, | ||
4413 | {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, | 4406 | {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, |
4407 | {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, | ||
4408 | {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, | ||
4409 | {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, | ||
4414 | {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)}, | 4410 | {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)}, |
4415 | #endif /* CONFIG_IWL5000 */ | 4411 | #endif /* CONFIG_IWL5000 */ |
4416 | {0} | 4412 | {0} |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 5d30c57e3969..913dc9fe08f9 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -126,7 +126,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, | |||
126 | (1 << IEEE80211_RADIOTAP_CHANNEL)); | 126 | (1 << IEEE80211_RADIOTAP_CHANNEL)); |
127 | hdr->rt_flags = 0; | 127 | hdr->rt_flags = 0; |
128 | hdr->rt_rate = txrate->bitrate / 5; | 128 | hdr->rt_rate = txrate->bitrate / 5; |
129 | hdr->rt_channel = data->channel->center_freq; | 129 | hdr->rt_channel = cpu_to_le16(data->channel->center_freq); |
130 | flags = IEEE80211_CHAN_2GHZ; | 130 | flags = IEEE80211_CHAN_2GHZ; |
131 | if (txrate->flags & IEEE80211_RATE_ERP_G) | 131 | if (txrate->flags & IEEE80211_RATE_ERP_G) |
132 | flags |= IEEE80211_CHAN_OFDM; | 132 | flags |= IEEE80211_CHAN_OFDM; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 91cbd9e560bd..4c0538d6099b 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1069,6 +1069,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1069 | /* | 1069 | /* |
1070 | * TX data initialization | 1070 | * TX data initialization |
1071 | */ | 1071 | */ |
1072 | static void rt2400pci_write_beacon(struct queue_entry *entry) | ||
1073 | { | ||
1074 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1075 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1076 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1077 | u32 word; | ||
1078 | u32 reg; | ||
1079 | |||
1080 | /* | ||
1081 | * Disable beaconing while we are reloading the beacon data, | ||
1082 | * otherwise we might be sending out invalid data. | ||
1083 | */ | ||
1084 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1085 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1086 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1087 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1088 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1089 | |||
1090 | /* | ||
1091 | * Replace rt2x00lib allocated descriptor with the | ||
1092 | * pointer to the _real_ hardware descriptor. | ||
1093 | * After that, map the beacon to DMA and update the | ||
1094 | * descriptor. | ||
1095 | */ | ||
1096 | memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); | ||
1097 | skbdesc->desc = entry_priv->desc; | ||
1098 | |||
1099 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | ||
1100 | |||
1101 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1102 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | ||
1103 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
1104 | } | ||
1105 | |||
1072 | static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1106 | static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1073 | const enum data_queue_qid queue) | 1107 | const enum data_queue_qid queue) |
1074 | { | 1108 | { |
@@ -1515,59 +1549,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) | |||
1515 | return tsf; | 1549 | return tsf; |
1516 | } | 1550 | } |
1517 | 1551 | ||
1518 | static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1519 | { | ||
1520 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1521 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1522 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
1523 | struct queue_entry_priv_pci *entry_priv; | ||
1524 | struct skb_frame_desc *skbdesc; | ||
1525 | struct txentry_desc txdesc; | ||
1526 | u32 reg; | ||
1527 | |||
1528 | if (unlikely(!intf->beacon)) | ||
1529 | return -ENOBUFS; | ||
1530 | entry_priv = intf->beacon->priv_data; | ||
1531 | |||
1532 | /* | ||
1533 | * Copy all TX descriptor information into txdesc, | ||
1534 | * after that we are free to use the skb->cb array | ||
1535 | * for our information. | ||
1536 | */ | ||
1537 | intf->beacon->skb = skb; | ||
1538 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
1539 | |||
1540 | /* | ||
1541 | * Fill in skb descriptor | ||
1542 | */ | ||
1543 | skbdesc = get_skb_frame_desc(skb); | ||
1544 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
1545 | skbdesc->desc = entry_priv->desc; | ||
1546 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
1547 | skbdesc->entry = intf->beacon; | ||
1548 | |||
1549 | /* | ||
1550 | * Disable beaconing while we are reloading the beacon data, | ||
1551 | * otherwise we might be sending out invalid data. | ||
1552 | */ | ||
1553 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1554 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1555 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1556 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1557 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1558 | |||
1559 | /* | ||
1560 | * Enable beacon generation. | ||
1561 | * Write entire beacon with descriptor to register, | ||
1562 | * and kick the beacon generator. | ||
1563 | */ | ||
1564 | rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); | ||
1565 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1566 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | ||
1567 | |||
1568 | return 0; | ||
1569 | } | ||
1570 | |||
1571 | static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) | 1552 | static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) |
1572 | { | 1553 | { |
1573 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1554 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -1592,7 +1573,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { | |||
1592 | .conf_tx = rt2400pci_conf_tx, | 1573 | .conf_tx = rt2400pci_conf_tx, |
1593 | .get_tx_stats = rt2x00mac_get_tx_stats, | 1574 | .get_tx_stats = rt2x00mac_get_tx_stats, |
1594 | .get_tsf = rt2400pci_get_tsf, | 1575 | .get_tsf = rt2400pci_get_tsf, |
1595 | .beacon_update = rt2400pci_beacon_update, | ||
1596 | .tx_last_beacon = rt2400pci_tx_last_beacon, | 1576 | .tx_last_beacon = rt2400pci_tx_last_beacon, |
1597 | }; | 1577 | }; |
1598 | 1578 | ||
@@ -1610,6 +1590,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { | |||
1610 | .link_tuner = rt2400pci_link_tuner, | 1590 | .link_tuner = rt2400pci_link_tuner, |
1611 | .write_tx_desc = rt2400pci_write_tx_desc, | 1591 | .write_tx_desc = rt2400pci_write_tx_desc, |
1612 | .write_tx_data = rt2x00pci_write_tx_data, | 1592 | .write_tx_data = rt2x00pci_write_tx_data, |
1593 | .write_beacon = rt2400pci_write_beacon, | ||
1613 | .kick_tx_queue = rt2400pci_kick_tx_queue, | 1594 | .kick_tx_queue = rt2400pci_kick_tx_queue, |
1614 | .fill_rxdone = rt2400pci_fill_rxdone, | 1595 | .fill_rxdone = rt2400pci_fill_rxdone, |
1615 | .config_filter = rt2400pci_config_filter, | 1596 | .config_filter = rt2400pci_config_filter, |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0f2a0e22fd71..aa6dfb811c71 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1227,6 +1227,40 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1227 | /* | 1227 | /* |
1228 | * TX data initialization | 1228 | * TX data initialization |
1229 | */ | 1229 | */ |
1230 | static void rt2500pci_write_beacon(struct queue_entry *entry) | ||
1231 | { | ||
1232 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1233 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1234 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1235 | u32 word; | ||
1236 | u32 reg; | ||
1237 | |||
1238 | /* | ||
1239 | * Disable beaconing while we are reloading the beacon data, | ||
1240 | * otherwise we might be sending out invalid data. | ||
1241 | */ | ||
1242 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1243 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1244 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1245 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1246 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1247 | |||
1248 | /* | ||
1249 | * Replace rt2x00lib allocated descriptor with the | ||
1250 | * pointer to the _real_ hardware descriptor. | ||
1251 | * After that, map the beacon to DMA and update the | ||
1252 | * descriptor. | ||
1253 | */ | ||
1254 | memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); | ||
1255 | skbdesc->desc = entry_priv->desc; | ||
1256 | |||
1257 | rt2x00queue_map_txskb(rt2x00dev, entry->skb); | ||
1258 | |||
1259 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1260 | rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); | ||
1261 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
1262 | } | ||
1263 | |||
1230 | static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1264 | static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1231 | const enum data_queue_qid queue) | 1265 | const enum data_queue_qid queue) |
1232 | { | 1266 | { |
@@ -1808,60 +1842,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) | |||
1808 | return tsf; | 1842 | return tsf; |
1809 | } | 1843 | } |
1810 | 1844 | ||
1811 | static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1812 | { | ||
1813 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1814 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1815 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
1816 | struct queue_entry_priv_pci *entry_priv; | ||
1817 | struct skb_frame_desc *skbdesc; | ||
1818 | struct txentry_desc txdesc; | ||
1819 | u32 reg; | ||
1820 | |||
1821 | if (unlikely(!intf->beacon)) | ||
1822 | return -ENOBUFS; | ||
1823 | |||
1824 | entry_priv = intf->beacon->priv_data; | ||
1825 | |||
1826 | /* | ||
1827 | * Copy all TX descriptor information into txdesc, | ||
1828 | * after that we are free to use the skb->cb array | ||
1829 | * for our information. | ||
1830 | */ | ||
1831 | intf->beacon->skb = skb; | ||
1832 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
1833 | |||
1834 | /* | ||
1835 | * Fill in skb descriptor | ||
1836 | */ | ||
1837 | skbdesc = get_skb_frame_desc(skb); | ||
1838 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
1839 | skbdesc->desc = entry_priv->desc; | ||
1840 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
1841 | skbdesc->entry = intf->beacon; | ||
1842 | |||
1843 | /* | ||
1844 | * Disable beaconing while we are reloading the beacon data, | ||
1845 | * otherwise we might be sending out invalid data. | ||
1846 | */ | ||
1847 | rt2x00pci_register_read(rt2x00dev, CSR14, ®); | ||
1848 | rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); | ||
1849 | rt2x00_set_field32(®, CSR14_TBCN, 0); | ||
1850 | rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); | ||
1851 | rt2x00pci_register_write(rt2x00dev, CSR14, reg); | ||
1852 | |||
1853 | /* | ||
1854 | * Enable beacon generation. | ||
1855 | * Write entire beacon with descriptor to register, | ||
1856 | * and kick the beacon generator. | ||
1857 | */ | ||
1858 | rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); | ||
1859 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1860 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | ||
1861 | |||
1862 | return 0; | ||
1863 | } | ||
1864 | |||
1865 | static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) | 1845 | static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) |
1866 | { | 1846 | { |
1867 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1847 | struct rt2x00_dev *rt2x00dev = hw->priv; |
@@ -1886,7 +1866,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { | |||
1886 | .conf_tx = rt2x00mac_conf_tx, | 1866 | .conf_tx = rt2x00mac_conf_tx, |
1887 | .get_tx_stats = rt2x00mac_get_tx_stats, | 1867 | .get_tx_stats = rt2x00mac_get_tx_stats, |
1888 | .get_tsf = rt2500pci_get_tsf, | 1868 | .get_tsf = rt2500pci_get_tsf, |
1889 | .beacon_update = rt2500pci_beacon_update, | ||
1890 | .tx_last_beacon = rt2500pci_tx_last_beacon, | 1869 | .tx_last_beacon = rt2500pci_tx_last_beacon, |
1891 | }; | 1870 | }; |
1892 | 1871 | ||
@@ -1904,6 +1883,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { | |||
1904 | .link_tuner = rt2500pci_link_tuner, | 1883 | .link_tuner = rt2500pci_link_tuner, |
1905 | .write_tx_desc = rt2500pci_write_tx_desc, | 1884 | .write_tx_desc = rt2500pci_write_tx_desc, |
1906 | .write_tx_data = rt2x00pci_write_tx_data, | 1885 | .write_tx_data = rt2x00pci_write_tx_data, |
1886 | .write_beacon = rt2500pci_write_beacon, | ||
1907 | .kick_tx_queue = rt2500pci_kick_tx_queue, | 1887 | .kick_tx_queue = rt2500pci_kick_tx_queue, |
1908 | .fill_rxdone = rt2500pci_fill_rxdone, | 1888 | .fill_rxdone = rt2500pci_fill_rxdone, |
1909 | .config_filter = rt2500pci_config_filter, | 1889 | .config_filter = rt2500pci_config_filter, |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 367db10b96d9..3558cb210747 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1107,6 +1107,65 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1107 | rt2x00_desc_write(txd, 0, word); | 1107 | rt2x00_desc_write(txd, 0, word); |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | /* | ||
1111 | * TX data initialization | ||
1112 | */ | ||
1113 | static void rt2500usb_beacondone(struct urb *urb); | ||
1114 | |||
1115 | static void rt2500usb_write_beacon(struct queue_entry *entry) | ||
1116 | { | ||
1117 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1118 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | ||
1119 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | ||
1120 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1121 | int pipe = usb_sndbulkpipe(usb_dev, 1); | ||
1122 | int length; | ||
1123 | u16 reg; | ||
1124 | |||
1125 | /* | ||
1126 | * Add the descriptor in front of the skb. | ||
1127 | */ | ||
1128 | skb_push(entry->skb, entry->queue->desc_size); | ||
1129 | memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); | ||
1130 | skbdesc->desc = entry->skb->data; | ||
1131 | |||
1132 | /* | ||
1133 | * Disable beaconing while we are reloading the beacon data, | ||
1134 | * otherwise we might be sending out invalid data. | ||
1135 | */ | ||
1136 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | ||
1137 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); | ||
1138 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); | ||
1139 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); | ||
1140 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | ||
1141 | |||
1142 | /* | ||
1143 | * USB devices cannot blindly pass the skb->len as the | ||
1144 | * length of the data to usb_fill_bulk_urb. Pass the skb | ||
1145 | * to the driver to determine what the length should be. | ||
1146 | */ | ||
1147 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); | ||
1148 | |||
1149 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, | ||
1150 | entry->skb->data, length, rt2500usb_beacondone, | ||
1151 | entry); | ||
1152 | |||
1153 | /* | ||
1154 | * Second we need to create the guardian byte. | ||
1155 | * We only need a single byte, so lets recycle | ||
1156 | * the 'flags' field we are not using for beacons. | ||
1157 | */ | ||
1158 | bcn_priv->guardian_data = 0; | ||
1159 | usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, | ||
1160 | &bcn_priv->guardian_data, 1, rt2500usb_beacondone, | ||
1161 | entry); | ||
1162 | |||
1163 | /* | ||
1164 | * Send out the guardian byte. | ||
1165 | */ | ||
1166 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); | ||
1167 | } | ||
1168 | |||
1110 | static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1169 | static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, |
1111 | struct sk_buff *skb) | 1170 | struct sk_buff *skb) |
1112 | { | 1171 | { |
@@ -1122,9 +1181,6 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1122 | return length; | 1181 | return length; |
1123 | } | 1182 | } |
1124 | 1183 | ||
1125 | /* | ||
1126 | * TX data initialization | ||
1127 | */ | ||
1128 | static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1184 | static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1129 | const enum data_queue_qid queue) | 1185 | const enum data_queue_qid queue) |
1130 | { | 1186 | { |
@@ -1679,96 +1735,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1679 | return 0; | 1735 | return 0; |
1680 | } | 1736 | } |
1681 | 1737 | ||
1682 | /* | ||
1683 | * IEEE80211 stack callback functions. | ||
1684 | */ | ||
1685 | static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1686 | { | ||
1687 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1688 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | ||
1689 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1690 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
1691 | struct queue_entry_priv_usb_bcn *bcn_priv; | ||
1692 | struct skb_frame_desc *skbdesc; | ||
1693 | struct txentry_desc txdesc; | ||
1694 | int pipe = usb_sndbulkpipe(usb_dev, 1); | ||
1695 | int length; | ||
1696 | u16 reg; | ||
1697 | |||
1698 | if (unlikely(!intf->beacon)) | ||
1699 | return -ENOBUFS; | ||
1700 | |||
1701 | bcn_priv = intf->beacon->priv_data; | ||
1702 | |||
1703 | /* | ||
1704 | * Copy all TX descriptor information into txdesc, | ||
1705 | * after that we are free to use the skb->cb array | ||
1706 | * for our information. | ||
1707 | */ | ||
1708 | intf->beacon->skb = skb; | ||
1709 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
1710 | |||
1711 | /* | ||
1712 | * Add the descriptor in front of the skb. | ||
1713 | */ | ||
1714 | skb_push(skb, intf->beacon->queue->desc_size); | ||
1715 | memset(skb->data, 0, intf->beacon->queue->desc_size); | ||
1716 | |||
1717 | /* | ||
1718 | * Fill in skb descriptor | ||
1719 | */ | ||
1720 | skbdesc = get_skb_frame_desc(skb); | ||
1721 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
1722 | skbdesc->desc = skb->data; | ||
1723 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
1724 | skbdesc->entry = intf->beacon; | ||
1725 | |||
1726 | /* | ||
1727 | * Disable beaconing while we are reloading the beacon data, | ||
1728 | * otherwise we might be sending out invalid data. | ||
1729 | */ | ||
1730 | rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); | ||
1731 | rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); | ||
1732 | rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); | ||
1733 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); | ||
1734 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | ||
1735 | |||
1736 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1737 | |||
1738 | /* | ||
1739 | * USB devices cannot blindly pass the skb->len as the | ||
1740 | * length of the data to usb_fill_bulk_urb. Pass the skb | ||
1741 | * to the driver to determine what the length should be. | ||
1742 | */ | ||
1743 | length = rt2500usb_get_tx_data_len(rt2x00dev, skb); | ||
1744 | |||
1745 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, | ||
1746 | skb->data, length, rt2500usb_beacondone, | ||
1747 | intf->beacon); | ||
1748 | |||
1749 | /* | ||
1750 | * Second we need to create the guardian byte. | ||
1751 | * We only need a single byte, so lets recycle | ||
1752 | * the 'flags' field we are not using for beacons. | ||
1753 | */ | ||
1754 | bcn_priv->guardian_data = 0; | ||
1755 | usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, | ||
1756 | &bcn_priv->guardian_data, 1, rt2500usb_beacondone, | ||
1757 | intf->beacon); | ||
1758 | |||
1759 | /* | ||
1760 | * Send out the guardian byte. | ||
1761 | */ | ||
1762 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); | ||
1763 | |||
1764 | /* | ||
1765 | * Enable beacon generation. | ||
1766 | */ | ||
1767 | rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON); | ||
1768 | |||
1769 | return 0; | ||
1770 | } | ||
1771 | |||
1772 | static const struct ieee80211_ops rt2500usb_mac80211_ops = { | 1738 | static const struct ieee80211_ops rt2500usb_mac80211_ops = { |
1773 | .tx = rt2x00mac_tx, | 1739 | .tx = rt2x00mac_tx, |
1774 | .start = rt2x00mac_start, | 1740 | .start = rt2x00mac_start, |
@@ -1782,7 +1748,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { | |||
1782 | .bss_info_changed = rt2x00mac_bss_info_changed, | 1748 | .bss_info_changed = rt2x00mac_bss_info_changed, |
1783 | .conf_tx = rt2x00mac_conf_tx, | 1749 | .conf_tx = rt2x00mac_conf_tx, |
1784 | .get_tx_stats = rt2x00mac_get_tx_stats, | 1750 | .get_tx_stats = rt2x00mac_get_tx_stats, |
1785 | .beacon_update = rt2500usb_beacon_update, | ||
1786 | }; | 1751 | }; |
1787 | 1752 | ||
1788 | static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | 1753 | static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { |
@@ -1797,6 +1762,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { | |||
1797 | .link_tuner = rt2500usb_link_tuner, | 1762 | .link_tuner = rt2500usb_link_tuner, |
1798 | .write_tx_desc = rt2500usb_write_tx_desc, | 1763 | .write_tx_desc = rt2500usb_write_tx_desc, |
1799 | .write_tx_data = rt2x00usb_write_tx_data, | 1764 | .write_tx_data = rt2x00usb_write_tx_data, |
1765 | .write_beacon = rt2500usb_write_beacon, | ||
1800 | .get_tx_data_len = rt2500usb_get_tx_data_len, | 1766 | .get_tx_data_len = rt2500usb_get_tx_data_len, |
1801 | .kick_tx_queue = rt2500usb_kick_tx_queue, | 1767 | .kick_tx_queue = rt2500usb_kick_tx_queue, |
1802 | .fill_rxdone = rt2500usb_fill_rxdone, | 1768 | .fill_rxdone = rt2500usb_fill_rxdone, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c07d9ef383f0..9fab0df18c3c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -364,6 +364,8 @@ struct rt2x00_intf { | |||
364 | #define DELAYED_UPDATE_BEACON 0x00000001 | 364 | #define DELAYED_UPDATE_BEACON 0x00000001 |
365 | #define DELAYED_CONFIG_ERP 0x00000002 | 365 | #define DELAYED_CONFIG_ERP 0x00000002 |
366 | #define DELAYED_LED_ASSOC 0x00000004 | 366 | #define DELAYED_LED_ASSOC 0x00000004 |
367 | |||
368 | u16 seqno; | ||
367 | }; | 369 | }; |
368 | 370 | ||
369 | static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) | 371 | static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) |
@@ -434,6 +436,7 @@ struct rt2x00lib_conf { | |||
434 | */ | 436 | */ |
435 | struct rt2x00lib_erp { | 437 | struct rt2x00lib_erp { |
436 | int short_preamble; | 438 | int short_preamble; |
439 | int cts_protection; | ||
437 | 440 | ||
438 | int ack_timeout; | 441 | int ack_timeout; |
439 | int ack_consume_time; | 442 | int ack_consume_time; |
@@ -520,6 +523,7 @@ struct rt2x00lib_ops { | |||
520 | struct sk_buff *skb, | 523 | struct sk_buff *skb, |
521 | struct txentry_desc *txdesc); | 524 | struct txentry_desc *txdesc); |
522 | int (*write_tx_data) (struct queue_entry *entry); | 525 | int (*write_tx_data) (struct queue_entry *entry); |
526 | void (*write_beacon) (struct queue_entry *entry); | ||
523 | int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, | 527 | int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, |
524 | struct sk_buff *skb); | 528 | struct sk_buff *skb); |
525 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, | 529 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, |
@@ -910,39 +914,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) | |||
910 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | 914 | void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); |
911 | 915 | ||
912 | /** | 916 | /** |
913 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input | ||
914 | * @entry: The entry which will be used to transfer the TX frame. | ||
915 | * @txdesc: rt2x00 TX descriptor which will be initialized by this function. | ||
916 | * | ||
917 | * This function will initialize the &struct txentry_desc based on information | ||
918 | * from mac80211. This descriptor can then be used by rt2x00lib and the drivers | ||
919 | * to correctly initialize the hardware descriptor. | ||
920 | * Note that before calling this function the skb->cb array must be untouched | ||
921 | * by rt2x00lib. Only after this function completes will it be save to | ||
922 | * overwrite the skb->cb information. | ||
923 | * The reason for this is that mac80211 writes its own tx information into | ||
924 | * the skb->cb array, and this function will use that information to initialize | ||
925 | * the &struct txentry_desc structure. | ||
926 | */ | ||
927 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | ||
928 | struct txentry_desc *txdesc); | ||
929 | |||
930 | /** | ||
931 | * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware | ||
932 | * @entry: The entry which will be used to transfer the TX frame. | ||
933 | * @txdesc: TX descriptor which will be used to write hardware descriptor | ||
934 | * | ||
935 | * This function will write a TX descriptor initialized by | ||
936 | * &rt2x00queue_create_tx_descriptor to the hardware. After this call | ||
937 | * has completed the frame is now owned by the hardware, the hardware | ||
938 | * queue will have automatically be kicked unless this frame was generated | ||
939 | * by rt2x00lib, in which case the frame is "special" and must be kicked | ||
940 | * by the caller. | ||
941 | */ | ||
942 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | ||
943 | struct txentry_desc *txdesc); | ||
944 | |||
945 | /** | ||
946 | * rt2x00queue_get_queue - Convert queue index to queue pointer | 917 | * rt2x00queue_get_queue - Convert queue index to queue pointer |
947 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 918 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
948 | * @queue: rt2x00 queue index (see &enum data_queue_qid). | 919 | * @queue: rt2x00 queue index (see &enum data_queue_qid). |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48608e8cc8b4..f20ca712504f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -84,6 +84,8 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, | |||
84 | memset(&erp, 0, sizeof(erp)); | 84 | memset(&erp, 0, sizeof(erp)); |
85 | 85 | ||
86 | erp.short_preamble = bss_conf->use_short_preamble; | 86 | erp.short_preamble = bss_conf->use_short_preamble; |
87 | erp.cts_protection = bss_conf->use_cts_prot; | ||
88 | |||
87 | erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); | 89 | erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); |
88 | erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); | 90 | erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); |
89 | 91 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b48c04e80a38..8c93eb8353b0 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 | ||
@@ -435,12 +434,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
435 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) | 434 | if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) |
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 | rt2x00queue_update_beacon(rt2x00dev, vif); |
440 | if (skb && | ||
441 | rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb)) | ||
442 | dev_kfree_skb(skb); | ||
443 | } | ||
444 | 439 | ||
445 | if (delayed_flags & DELAYED_CONFIG_ERP) | 440 | if (delayed_flags & DELAYED_CONFIG_ERP) |
446 | rt2x00lib_config_erp(rt2x00dev, intf, &conf); | 441 | rt2x00lib_config_erp(rt2x00dev, intf, &conf); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b971bc6e7ee2..bab05a56e7a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c | |||
@@ -100,6 +100,14 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) | |||
100 | retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, | 100 | retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, |
101 | rt2x00dev->fw->data, | 101 | rt2x00dev->fw->data, |
102 | rt2x00dev->fw->size); | 102 | rt2x00dev->fw->size); |
103 | |||
104 | /* | ||
105 | * When the firmware is uploaded to the hardware the LED | ||
106 | * association status might have been triggered, for correct | ||
107 | * LED handling it should now be reset. | ||
108 | */ | ||
109 | rt2x00leds_led_assoc(rt2x00dev, false); | ||
110 | |||
103 | return retval; | 111 | return retval; |
104 | } | 112 | } |
105 | 113 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index eae5ce1d4de3..f2c9b0e79b5f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -139,6 +139,14 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); | |||
139 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); | 139 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); |
140 | 140 | ||
141 | /** | 141 | /** |
142 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware | ||
143 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | ||
144 | * @vif: Interface for which the beacon should be updated. | ||
145 | */ | ||
146 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | ||
147 | struct ieee80211_vif *vif); | ||
148 | |||
149 | /** | ||
142 | * rt2x00queue_index_inc - Index incrementation function | 150 | * rt2x00queue_index_inc - Index incrementation function |
143 | * @queue: Queue (&struct data_queue) to perform the action on. | 151 | * @queue: Queue (&struct data_queue) to perform the action on. |
144 | * @index: Index type (&enum queue_index) to perform the action on. | 152 | * @index: Index type (&enum queue_index) to perform the action on. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 3a1fb6d47e5d..77af1df5d899 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -96,6 +96,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
96 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 96 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
97 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; | 97 | struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; |
98 | enum data_queue_qid qid = skb_get_queue_mapping(skb); | 98 | enum data_queue_qid qid = skb_get_queue_mapping(skb); |
99 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
99 | struct data_queue *queue; | 100 | struct data_queue *queue; |
100 | u16 frame_control; | 101 | u16 frame_control; |
101 | 102 | ||
@@ -151,6 +152,18 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
151 | } | 152 | } |
152 | } | 153 | } |
153 | 154 | ||
155 | /* | ||
156 | * XXX: This is as wrong as the old mac80211 code was, | ||
157 | * due to beacons not getting sequence numbers assigned | ||
158 | * properly. | ||
159 | */ | ||
160 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
161 | if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
162 | intf->seqno += 0x10; | ||
163 | ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
164 | ieee80211hdr->seq_ctrl |= cpu_to_le16(intf->seqno); | ||
165 | } | ||
166 | |||
154 | if (rt2x00queue_write_tx_frame(queue, skb)) { | 167 | if (rt2x00queue_write_tx_frame(queue, skb)) { |
155 | ieee80211_stop_queue(rt2x00dev->hw, qid); | 168 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
156 | return NETDEV_TX_BUSY; | 169 | return NETDEV_TX_BUSY; |
@@ -348,7 +361,8 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, | |||
348 | { | 361 | { |
349 | struct rt2x00_dev *rt2x00dev = hw->priv; | 362 | struct rt2x00_dev *rt2x00dev = hw->priv; |
350 | struct rt2x00_intf *intf = vif_to_intf(vif); | 363 | struct rt2x00_intf *intf = vif_to_intf(vif); |
351 | int status; | 364 | int update_bssid = 0; |
365 | int status = 0; | ||
352 | 366 | ||
353 | /* | 367 | /* |
354 | * Mac80211 might be calling this function while we are trying | 368 | * Mac80211 might be calling this function while we are trying |
@@ -360,12 +374,13 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, | |||
360 | spin_lock(&intf->lock); | 374 | spin_lock(&intf->lock); |
361 | 375 | ||
362 | /* | 376 | /* |
363 | * If the interface does not work in master mode, | 377 | * conf->bssid can be NULL if coming from the internal |
364 | * then the bssid value in the interface structure | 378 | * beacon update routine. |
365 | * should now be set. | ||
366 | */ | 379 | */ |
367 | if (conf->type != IEEE80211_IF_TYPE_AP) | 380 | if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { |
381 | update_bssid = 1; | ||
368 | memcpy(&intf->bssid, conf->bssid, ETH_ALEN); | 382 | memcpy(&intf->bssid, conf->bssid, ETH_ALEN); |
383 | } | ||
369 | 384 | ||
370 | spin_unlock(&intf->lock); | 385 | spin_unlock(&intf->lock); |
371 | 386 | ||
@@ -375,17 +390,14 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, | |||
375 | * values as arguments we make keep access to rt2x00_intf thread safe | 390 | * values as arguments we make keep access to rt2x00_intf thread safe |
376 | * even without the lock. | 391 | * even without the lock. |
377 | */ | 392 | */ |
378 | rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid); | 393 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, |
394 | update_bssid ? conf->bssid : NULL); | ||
379 | 395 | ||
380 | /* | 396 | /* |
381 | * We only need to initialize the beacon when master mode is enabled. | 397 | * Update the beacon. |
382 | */ | 398 | */ |
383 | if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon) | 399 | if (conf->changed & IEEE80211_IFCC_BEACON) |
384 | return 0; | 400 | status = rt2x00queue_update_beacon(rt2x00dev, vif); |
385 | |||
386 | status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon); | ||
387 | if (status) | ||
388 | dev_kfree_skb(conf->beacon); | ||
389 | 401 | ||
390 | return status; | 402 | return status; |
391 | } | 403 | } |
@@ -501,7 +513,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
501 | * When the erp information has changed, we should perform | 513 | * When the erp information has changed, we should perform |
502 | * additional configuration steps. For all other changes we are done. | 514 | * additional configuration steps. For all other changes we are done. |
503 | */ | 515 | */ |
504 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | 516 | if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_CTS_PROT)) { |
505 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 517 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) |
506 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); | 518 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); |
507 | else | 519 | else |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 3ddce538ef4a..7f442030f5ad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -108,12 +108,15 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
108 | 108 | ||
109 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | 109 | void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) |
110 | { | 110 | { |
111 | if (!skb) | ||
112 | return; | ||
113 | |||
111 | rt2x00queue_unmap_skb(rt2x00dev, skb); | 114 | rt2x00queue_unmap_skb(rt2x00dev, skb); |
112 | dev_kfree_skb_any(skb); | 115 | dev_kfree_skb_any(skb); |
113 | } | 116 | } |
114 | 117 | ||
115 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | 118 | static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, |
116 | struct txentry_desc *txdesc) | 119 | struct txentry_desc *txdesc) |
117 | { | 120 | { |
118 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 121 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
119 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | 122 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); |
@@ -237,10 +240,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
237 | txdesc->signal |= 0x08; | 240 | txdesc->signal |= 0x08; |
238 | } | 241 | } |
239 | } | 242 | } |
240 | EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); | ||
241 | 243 | ||
242 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | 244 | static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, |
243 | struct txentry_desc *txdesc) | 245 | struct txentry_desc *txdesc) |
244 | { | 246 | { |
245 | struct data_queue *queue = entry->queue; | 247 | struct data_queue *queue = entry->queue; |
246 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; | 248 | struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; |
@@ -270,7 +272,6 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
270 | !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) | 272 | !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) |
271 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); | 273 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); |
272 | } | 274 | } |
273 | EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); | ||
274 | 275 | ||
275 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | 276 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) |
276 | { | 277 | { |
@@ -320,6 +321,60 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
320 | return 0; | 321 | return 0; |
321 | } | 322 | } |
322 | 323 | ||
324 | int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, | ||
325 | struct ieee80211_vif *vif) | ||
326 | { | ||
327 | struct rt2x00_intf *intf = vif_to_intf(vif); | ||
328 | struct skb_frame_desc *skbdesc; | ||
329 | struct txentry_desc txdesc; | ||
330 | __le32 desc[16]; | ||
331 | |||
332 | if (unlikely(!intf->beacon)) | ||
333 | return -ENOBUFS; | ||
334 | |||
335 | intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); | ||
336 | if (!intf->beacon->skb) | ||
337 | return -ENOMEM; | ||
338 | |||
339 | /* | ||
340 | * Copy all TX descriptor information into txdesc, | ||
341 | * after that we are free to use the skb->cb array | ||
342 | * for our information. | ||
343 | */ | ||
344 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
345 | |||
346 | /* | ||
347 | * For the descriptor we use a local array from where the | ||
348 | * driver can move it to the correct location required for | ||
349 | * the hardware. | ||
350 | */ | ||
351 | memset(desc, 0, sizeof(desc)); | ||
352 | |||
353 | /* | ||
354 | * Fill in skb descriptor | ||
355 | */ | ||
356 | skbdesc = get_skb_frame_desc(intf->beacon->skb); | ||
357 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
358 | skbdesc->desc = desc; | ||
359 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
360 | skbdesc->entry = intf->beacon; | ||
361 | |||
362 | /* | ||
363 | * Write TX descriptor into reserved room in front of the beacon. | ||
364 | */ | ||
365 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
366 | |||
367 | /* | ||
368 | * Send beacon to hardware. | ||
369 | * Also enable beacon generation, which might have been disabled | ||
370 | * by the driver during the config_beacon() callback function. | ||
371 | */ | ||
372 | rt2x00dev->ops->lib->write_beacon(intf->beacon); | ||
373 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
323 | struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, | 378 | struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, |
324 | const enum data_queue_qid queue) | 379 | const enum data_queue_qid queue) |
325 | { | 380 | { |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 5a1330c5de71..70ef7bf434ab 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1600,6 +1600,41 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1600 | /* | 1600 | /* |
1601 | * TX data initialization | 1601 | * TX data initialization |
1602 | */ | 1602 | */ |
1603 | static void rt61pci_write_beacon(struct queue_entry *entry) | ||
1604 | { | ||
1605 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1606 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1607 | unsigned int beacon_base; | ||
1608 | u32 reg; | ||
1609 | |||
1610 | /* | ||
1611 | * Disable beaconing while we are reloading the beacon data, | ||
1612 | * otherwise we might be sending out invalid data. | ||
1613 | */ | ||
1614 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
1615 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | ||
1616 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | ||
1617 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
1618 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1619 | |||
1620 | /* | ||
1621 | * Write entire beacon with descriptor to register. | ||
1622 | */ | ||
1623 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
1624 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
1625 | beacon_base, | ||
1626 | skbdesc->desc, skbdesc->desc_len); | ||
1627 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
1628 | beacon_base + skbdesc->desc_len, | ||
1629 | entry->skb->data, entry->skb->len); | ||
1630 | |||
1631 | /* | ||
1632 | * Clean up beacon skb. | ||
1633 | */ | ||
1634 | dev_kfree_skb_any(entry->skb); | ||
1635 | entry->skb = NULL; | ||
1636 | } | ||
1637 | |||
1603 | static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1638 | static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1604 | const enum data_queue_qid queue) | 1639 | const enum data_queue_qid queue) |
1605 | { | 1640 | { |
@@ -2355,72 +2390,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) | |||
2355 | return tsf; | 2390 | return tsf; |
2356 | } | 2391 | } |
2357 | 2392 | ||
2358 | static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
2359 | { | ||
2360 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
2361 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
2362 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
2363 | struct queue_entry_priv_pci *entry_priv; | ||
2364 | struct skb_frame_desc *skbdesc; | ||
2365 | struct txentry_desc txdesc; | ||
2366 | unsigned int beacon_base; | ||
2367 | u32 reg; | ||
2368 | |||
2369 | if (unlikely(!intf->beacon)) | ||
2370 | return -ENOBUFS; | ||
2371 | |||
2372 | /* | ||
2373 | * Copy all TX descriptor information into txdesc, | ||
2374 | * after that we are free to use the skb->cb array | ||
2375 | * for our information. | ||
2376 | */ | ||
2377 | intf->beacon->skb = skb; | ||
2378 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
2379 | |||
2380 | entry_priv = intf->beacon->priv_data; | ||
2381 | memset(entry_priv->desc, 0, intf->beacon->queue->desc_size); | ||
2382 | |||
2383 | /* | ||
2384 | * Fill in skb descriptor | ||
2385 | */ | ||
2386 | skbdesc = get_skb_frame_desc(skb); | ||
2387 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
2388 | skbdesc->desc = entry_priv->desc; | ||
2389 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
2390 | skbdesc->entry = intf->beacon; | ||
2391 | |||
2392 | /* | ||
2393 | * Disable beaconing while we are reloading the beacon data, | ||
2394 | * otherwise we might be sending out invalid data. | ||
2395 | */ | ||
2396 | rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
2397 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | ||
2398 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | ||
2399 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
2400 | rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2401 | |||
2402 | /* | ||
2403 | * Write entire beacon with descriptor to register, | ||
2404 | * and kick the beacon generator. | ||
2405 | */ | ||
2406 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
2407 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
2408 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, | ||
2409 | skbdesc->desc, skbdesc->desc_len); | ||
2410 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
2411 | beacon_base + skbdesc->desc_len, | ||
2412 | skb->data, skb->len); | ||
2413 | rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); | ||
2414 | |||
2415 | /* | ||
2416 | * Clean up beacon skb. | ||
2417 | */ | ||
2418 | dev_kfree_skb_any(skb); | ||
2419 | intf->beacon->skb = NULL; | ||
2420 | |||
2421 | return 0; | ||
2422 | } | ||
2423 | |||
2424 | static const struct ieee80211_ops rt61pci_mac80211_ops = { | 2393 | static const struct ieee80211_ops rt61pci_mac80211_ops = { |
2425 | .tx = rt2x00mac_tx, | 2394 | .tx = rt2x00mac_tx, |
2426 | .start = rt2x00mac_start, | 2395 | .start = rt2x00mac_start, |
@@ -2436,7 +2405,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { | |||
2436 | .conf_tx = rt2x00mac_conf_tx, | 2405 | .conf_tx = rt2x00mac_conf_tx, |
2437 | .get_tx_stats = rt2x00mac_get_tx_stats, | 2406 | .get_tx_stats = rt2x00mac_get_tx_stats, |
2438 | .get_tsf = rt61pci_get_tsf, | 2407 | .get_tsf = rt61pci_get_tsf, |
2439 | .beacon_update = rt61pci_beacon_update, | ||
2440 | }; | 2408 | }; |
2441 | 2409 | ||
2442 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | 2410 | static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { |
@@ -2456,6 +2424,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { | |||
2456 | .link_tuner = rt61pci_link_tuner, | 2424 | .link_tuner = rt61pci_link_tuner, |
2457 | .write_tx_desc = rt61pci_write_tx_desc, | 2425 | .write_tx_desc = rt61pci_write_tx_desc, |
2458 | .write_tx_data = rt2x00pci_write_tx_data, | 2426 | .write_tx_data = rt2x00pci_write_tx_data, |
2427 | .write_beacon = rt61pci_write_beacon, | ||
2459 | .kick_tx_queue = rt61pci_kick_tx_queue, | 2428 | .kick_tx_queue = rt61pci_kick_tx_queue, |
2460 | .fill_rxdone = rt61pci_fill_rxdone, | 2429 | .fill_rxdone = rt61pci_fill_rxdone, |
2461 | .config_filter = rt61pci_config_filter, | 2430 | .config_filter = rt61pci_config_filter, |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 25d8b660051f..34c6ff27afc4 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1343,6 +1343,49 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1343 | rt2x00_desc_write(txd, 0, word); | 1343 | rt2x00_desc_write(txd, 0, word); |
1344 | } | 1344 | } |
1345 | 1345 | ||
1346 | /* | ||
1347 | * TX data initialization | ||
1348 | */ | ||
1349 | static void rt73usb_write_beacon(struct queue_entry *entry) | ||
1350 | { | ||
1351 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1352 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1353 | unsigned int beacon_base; | ||
1354 | u32 reg; | ||
1355 | |||
1356 | /* | ||
1357 | * Add the descriptor in front of the skb. | ||
1358 | */ | ||
1359 | skb_push(entry->skb, entry->queue->desc_size); | ||
1360 | memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); | ||
1361 | skbdesc->desc = entry->skb->data; | ||
1362 | |||
1363 | /* | ||
1364 | * Disable beaconing while we are reloading the beacon data, | ||
1365 | * otherwise we might be sending out invalid data. | ||
1366 | */ | ||
1367 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
1368 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | ||
1369 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | ||
1370 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
1371 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
1372 | |||
1373 | /* | ||
1374 | * Write entire beacon with descriptor to register. | ||
1375 | */ | ||
1376 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
1377 | rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, | ||
1378 | USB_VENDOR_REQUEST_OUT, beacon_base, 0, | ||
1379 | entry->skb->data, entry->skb->len, | ||
1380 | REGISTER_TIMEOUT32(entry->skb->len)); | ||
1381 | |||
1382 | /* | ||
1383 | * Clean up the beacon skb. | ||
1384 | */ | ||
1385 | dev_kfree_skb(entry->skb); | ||
1386 | entry->skb = NULL; | ||
1387 | } | ||
1388 | |||
1346 | static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1389 | static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, |
1347 | struct sk_buff *skb) | 1390 | struct sk_buff *skb) |
1348 | { | 1391 | { |
@@ -1358,9 +1401,6 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1358 | return length; | 1401 | return length; |
1359 | } | 1402 | } |
1360 | 1403 | ||
1361 | /* | ||
1362 | * TX data initialization | ||
1363 | */ | ||
1364 | static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | 1404 | static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, |
1365 | const enum data_queue_qid queue) | 1405 | const enum data_queue_qid queue) |
1366 | { | 1406 | { |
@@ -1958,73 +1998,6 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) | |||
1958 | #define rt73usb_get_tsf NULL | 1998 | #define rt73usb_get_tsf NULL |
1959 | #endif | 1999 | #endif |
1960 | 2000 | ||
1961 | static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1962 | { | ||
1963 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
1964 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1965 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
1966 | struct skb_frame_desc *skbdesc; | ||
1967 | struct txentry_desc txdesc; | ||
1968 | unsigned int beacon_base; | ||
1969 | u32 reg; | ||
1970 | |||
1971 | if (unlikely(!intf->beacon)) | ||
1972 | return -ENOBUFS; | ||
1973 | |||
1974 | /* | ||
1975 | * Copy all TX descriptor information into txdesc, | ||
1976 | * after that we are free to use the skb->cb array | ||
1977 | * for our information. | ||
1978 | */ | ||
1979 | intf->beacon->skb = skb; | ||
1980 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); | ||
1981 | |||
1982 | /* | ||
1983 | * Add the descriptor in front of the skb. | ||
1984 | */ | ||
1985 | skb_push(skb, intf->beacon->queue->desc_size); | ||
1986 | memset(skb->data, 0, intf->beacon->queue->desc_size); | ||
1987 | |||
1988 | /* | ||
1989 | * Fill in skb descriptor | ||
1990 | */ | ||
1991 | skbdesc = get_skb_frame_desc(skb); | ||
1992 | memset(skbdesc, 0, sizeof(*skbdesc)); | ||
1993 | skbdesc->desc = skb->data; | ||
1994 | skbdesc->desc_len = intf->beacon->queue->desc_size; | ||
1995 | skbdesc->entry = intf->beacon; | ||
1996 | |||
1997 | /* | ||
1998 | * Disable beaconing while we are reloading the beacon data, | ||
1999 | * otherwise we might be sending out invalid data. | ||
2000 | */ | ||
2001 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | ||
2002 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | ||
2003 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | ||
2004 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | ||
2005 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | ||
2006 | |||
2007 | /* | ||
2008 | * Write entire beacon with descriptor to register, | ||
2009 | * and kick the beacon generator. | ||
2010 | */ | ||
2011 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
2012 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
2013 | rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, | ||
2014 | USB_VENDOR_REQUEST_OUT, beacon_base, 0, | ||
2015 | skb->data, skb->len, | ||
2016 | REGISTER_TIMEOUT32(skb->len)); | ||
2017 | rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); | ||
2018 | |||
2019 | /* | ||
2020 | * Clean up the beacon skb. | ||
2021 | */ | ||
2022 | dev_kfree_skb(skb); | ||
2023 | intf->beacon->skb = NULL; | ||
2024 | |||
2025 | return 0; | ||
2026 | } | ||
2027 | |||
2028 | static const struct ieee80211_ops rt73usb_mac80211_ops = { | 2001 | static const struct ieee80211_ops rt73usb_mac80211_ops = { |
2029 | .tx = rt2x00mac_tx, | 2002 | .tx = rt2x00mac_tx, |
2030 | .start = rt2x00mac_start, | 2003 | .start = rt2x00mac_start, |
@@ -2040,7 +2013,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { | |||
2040 | .conf_tx = rt2x00mac_conf_tx, | 2013 | .conf_tx = rt2x00mac_conf_tx, |
2041 | .get_tx_stats = rt2x00mac_get_tx_stats, | 2014 | .get_tx_stats = rt2x00mac_get_tx_stats, |
2042 | .get_tsf = rt73usb_get_tsf, | 2015 | .get_tsf = rt73usb_get_tsf, |
2043 | .beacon_update = rt73usb_beacon_update, | ||
2044 | }; | 2016 | }; |
2045 | 2017 | ||
2046 | static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | 2018 | static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { |
@@ -2058,6 +2030,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { | |||
2058 | .link_tuner = rt73usb_link_tuner, | 2030 | .link_tuner = rt73usb_link_tuner, |
2059 | .write_tx_desc = rt73usb_write_tx_desc, | 2031 | .write_tx_desc = rt73usb_write_tx_desc, |
2060 | .write_tx_data = rt2x00usb_write_tx_data, | 2032 | .write_tx_data = rt2x00usb_write_tx_data, |
2033 | .write_beacon = rt73usb_write_beacon, | ||
2061 | .get_tx_data_len = rt73usb_get_tx_data_len, | 2034 | .get_tx_data_len = rt73usb_get_tx_data_len, |
2062 | .kick_tx_queue = rt73usb_kick_tx_queue, | 2035 | .kick_tx_queue = rt73usb_kick_tx_queue, |
2063 | .fill_rxdone = rt73usb_fill_rxdone, | 2036 | .fill_rxdone = rt73usb_fill_rxdone, |
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 33527e58256f..d3067b1216ca 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -430,8 +430,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
430 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 430 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
431 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | | 431 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | |
432 | RTL818X_CONFIG3_ANAPARAM_WRITE); | 432 | RTL818X_CONFIG3_ANAPARAM_WRITE); |
433 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); | 433 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, |
434 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 434 | RTL8187_RTL8225_ANAPARAM_ON); |
435 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, | ||
436 | RTL8187_RTL8225_ANAPARAM2_ON); | ||
435 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & | 437 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & |
436 | ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 438 | ~RTL818X_CONFIG3_ANAPARAM_WRITE); |
437 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | 439 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, |
@@ -453,8 +455,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
453 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 455 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
454 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 456 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
455 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 457 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); |
456 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); | 458 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, |
457 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 459 | RTL8187_RTL8225_ANAPARAM_ON); |
460 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, | ||
461 | RTL8187_RTL8225_ANAPARAM2_ON); | ||
458 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 462 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
459 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 463 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); |
460 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 464 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
@@ -566,9 +570,12 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) | |||
566 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 570 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
567 | reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; | 571 | reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; |
568 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); | 572 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); |
569 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52); | 573 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, |
570 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658); | 574 | RTL8187B_RTL8225_ANAPARAM2_ON); |
571 | rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0); | 575 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, |
576 | RTL8187B_RTL8225_ANAPARAM_ON); | ||
577 | rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, | ||
578 | RTL8187B_RTL8225_ANAPARAM3_ON); | ||
572 | 579 | ||
573 | rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); | 580 | rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); |
574 | reg = rtl818x_ioread8(priv, (u8 *)0xFF62); | 581 | reg = rtl818x_ioread8(priv, (u8 *)0xFF62); |
@@ -1180,7 +1187,7 @@ static struct usb_driver rtl8187_driver = { | |||
1180 | .name = KBUILD_MODNAME, | 1187 | .name = KBUILD_MODNAME, |
1181 | .id_table = rtl8187_table, | 1188 | .id_table = rtl8187_table, |
1182 | .probe = rtl8187_probe, | 1189 | .probe = rtl8187_probe, |
1183 | .disconnect = rtl8187_disconnect, | 1190 | .disconnect = __devexit_p(rtl8187_disconnect), |
1184 | }; | 1191 | }; |
1185 | 1192 | ||
1186 | static int __init rtl8187_init(void) | 1193 | static int __init rtl8187_init(void) |
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index 1e059de97116..1bae89903410 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c | |||
@@ -307,7 +307,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | |||
307 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 307 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
308 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 308 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
309 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 309 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); |
310 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 310 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, |
311 | RTL8187_RTL8225_ANAPARAM2_ON); | ||
311 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 312 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
312 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 313 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); |
313 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 314 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
@@ -560,7 +561,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | |||
560 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 561 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
561 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 562 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
562 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 563 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); |
563 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 564 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, |
565 | RTL8187_RTL8225_ANAPARAM2_ON); | ||
564 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, | 566 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
565 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 567 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); |
566 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 568 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
@@ -913,8 +915,19 @@ static void rtl8225_rf_stop(struct ieee80211_hw *dev) | |||
913 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 915 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
914 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 916 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
915 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 917 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); |
916 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); | 918 | if (!priv->is_rtl8187b) { |
917 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); | 919 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, |
920 | RTL8187_RTL8225_ANAPARAM2_OFF); | ||
921 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, | ||
922 | RTL8187_RTL8225_ANAPARAM_OFF); | ||
923 | } else { | ||
924 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, | ||
925 | RTL8187B_RTL8225_ANAPARAM2_OFF); | ||
926 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, | ||
927 | RTL8187B_RTL8225_ANAPARAM_OFF); | ||
928 | rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, | ||
929 | RTL8187B_RTL8225_ANAPARAM3_OFF); | ||
930 | } | ||
918 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 931 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); |
919 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 932 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
920 | } | 933 | } |
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h index d39ed0295b6e..20c5b6ead0f6 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.h +++ b/drivers/net/wireless/rtl8187_rtl8225.h | |||
@@ -15,10 +15,17 @@ | |||
15 | #ifndef RTL8187_RTL8225_H | 15 | #ifndef RTL8187_RTL8225_H |
16 | #define RTL8187_RTL8225_H | 16 | #define RTL8187_RTL8225_H |
17 | 17 | ||
18 | #define RTL8225_ANAPARAM_ON 0xa0000a59 | 18 | #define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59 |
19 | #define RTL8225_ANAPARAM2_ON 0x860c7312 | 19 | #define RTL8187_RTL8225_ANAPARAM2_ON 0x860c7312 |
20 | #define RTL8225_ANAPARAM_OFF 0xa00beb59 | 20 | #define RTL8187_RTL8225_ANAPARAM_OFF 0xa00beb59 |
21 | #define RTL8225_ANAPARAM2_OFF 0x840dec11 | 21 | #define RTL8187_RTL8225_ANAPARAM2_OFF 0x840dec11 |
22 | |||
23 | #define RTL8187B_RTL8225_ANAPARAM_ON 0x45090658 | ||
24 | #define RTL8187B_RTL8225_ANAPARAM2_ON 0x727f3f52 | ||
25 | #define RTL8187B_RTL8225_ANAPARAM3_ON 0x00 | ||
26 | #define RTL8187B_RTL8225_ANAPARAM_OFF 0x55480658 | ||
27 | #define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50 | ||
28 | #define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00 | ||
22 | 29 | ||
23 | const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); | 30 | const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); |
24 | 31 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index feaf43d17249..fcc532bb6a7e 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -728,15 +728,19 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, | |||
728 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || | 728 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || |
729 | mac->type == IEEE80211_IF_TYPE_IBSS) { | 729 | mac->type == IEEE80211_IF_TYPE_IBSS) { |
730 | associated = true; | 730 | associated = true; |
731 | if (conf->beacon) { | 731 | if (conf->changed & IEEE80211_IFCC_BEACON) { |
732 | r = zd_mac_config_beacon(hw, conf->beacon); | 732 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
733 | |||
734 | if (!beacon) | ||
735 | return -ENOMEM; | ||
736 | r = zd_mac_config_beacon(hw, beacon); | ||
733 | if (r < 0) | 737 | if (r < 0) |
734 | return r; | 738 | return r; |
735 | r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | 739 | r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | |
736 | hw->conf.beacon_int); | 740 | hw->conf.beacon_int); |
737 | if (r < 0) | 741 | if (r < 0) |
738 | return r; | 742 | return r; |
739 | kfree_skb(conf->beacon); | 743 | kfree_skb(beacon); |
740 | } | 744 | } |
741 | } else | 745 | } else |
742 | associated = is_valid_ether_addr(conf->bssid); | 746 | associated = is_valid_ether_addr(conf->bssid); |
@@ -890,17 +894,6 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, | |||
890 | } | 894 | } |
891 | } | 895 | } |
892 | 896 | ||
893 | static int zd_op_beacon_update(struct ieee80211_hw *hw, | ||
894 | struct sk_buff *skb) | ||
895 | { | ||
896 | struct zd_mac *mac = zd_hw_mac(hw); | ||
897 | zd_mac_config_beacon(hw, skb); | ||
898 | kfree_skb(skb); | ||
899 | zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | ||
900 | hw->conf.beacon_int); | ||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static const struct ieee80211_ops zd_ops = { | 897 | static const struct ieee80211_ops zd_ops = { |
905 | .tx = zd_op_tx, | 898 | .tx = zd_op_tx, |
906 | .start = zd_op_start, | 899 | .start = zd_op_start, |
@@ -911,7 +904,6 @@ static const struct ieee80211_ops zd_ops = { | |||
911 | .config_interface = zd_op_config_interface, | 904 | .config_interface = zd_op_config_interface, |
912 | .configure_filter = zd_op_configure_filter, | 905 | .configure_filter = zd_op_configure_filter, |
913 | .bss_info_changed = zd_op_bss_info_changed, | 906 | .bss_info_changed = zd_op_bss_info_changed, |
914 | .beacon_update = zd_op_beacon_update, | ||
915 | }; | 907 | }; |
916 | 908 | ||
917 | struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | 909 | struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 0fe5a0ded3ea..4bf8cade9dbc 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/spinlock.h> | 7 | #include <linux/spinlock.h> |
8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
9 | #include <linux/mod_devicetable.h> | 9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/dma-mapping.h> | ||
10 | 11 | ||
11 | #include <linux/ssb/ssb_regs.h> | 12 | #include <linux/ssb/ssb_regs.h> |
12 | 13 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 656442c6b1c3..24a69f6075c2 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -115,17 +115,17 @@ enum ieee80211_max_queues { | |||
115 | * The information provided in this structure is required for QoS | 115 | * The information provided in this structure is required for QoS |
116 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. | 116 | * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29. |
117 | * | 117 | * |
118 | * @aifs: arbitration interface space [0..255, -1: use default] | 118 | * @aifs: arbitration interface space [0..255] |
119 | * @cw_min: minimum contention window [will be a value of the form | 119 | * @cw_min: minimum contention window [a value of the form |
120 | * 2^n-1 in the range 1..1023; 0: use default] | 120 | * 2^n-1 in the range 1..32767] |
121 | * @cw_max: maximum contention window [like @cw_min] | 121 | * @cw_max: maximum contention window [like @cw_min] |
122 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled | 122 | * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled |
123 | */ | 123 | */ |
124 | struct ieee80211_tx_queue_params { | 124 | struct ieee80211_tx_queue_params { |
125 | s16 aifs; | 125 | u16 txop; |
126 | u16 cw_min; | 126 | u16 cw_min; |
127 | u16 cw_max; | 127 | u16 cw_max; |
128 | u16 txop; | 128 | u8 aifs; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | /** | 131 | /** |
@@ -239,6 +239,17 @@ struct ieee80211_bss_conf { | |||
239 | * is for the whole aggregation. | 239 | * is for the whole aggregation. |
240 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, | 240 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, |
241 | * so consider using block ack request (BAR). | 241 | * so consider using block ack request (BAR). |
242 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence | ||
243 | * number to this frame, taking care of not overwriting the fragment | ||
244 | * number and increasing the sequence number only when the | ||
245 | * IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly | ||
246 | * assign sequence numbers to QoS-data frames but cannot do so correctly | ||
247 | * for non-QoS-data and management frames because beacons need them from | ||
248 | * that counter as well and mac80211 cannot guarantee proper sequencing. | ||
249 | * If this flag is set, the driver should instruct the hardware to | ||
250 | * assign a sequence number to the frame or assign one itself. Cf. IEEE | ||
251 | * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for | ||
252 | * beacons always be clear for frames without a sequence number field. | ||
242 | */ | 253 | */ |
243 | enum mac80211_tx_control_flags { | 254 | enum mac80211_tx_control_flags { |
244 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 255 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -265,6 +276,7 @@ enum mac80211_tx_control_flags { | |||
265 | IEEE80211_TX_STAT_ACK = BIT(21), | 276 | IEEE80211_TX_STAT_ACK = BIT(21), |
266 | IEEE80211_TX_STAT_AMPDU = BIT(22), | 277 | IEEE80211_TX_STAT_AMPDU = BIT(22), |
267 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), | 278 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), |
279 | IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(24), | ||
268 | }; | 280 | }; |
269 | 281 | ||
270 | 282 | ||
@@ -407,11 +419,13 @@ struct ieee80211_rx_status { | |||
407 | * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time | 419 | * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time |
408 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) | 420 | * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) |
409 | * @IEEE80211_CONF_SUPPORT_HT_MODE: use 802.11n HT capabilities (if supported) | 421 | * @IEEE80211_CONF_SUPPORT_HT_MODE: use 802.11n HT capabilities (if supported) |
422 | * @IEEE80211_CONF_PS: Enable 802.11 power save mode | ||
410 | */ | 423 | */ |
411 | enum ieee80211_conf_flags { | 424 | enum ieee80211_conf_flags { |
412 | IEEE80211_CONF_SHORT_SLOT_TIME = (1<<0), | 425 | IEEE80211_CONF_SHORT_SLOT_TIME = (1<<0), |
413 | IEEE80211_CONF_RADIOTAP = (1<<1), | 426 | IEEE80211_CONF_RADIOTAP = (1<<1), |
414 | IEEE80211_CONF_SUPPORT_HT_MODE = (1<<2), | 427 | IEEE80211_CONF_SUPPORT_HT_MODE = (1<<2), |
428 | IEEE80211_CONF_PS = (1<<3), | ||
415 | }; | 429 | }; |
416 | 430 | ||
417 | /** | 431 | /** |
@@ -527,33 +541,38 @@ struct ieee80211_if_init_conf { | |||
527 | }; | 541 | }; |
528 | 542 | ||
529 | /** | 543 | /** |
544 | * enum ieee80211_if_conf_change - interface config change flags | ||
545 | * | ||
546 | * @IEEE80211_IFCC_BSSID: The BSSID changed. | ||
547 | * @IEEE80211_IFCC_SSID: The SSID changed. | ||
548 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed | ||
549 | * (currently AP and MESH only), use ieee80211_beacon_get(). | ||
550 | */ | ||
551 | enum ieee80211_if_conf_change { | ||
552 | IEEE80211_IFCC_BSSID = BIT(0), | ||
553 | IEEE80211_IFCC_SSID = BIT(1), | ||
554 | IEEE80211_IFCC_BEACON = BIT(2), | ||
555 | }; | ||
556 | |||
557 | /** | ||
530 | * struct ieee80211_if_conf - configuration of an interface | 558 | * struct ieee80211_if_conf - configuration of an interface |
531 | * | 559 | * |
532 | * @type: type of the interface. This is always the same as was specified in | 560 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. |
533 | * &struct ieee80211_if_init_conf. The type of an interface never changes | ||
534 | * during the life of the interface; this field is present only for | ||
535 | * convenience. | ||
536 | * @bssid: BSSID of the network we are associated to/creating. | 561 | * @bssid: BSSID of the network we are associated to/creating. |
537 | * @ssid: used (together with @ssid_len) by drivers for hardware that | 562 | * @ssid: used (together with @ssid_len) by drivers for hardware that |
538 | * generate beacons independently. The pointer is valid only during the | 563 | * generate beacons independently. The pointer is valid only during the |
539 | * config_interface() call, so copy the value somewhere if you need | 564 | * config_interface() call, so copy the value somewhere if you need |
540 | * it. | 565 | * it. |
541 | * @ssid_len: length of the @ssid field. | 566 | * @ssid_len: length of the @ssid field. |
542 | * @beacon: beacon template. Valid only if @host_gen_beacon_template in | ||
543 | * &struct ieee80211_hw is set. The driver is responsible of freeing | ||
544 | * the sk_buff. | ||
545 | * @beacon_control: tx_control for the beacon template, this field is only | ||
546 | * valid when the @beacon field was set. | ||
547 | * | 567 | * |
548 | * This structure is passed to the config_interface() callback of | 568 | * This structure is passed to the config_interface() callback of |
549 | * &struct ieee80211_hw. | 569 | * &struct ieee80211_hw. |
550 | */ | 570 | */ |
551 | struct ieee80211_if_conf { | 571 | struct ieee80211_if_conf { |
552 | int type; | 572 | u32 changed; |
553 | u8 *bssid; | 573 | u8 *bssid; |
554 | u8 *ssid; | 574 | u8 *ssid; |
555 | size_t ssid_len; | 575 | size_t ssid_len; |
556 | struct sk_buff *beacon; | ||
557 | }; | 576 | }; |
558 | 577 | ||
559 | /** | 578 | /** |
@@ -681,15 +700,6 @@ enum ieee80211_tkip_key_type { | |||
681 | * any particular flags. There are some exceptions to this rule, | 700 | * any particular flags. There are some exceptions to this rule, |
682 | * however, so you are advised to review these flags carefully. | 701 | * however, so you are advised to review these flags carefully. |
683 | * | 702 | * |
684 | * @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE: | ||
685 | * The device only needs to be supplied with a beacon template. | ||
686 | * If you need the host to generate each beacon then don't use | ||
687 | * this flag and call ieee80211_beacon_get() when you need the | ||
688 | * next beacon frame. Note that if you set this flag, you must | ||
689 | * implement the set_tim() callback for powersave mode to work | ||
690 | * properly. | ||
691 | * This flag is only relevant for access-point mode. | ||
692 | * | ||
693 | * @IEEE80211_HW_RX_INCLUDES_FCS: | 703 | * @IEEE80211_HW_RX_INCLUDES_FCS: |
694 | * Indicates that received frames passed to the stack include | 704 | * Indicates that received frames passed to the stack include |
695 | * the FCS at the end. | 705 | * the FCS at the end. |
@@ -1149,17 +1159,6 @@ enum ieee80211_ampdu_mlme_action { | |||
1149 | * function is optional if the firmware/hardware takes full care of | 1159 | * function is optional if the firmware/hardware takes full care of |
1150 | * TSF synchronization. | 1160 | * TSF synchronization. |
1151 | * | 1161 | * |
1152 | * @beacon_update: Setup beacon data for IBSS beacons. Unlike access point, | ||
1153 | * IBSS uses a fixed beacon frame which is configured using this | ||
1154 | * function. | ||
1155 | * If the driver returns success (0) from this callback, it owns | ||
1156 | * the skb. That means the driver is responsible to kfree_skb() it. | ||
1157 | * The control structure is not dynamically allocated. That means the | ||
1158 | * driver does not own the pointer and if it needs it somewhere | ||
1159 | * outside of the context of this function, it must copy it | ||
1160 | * somewhere else. | ||
1161 | * This handler is required only for IBSS mode. | ||
1162 | * | ||
1163 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. | 1162 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. |
1164 | * This is needed only for IBSS mode and the result of this function is | 1163 | * This is needed only for IBSS mode and the result of this function is |
1165 | * used to determine whether to reply to Probe Requests. | 1164 | * used to determine whether to reply to Probe Requests. |
@@ -1217,8 +1216,6 @@ struct ieee80211_ops { | |||
1217 | struct ieee80211_tx_queue_stats *stats); | 1216 | struct ieee80211_tx_queue_stats *stats); |
1218 | u64 (*get_tsf)(struct ieee80211_hw *hw); | 1217 | u64 (*get_tsf)(struct ieee80211_hw *hw); |
1219 | void (*reset_tsf)(struct ieee80211_hw *hw); | 1218 | void (*reset_tsf)(struct ieee80211_hw *hw); |
1220 | int (*beacon_update)(struct ieee80211_hw *hw, | ||
1221 | struct sk_buff *skb); | ||
1222 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 1219 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
1223 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1220 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1224 | enum ieee80211_ampdu_mlme_action action, | 1221 | enum ieee80211_ampdu_mlme_action action, |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 3f7941319217..c1f4e0d428c0 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -318,7 +318,7 @@ static struct attribute_group netstat_group = { | |||
318 | .attrs = netstat_attrs, | 318 | .attrs = netstat_attrs, |
319 | }; | 319 | }; |
320 | 320 | ||
321 | #ifdef CONFIG_WIRELESS_EXT | 321 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
322 | /* helper function that does all the locking etc for wireless stats */ | 322 | /* helper function that does all the locking etc for wireless stats */ |
323 | static ssize_t wireless_show(struct device *d, char *buf, | 323 | static ssize_t wireless_show(struct device *d, char *buf, |
324 | ssize_t (*format)(const struct iw_statistics *, | 324 | ssize_t (*format)(const struct iw_statistics *, |
@@ -459,7 +459,7 @@ int netdev_register_kobject(struct net_device *net) | |||
459 | #ifdef CONFIG_SYSFS | 459 | #ifdef CONFIG_SYSFS |
460 | *groups++ = &netstat_group; | 460 | *groups++ = &netstat_group; |
461 | 461 | ||
462 | #ifdef CONFIG_WIRELESS_EXT | 462 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
463 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) | 463 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) |
464 | *groups++ = &wireless_group; | 464 | *groups++ = &wireless_group; |
465 | #endif | 465 | #endif |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 81087281b031..8e7ba0e62cf5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -50,14 +50,11 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
50 | struct ieee80211_sub_if_data *sdata; | 50 | struct ieee80211_sub_if_data *sdata; |
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
54 | return -ENODEV; | ||
55 | |||
56 | itype = nl80211_type_to_mac80211_type(type); | 53 | itype = nl80211_type_to_mac80211_type(type); |
57 | if (itype == IEEE80211_IF_TYPE_INVALID) | 54 | if (itype == IEEE80211_IF_TYPE_INVALID) |
58 | return -EINVAL; | 55 | return -EINVAL; |
59 | 56 | ||
60 | err = ieee80211_if_add(local->mdev, name, &dev, itype, params); | 57 | err = ieee80211_if_add(local, name, &dev, itype, params); |
61 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) | 58 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) |
62 | return err; | 59 | return err; |
63 | 60 | ||
@@ -68,54 +65,41 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
68 | 65 | ||
69 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 66 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
70 | { | 67 | { |
71 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
72 | struct net_device *dev; | 68 | struct net_device *dev; |
73 | char *name; | ||
74 | |||
75 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
76 | return -ENODEV; | ||
77 | 69 | ||
78 | /* we're under RTNL */ | 70 | /* we're under RTNL */ |
79 | dev = __dev_get_by_index(&init_net, ifindex); | 71 | dev = __dev_get_by_index(&init_net, ifindex); |
80 | if (!dev) | 72 | if (!dev) |
81 | return 0; | 73 | return -ENODEV; |
82 | 74 | ||
83 | name = dev->name; | 75 | ieee80211_if_remove(dev); |
84 | 76 | ||
85 | return ieee80211_if_remove(local->mdev, name, -1); | 77 | return 0; |
86 | } | 78 | } |
87 | 79 | ||
88 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | 80 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, |
89 | enum nl80211_iftype type, u32 *flags, | 81 | enum nl80211_iftype type, u32 *flags, |
90 | struct vif_params *params) | 82 | struct vif_params *params) |
91 | { | 83 | { |
92 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
93 | struct net_device *dev; | 84 | struct net_device *dev; |
94 | enum ieee80211_if_types itype; | 85 | enum ieee80211_if_types itype; |
95 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
96 | 87 | int ret; | |
97 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
98 | return -ENODEV; | ||
99 | 88 | ||
100 | /* we're under RTNL */ | 89 | /* we're under RTNL */ |
101 | dev = __dev_get_by_index(&init_net, ifindex); | 90 | dev = __dev_get_by_index(&init_net, ifindex); |
102 | if (!dev) | 91 | if (!dev) |
103 | return -ENODEV; | 92 | return -ENODEV; |
104 | 93 | ||
105 | if (netif_running(dev)) | ||
106 | return -EBUSY; | ||
107 | |||
108 | itype = nl80211_type_to_mac80211_type(type); | 94 | itype = nl80211_type_to_mac80211_type(type); |
109 | if (itype == IEEE80211_IF_TYPE_INVALID) | 95 | if (itype == IEEE80211_IF_TYPE_INVALID) |
110 | return -EINVAL; | 96 | return -EINVAL; |
111 | 97 | ||
112 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 98 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
113 | 99 | ||
114 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 100 | ret = ieee80211_if_change_type(sdata, itype); |
115 | return -EOPNOTSUPP; | 101 | if (ret) |
116 | 102 | return ret; | |
117 | ieee80211_if_reinit(dev); | ||
118 | ieee80211_if_set_type(dev, itype); | ||
119 | 103 | ||
120 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 104 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
121 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 105 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, |
@@ -485,7 +469,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
485 | 469 | ||
486 | kfree(old); | 470 | kfree(old); |
487 | 471 | ||
488 | return ieee80211_if_config_beacon(sdata->dev); | 472 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
489 | } | 473 | } |
490 | 474 | ||
491 | 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, |
@@ -539,7 +523,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
539 | synchronize_rcu(); | 523 | synchronize_rcu(); |
540 | kfree(old); | 524 | kfree(old); |
541 | 525 | ||
542 | return ieee80211_if_config_beacon(dev); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
543 | } | 527 | } |
544 | 528 | ||
545 | /* 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/debugfs.c b/net/mac80211/debugfs.c index d20d90eead1f..ee509f1109e2 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -70,16 +70,6 @@ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | |||
70 | 70 | ||
71 | /* statistics stuff */ | 71 | /* statistics stuff */ |
72 | 72 | ||
73 | static inline int rtnl_lock_local(struct ieee80211_local *local) | ||
74 | { | ||
75 | rtnl_lock(); | ||
76 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) { | ||
77 | rtnl_unlock(); | ||
78 | return -ENODEV; | ||
79 | } | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 73 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
84 | DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value) | 74 | DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value) |
85 | 75 | ||
@@ -96,10 +86,7 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local, | |||
96 | if (!local->ops->get_stats) | 86 | if (!local->ops->get_stats) |
97 | return -EOPNOTSUPP; | 87 | return -EOPNOTSUPP; |
98 | 88 | ||
99 | res = rtnl_lock_local(local); | 89 | rtnl_lock(); |
100 | if (res) | ||
101 | return res; | ||
102 | |||
103 | res = local->ops->get_stats(local_to_hw(local), &stats); | 90 | res = local->ops->get_stats(local_to_hw(local), &stats); |
104 | rtnl_unlock(); | 91 | rtnl_unlock(); |
105 | if (!res) | 92 | if (!res) |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index b2089b2da48a..475f89a8aee1 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -156,6 +156,8 @@ static const struct file_operations name##_ops = { \ | |||
156 | 156 | ||
157 | /* common attributes */ | 157 | /* common attributes */ |
158 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 158 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
159 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | ||
160 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | ||
159 | 161 | ||
160 | /* STA/IBSS attributes */ | 162 | /* STA/IBSS attributes */ |
161 | IEEE80211_IF_FILE(state, u.sta.state, DEC); | 163 | IEEE80211_IF_FILE(state, u.sta.state, DEC); |
@@ -191,8 +193,6 @@ __IEEE80211_IF_FILE(flags); | |||
191 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 193 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
192 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 194 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
193 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); | 195 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); |
194 | IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC); | ||
195 | IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC); | ||
196 | 196 | ||
197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( | 197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( |
198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -248,6 +248,9 @@ IEEE80211_IF_WFILE(min_discovery_timeout, | |||
248 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 248 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
249 | { | 249 | { |
250 | DEBUGFS_ADD(drop_unencrypted, sta); | 250 | DEBUGFS_ADD(drop_unencrypted, sta); |
251 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
252 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
253 | |||
251 | DEBUGFS_ADD(state, sta); | 254 | DEBUGFS_ADD(state, sta); |
252 | DEBUGFS_ADD(bssid, sta); | 255 | DEBUGFS_ADD(bssid, sta); |
253 | DEBUGFS_ADD(prev_bssid, sta); | 256 | DEBUGFS_ADD(prev_bssid, sta); |
@@ -268,23 +271,29 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
268 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 271 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
269 | { | 272 | { |
270 | DEBUGFS_ADD(drop_unencrypted, ap); | 273 | DEBUGFS_ADD(drop_unencrypted, ap); |
274 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
275 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
276 | |||
271 | DEBUGFS_ADD(num_sta_ps, ap); | 277 | DEBUGFS_ADD(num_sta_ps, ap); |
272 | DEBUGFS_ADD(dtim_count, ap); | 278 | DEBUGFS_ADD(dtim_count, ap); |
273 | DEBUGFS_ADD(num_beacons, ap); | 279 | DEBUGFS_ADD(num_beacons, ap); |
274 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
275 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
276 | DEBUGFS_ADD(num_buffered_multicast, ap); | 280 | DEBUGFS_ADD(num_buffered_multicast, ap); |
277 | } | 281 | } |
278 | 282 | ||
279 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 283 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
280 | { | 284 | { |
281 | DEBUGFS_ADD(drop_unencrypted, wds); | 285 | DEBUGFS_ADD(drop_unencrypted, wds); |
286 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
287 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
288 | |||
282 | DEBUGFS_ADD(peer, wds); | 289 | DEBUGFS_ADD(peer, wds); |
283 | } | 290 | } |
284 | 291 | ||
285 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 292 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
286 | { | 293 | { |
287 | DEBUGFS_ADD(drop_unencrypted, vlan); | 294 | DEBUGFS_ADD(drop_unencrypted, vlan); |
295 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
296 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
288 | } | 297 | } |
289 | 298 | ||
290 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 299 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -372,6 +381,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
372 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) | 381 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) |
373 | { | 382 | { |
374 | DEBUGFS_DEL(drop_unencrypted, sta); | 383 | DEBUGFS_DEL(drop_unencrypted, sta); |
384 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
385 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
386 | |||
375 | DEBUGFS_DEL(state, sta); | 387 | DEBUGFS_DEL(state, sta); |
376 | DEBUGFS_DEL(bssid, sta); | 388 | DEBUGFS_DEL(bssid, sta); |
377 | DEBUGFS_DEL(prev_bssid, sta); | 389 | DEBUGFS_DEL(prev_bssid, sta); |
@@ -392,23 +404,29 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
392 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | 404 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) |
393 | { | 405 | { |
394 | DEBUGFS_DEL(drop_unencrypted, ap); | 406 | DEBUGFS_DEL(drop_unencrypted, ap); |
407 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
408 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
409 | |||
395 | DEBUGFS_DEL(num_sta_ps, ap); | 410 | DEBUGFS_DEL(num_sta_ps, ap); |
396 | DEBUGFS_DEL(dtim_count, ap); | 411 | DEBUGFS_DEL(dtim_count, ap); |
397 | DEBUGFS_DEL(num_beacons, ap); | 412 | DEBUGFS_DEL(num_beacons, ap); |
398 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
399 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
400 | DEBUGFS_DEL(num_buffered_multicast, ap); | 413 | DEBUGFS_DEL(num_buffered_multicast, ap); |
401 | } | 414 | } |
402 | 415 | ||
403 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) | 416 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) |
404 | { | 417 | { |
405 | DEBUGFS_DEL(drop_unencrypted, wds); | 418 | DEBUGFS_DEL(drop_unencrypted, wds); |
419 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
420 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
421 | |||
406 | DEBUGFS_DEL(peer, wds); | 422 | DEBUGFS_DEL(peer, wds); |
407 | } | 423 | } |
408 | 424 | ||
409 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | 425 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) |
410 | { | 426 | { |
411 | DEBUGFS_DEL(drop_unencrypted, vlan); | 427 | DEBUGFS_DEL(drop_unencrypted, vlan); |
428 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
429 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
412 | } | 430 | } |
413 | 431 | ||
414 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | 432 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -458,12 +476,12 @@ static void del_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
458 | } | 476 | } |
459 | #endif | 477 | #endif |
460 | 478 | ||
461 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) | 479 | static void del_files(struct ieee80211_sub_if_data *sdata) |
462 | { | 480 | { |
463 | if (!sdata->debugfsdir) | 481 | if (!sdata->debugfsdir) |
464 | return; | 482 | return; |
465 | 483 | ||
466 | switch (type) { | 484 | switch (sdata->vif.type) { |
467 | case IEEE80211_IF_TYPE_MESH_POINT: | 485 | case IEEE80211_IF_TYPE_MESH_POINT: |
468 | #ifdef CONFIG_MAC80211_MESH | 486 | #ifdef CONFIG_MAC80211_MESH |
469 | del_mesh_stats(sdata); | 487 | del_mesh_stats(sdata); |
@@ -503,29 +521,23 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | |||
503 | sprintf(buf, "netdev:%s", sdata->dev->name); | 521 | sprintf(buf, "netdev:%s", sdata->dev->name); |
504 | sdata->debugfsdir = debugfs_create_dir(buf, | 522 | sdata->debugfsdir = debugfs_create_dir(buf, |
505 | sdata->local->hw.wiphy->debugfsdir); | 523 | sdata->local->hw.wiphy->debugfsdir); |
524 | add_files(sdata); | ||
506 | } | 525 | } |
507 | 526 | ||
508 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | 527 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) |
509 | { | 528 | { |
510 | del_files(sdata, sdata->vif.type); | 529 | del_files(sdata); |
511 | debugfs_remove(sdata->debugfsdir); | 530 | debugfs_remove(sdata->debugfsdir); |
512 | sdata->debugfsdir = NULL; | 531 | sdata->debugfsdir = NULL; |
513 | } | 532 | } |
514 | 533 | ||
515 | void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata, | ||
516 | int oldtype) | ||
517 | { | ||
518 | del_files(sdata, oldtype); | ||
519 | add_files(sdata); | ||
520 | } | ||
521 | |||
522 | static int netdev_notify(struct notifier_block *nb, | 534 | static int netdev_notify(struct notifier_block *nb, |
523 | unsigned long state, | 535 | unsigned long state, |
524 | void *ndev) | 536 | void *ndev) |
525 | { | 537 | { |
526 | struct net_device *dev = ndev; | 538 | struct net_device *dev = ndev; |
527 | struct dentry *dir; | 539 | struct dentry *dir; |
528 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 540 | struct ieee80211_sub_if_data *sdata; |
529 | char buf[10+IFNAMSIZ]; | 541 | char buf[10+IFNAMSIZ]; |
530 | 542 | ||
531 | if (state != NETDEV_CHANGENAME) | 543 | if (state != NETDEV_CHANGENAME) |
@@ -537,6 +549,8 @@ static int netdev_notify(struct notifier_block *nb, | |||
537 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | 549 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) |
538 | return 0; | 550 | return 0; |
539 | 551 | ||
552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
553 | |||
540 | sprintf(buf, "netdev:%s", dev->name); | 554 | sprintf(buf, "netdev:%s", dev->name); |
541 | dir = sdata->debugfsdir; | 555 | dir = sdata->debugfsdir; |
542 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 556 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h index a690071fde8a..7af731f0b731 100644 --- a/net/mac80211/debugfs_netdev.h +++ b/net/mac80211/debugfs_netdev.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #ifdef CONFIG_MAC80211_DEBUGFS | 6 | #ifdef CONFIG_MAC80211_DEBUGFS |
7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); | 8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); |
9 | void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata, | ||
10 | int oldtype); | ||
11 | void ieee80211_debugfs_netdev_init(void); | 9 | void ieee80211_debugfs_netdev_init(void); |
12 | void ieee80211_debugfs_netdev_exit(void); | 10 | void ieee80211_debugfs_netdev_exit(void); |
13 | #else | 11 | #else |
@@ -17,9 +15,6 @@ static inline void ieee80211_debugfs_add_netdev( | |||
17 | static inline void ieee80211_debugfs_remove_netdev( | 15 | static inline void ieee80211_debugfs_remove_netdev( |
18 | struct ieee80211_sub_if_data *sdata) | 16 | struct ieee80211_sub_if_data *sdata) |
19 | {} | 17 | {} |
20 | static inline void ieee80211_debugfs_change_if_type( | ||
21 | struct ieee80211_sub_if_data *sdata, int oldtype) | ||
22 | {} | ||
23 | static inline void ieee80211_debugfs_netdev_init(void) | 18 | static inline void ieee80211_debugfs_netdev_init(void) |
24 | {} | 19 | {} |
25 | 20 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 02a8753a4eca..cbea0154ee3a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -237,8 +237,6 @@ struct ieee80211_if_ap { | |||
237 | struct sk_buff_head ps_bc_buf; | 237 | struct sk_buff_head ps_bc_buf; |
238 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 238 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
239 | int dtim_count; | 239 | int dtim_count; |
240 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | ||
241 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | ||
242 | int num_beacons; /* number of TXed beacon frames for this BSS */ | 240 | int num_beacons; /* number of TXed beacon frames for this BSS */ |
243 | }; | 241 | }; |
244 | 242 | ||
@@ -248,7 +246,6 @@ struct ieee80211_if_wds { | |||
248 | }; | 246 | }; |
249 | 247 | ||
250 | struct ieee80211_if_vlan { | 248 | struct ieee80211_if_vlan { |
251 | struct ieee80211_sub_if_data *ap; | ||
252 | struct list_head list; | 249 | struct list_head list; |
253 | }; | 250 | }; |
254 | 251 | ||
@@ -422,8 +419,6 @@ struct ieee80211_sub_if_data { | |||
422 | */ | 419 | */ |
423 | u64 basic_rates; | 420 | u64 basic_rates; |
424 | 421 | ||
425 | u16 sequence; | ||
426 | |||
427 | /* Fragment table for host-based reassembly */ | 422 | /* Fragment table for host-based reassembly */ |
428 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 423 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
429 | unsigned int fragment_next; | 424 | unsigned int fragment_next; |
@@ -432,16 +427,18 @@ struct ieee80211_sub_if_data { | |||
432 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; | 427 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; |
433 | struct ieee80211_key *default_key; | 428 | struct ieee80211_key *default_key; |
434 | 429 | ||
430 | /* BSS configuration for this interface. */ | ||
431 | struct ieee80211_bss_conf bss_conf; | ||
432 | |||
435 | /* | 433 | /* |
436 | * BSS configuration for this interface. | 434 | * AP this belongs to: self in AP mode and |
437 | * | 435 | * corresponding AP in VLAN mode, NULL for |
438 | * FIXME: I feel bad putting this here when we already have a | 436 | * all others (might be needed later in IBSS) |
439 | * bss pointer, but the bss pointer is just wrong when | ||
440 | * you have multiple virtual STA mode interfaces... | ||
441 | * This needs to be fixed. | ||
442 | */ | 437 | */ |
443 | struct ieee80211_bss_conf bss_conf; | 438 | struct ieee80211_if_ap *bss; |
444 | struct ieee80211_if_ap *bss; /* BSS that this device belongs to */ | 439 | |
440 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | ||
441 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | ||
445 | 442 | ||
446 | union { | 443 | union { |
447 | struct ieee80211_if_ap ap; | 444 | struct ieee80211_if_ap ap; |
@@ -533,8 +530,6 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
533 | return container_of(p, struct ieee80211_sub_if_data, vif); | 530 | return container_of(p, struct ieee80211_sub_if_data, vif); |
534 | } | 531 | } |
535 | 532 | ||
536 | #define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev) | ||
537 | |||
538 | enum { | 533 | enum { |
539 | IEEE80211_RX_MSG = 1, | 534 | IEEE80211_RX_MSG = 1, |
540 | IEEE80211_TX_STATUS_MSG = 2, | 535 | IEEE80211_TX_STATUS_MSG = 2, |
@@ -561,12 +556,6 @@ struct ieee80211_local { | |||
561 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 556 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
562 | int tx_headroom; /* required headroom for hardware/radiotap */ | 557 | int tx_headroom; /* required headroom for hardware/radiotap */ |
563 | 558 | ||
564 | enum { | ||
565 | IEEE80211_DEV_UNINITIALIZED = 0, | ||
566 | IEEE80211_DEV_REGISTERED, | ||
567 | IEEE80211_DEV_UNREGISTERED, | ||
568 | } reg_state; | ||
569 | |||
570 | /* Tasklet and skb queue to process calls from IRQ mode. All frames | 559 | /* Tasklet and skb queue to process calls from IRQ mode. All frames |
571 | * added to skb_queue will be processed, but frames in | 560 | * added to skb_queue will be processed, but frames in |
572 | * skb_queue_unreliable may be dropped if the total length of these | 561 | * skb_queue_unreliable may be dropped if the total length of these |
@@ -760,6 +749,16 @@ static inline int ieee80211_is_multiqueue(struct ieee80211_local *local) | |||
760 | #endif | 749 | #endif |
761 | } | 750 | } |
762 | 751 | ||
752 | static inline struct ieee80211_sub_if_data * | ||
753 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | ||
754 | { | ||
755 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
756 | |||
757 | BUG_ON(!local || local->mdev == dev); | ||
758 | |||
759 | return netdev_priv(dev); | ||
760 | } | ||
761 | |||
763 | /* this struct represents 802.11n's RA/TID combination */ | 762 | /* this struct represents 802.11n's RA/TID combination */ |
764 | struct ieee80211_ra_tid { | 763 | struct ieee80211_ra_tid { |
765 | u8 ra[ETH_ALEN]; | 764 | u8 ra[ETH_ALEN]; |
@@ -853,10 +852,8 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
853 | 852 | ||
854 | /* ieee80211.c */ | 853 | /* ieee80211.c */ |
855 | int ieee80211_hw_config(struct ieee80211_local *local); | 854 | int ieee80211_hw_config(struct ieee80211_local *local); |
856 | int ieee80211_if_config(struct net_device *dev); | 855 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
857 | int ieee80211_if_config_beacon(struct net_device *dev); | ||
858 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 856 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
859 | void ieee80211_if_setup(struct net_device *dev); | ||
860 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | 857 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, |
861 | struct ieee80211_ht_info *req_ht_cap, | 858 | struct ieee80211_ht_info *req_ht_cap, |
862 | struct ieee80211_ht_bss_info *req_bss_cap); | 859 | struct ieee80211_ht_bss_info *req_bss_cap); |
@@ -883,8 +880,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, | |||
883 | ieee80211_rx_result ieee80211_sta_rx_scan( | 880 | ieee80211_rx_result ieee80211_sta_rx_scan( |
884 | struct net_device *dev, struct sk_buff *skb, | 881 | struct net_device *dev, struct sk_buff *skb, |
885 | struct ieee80211_rx_status *rx_status); | 882 | struct ieee80211_rx_status *rx_status); |
886 | void ieee80211_rx_bss_list_init(struct net_device *dev); | 883 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); |
887 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); | 884 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); |
888 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); | 885 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); |
889 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | 886 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, |
890 | struct sk_buff *skb, u8 *bssid, | 887 | struct sk_buff *skb, u8 *bssid, |
@@ -925,17 +922,15 @@ static inline void ieee80211_start_mesh(struct net_device *dev) | |||
925 | {} | 922 | {} |
926 | #endif | 923 | #endif |
927 | 924 | ||
928 | /* ieee80211_iface.c */ | 925 | /* interface handling */ |
929 | int ieee80211_if_add(struct net_device *dev, const char *name, | 926 | void ieee80211_if_setup(struct net_device *dev); |
930 | struct net_device **new_dev, int type, | 927 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
928 | struct net_device **new_dev, enum ieee80211_if_types type, | ||
931 | struct vif_params *params); | 929 | struct vif_params *params); |
932 | void ieee80211_if_set_type(struct net_device *dev, int type); | 930 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
933 | void ieee80211_if_reinit(struct net_device *dev); | 931 | enum ieee80211_if_types type); |
934 | void __ieee80211_if_del(struct ieee80211_local *local, | 932 | void ieee80211_if_remove(struct net_device *dev); |
935 | struct ieee80211_sub_if_data *sdata); | 933 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
936 | int ieee80211_if_remove(struct net_device *dev, const char *name, int id); | ||
937 | void ieee80211_if_free(struct net_device *dev); | ||
938 | void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata); | ||
939 | 934 | ||
940 | /* tx handling */ | 935 | /* tx handling */ |
941 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 936 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index eeb16926aa7d..610ed1d9893a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -17,145 +18,91 @@ | |||
17 | #include "debugfs_netdev.h" | 18 | #include "debugfs_netdev.h" |
18 | #include "mesh.h" | 19 | #include "mesh.h" |
19 | 20 | ||
20 | void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) | 21 | /* |
22 | * Called when the netdev is removed or, by the code below, before | ||
23 | * the interface type changes. | ||
24 | */ | ||
25 | static void ieee80211_teardown_sdata(struct net_device *dev) | ||
21 | { | 26 | { |
27 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
28 | struct ieee80211_local *local = sdata->local; | ||
29 | struct beacon_data *beacon; | ||
30 | struct sk_buff *skb; | ||
31 | int flushed; | ||
22 | int i; | 32 | int i; |
23 | 33 | ||
24 | /* Default values for sub-interface parameters */ | 34 | ieee80211_debugfs_remove_netdev(sdata); |
25 | sdata->drop_unencrypted = 0; | ||
26 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | ||
27 | skb_queue_head_init(&sdata->fragments[i].skb_list); | ||
28 | |||
29 | INIT_LIST_HEAD(&sdata->key_list); | ||
30 | } | ||
31 | 35 | ||
32 | static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | 36 | /* free extra data */ |
33 | { | 37 | ieee80211_free_keys(sdata); |
34 | int i; | ||
35 | 38 | ||
36 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 39 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
37 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 40 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
38 | } | 41 | sdata->fragment_next = 0; |
39 | |||
40 | /* Must be called with rtnl lock held. */ | ||
41 | int ieee80211_if_add(struct net_device *dev, const char *name, | ||
42 | struct net_device **new_dev, int type, | ||
43 | struct vif_params *params) | ||
44 | { | ||
45 | struct net_device *ndev; | ||
46 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
47 | struct ieee80211_sub_if_data *sdata = NULL; | ||
48 | int ret; | ||
49 | |||
50 | ASSERT_RTNL(); | ||
51 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, | ||
52 | name, ieee80211_if_setup); | ||
53 | if (!ndev) | ||
54 | return -ENOMEM; | ||
55 | 42 | ||
56 | ndev->needed_headroom = local->tx_headroom + | 43 | switch (sdata->vif.type) { |
57 | 4*6 /* four MAC addresses */ | 44 | case IEEE80211_IF_TYPE_AP: |
58 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 45 | beacon = sdata->u.ap.beacon; |
59 | + 6 /* mesh */ | 46 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
60 | + 8 /* rfc1042/bridge tunnel */ | 47 | synchronize_rcu(); |
61 | - ETH_HLEN /* ethernet hard_header_len */ | 48 | kfree(beacon); |
62 | + IEEE80211_ENCRYPT_HEADROOM; | ||
63 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
64 | |||
65 | ret = dev_alloc_name(ndev, ndev->name); | ||
66 | if (ret < 0) | ||
67 | goto fail; | ||
68 | |||
69 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
70 | ndev->base_addr = dev->base_addr; | ||
71 | ndev->irq = dev->irq; | ||
72 | ndev->mem_start = dev->mem_start; | ||
73 | ndev->mem_end = dev->mem_end; | ||
74 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | ||
75 | |||
76 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | ||
77 | ndev->ieee80211_ptr = &sdata->wdev; | ||
78 | sdata->wdev.wiphy = local->hw.wiphy; | ||
79 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
80 | sdata->dev = ndev; | ||
81 | sdata->local = local; | ||
82 | ieee80211_if_sdata_init(sdata); | ||
83 | |||
84 | ret = register_netdevice(ndev); | ||
85 | if (ret) | ||
86 | goto fail; | ||
87 | |||
88 | ieee80211_debugfs_add_netdev(sdata); | ||
89 | ieee80211_if_set_type(ndev, type); | ||
90 | 49 | ||
91 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 50 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { |
92 | params && params->mesh_id_len) | 51 | local->total_ps_buffered--; |
93 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 52 | dev_kfree_skb(skb); |
94 | params->mesh_id_len, | 53 | } |
95 | params->mesh_id); | ||
96 | 54 | ||
97 | /* we're under RTNL so all this is fine */ | 55 | break; |
98 | if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) { | 56 | case IEEE80211_IF_TYPE_MESH_POINT: |
99 | __ieee80211_if_del(local, sdata); | 57 | /* Allow compiler to elide mesh_rmc_free call. */ |
100 | return -ENODEV; | 58 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
59 | mesh_rmc_free(dev); | ||
60 | /* fall through */ | ||
61 | case IEEE80211_IF_TYPE_STA: | ||
62 | case IEEE80211_IF_TYPE_IBSS: | ||
63 | kfree(sdata->u.sta.extra_ie); | ||
64 | kfree(sdata->u.sta.assocreq_ies); | ||
65 | kfree(sdata->u.sta.assocresp_ies); | ||
66 | kfree_skb(sdata->u.sta.probe_resp); | ||
67 | break; | ||
68 | case IEEE80211_IF_TYPE_WDS: | ||
69 | case IEEE80211_IF_TYPE_VLAN: | ||
70 | case IEEE80211_IF_TYPE_MNTR: | ||
71 | break; | ||
72 | case IEEE80211_IF_TYPE_INVALID: | ||
73 | BUG(); | ||
74 | break; | ||
101 | } | 75 | } |
102 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
103 | 76 | ||
104 | if (new_dev) | 77 | flushed = sta_info_flush(local, sdata); |
105 | *new_dev = ndev; | 78 | WARN_ON(flushed); |
106 | |||
107 | return 0; | ||
108 | |||
109 | fail: | ||
110 | free_netdev(ndev); | ||
111 | return ret; | ||
112 | } | 79 | } |
113 | 80 | ||
114 | void ieee80211_if_set_type(struct net_device *dev, int type) | 81 | /* |
82 | * Helper function to initialise an interface to a specific type. | ||
83 | */ | ||
84 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | ||
85 | enum ieee80211_if_types type) | ||
115 | { | 86 | { |
116 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 87 | struct ieee80211_if_sta *ifsta; |
117 | int oldtype = sdata->vif.type; | ||
118 | |||
119 | /* | ||
120 | * We need to call this function on the master interface | ||
121 | * which already has a hard_start_xmit routine assigned | ||
122 | * which must not be changed. | ||
123 | */ | ||
124 | if (dev != sdata->local->mdev) | ||
125 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
126 | 88 | ||
127 | /* | 89 | /* clear type-dependent union */ |
128 | * Called even when register_netdevice fails, it would | 90 | memset(&sdata->u, 0, sizeof(sdata->u)); |
129 | * oops if assigned before initialising the rest. | ||
130 | */ | ||
131 | dev->uninit = ieee80211_if_reinit; | ||
132 | 91 | ||
133 | /* most have no BSS pointer */ | 92 | /* and set some type-dependent values */ |
134 | sdata->bss = NULL; | ||
135 | sdata->vif.type = type; | 93 | sdata->vif.type = type; |
136 | 94 | ||
137 | sdata->basic_rates = 0; | 95 | /* only monitor differs */ |
96 | sdata->dev->type = ARPHRD_ETHER; | ||
138 | 97 | ||
139 | switch (type) { | 98 | switch (type) { |
140 | case IEEE80211_IF_TYPE_WDS: | ||
141 | /* nothing special */ | ||
142 | break; | ||
143 | case IEEE80211_IF_TYPE_VLAN: | ||
144 | sdata->u.vlan.ap = NULL; | ||
145 | break; | ||
146 | case IEEE80211_IF_TYPE_AP: | 99 | case IEEE80211_IF_TYPE_AP: |
147 | sdata->u.ap.force_unicast_rateidx = -1; | ||
148 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
149 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 100 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
150 | sdata->bss = &sdata->u.ap; | ||
151 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 101 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
152 | break; | 102 | break; |
153 | case IEEE80211_IF_TYPE_MESH_POINT: | 103 | case IEEE80211_IF_TYPE_MESH_POINT: |
154 | case IEEE80211_IF_TYPE_STA: | 104 | case IEEE80211_IF_TYPE_STA: |
155 | case IEEE80211_IF_TYPE_IBSS: { | 105 | case IEEE80211_IF_TYPE_IBSS: |
156 | struct ieee80211_sub_if_data *msdata; | ||
157 | struct ieee80211_if_sta *ifsta; | ||
158 | |||
159 | ifsta = &sdata->u.sta; | 106 | ifsta = &sdata->u.sta; |
160 | INIT_WORK(&ifsta->work, ieee80211_sta_work); | 107 | INIT_WORK(&ifsta->work, ieee80211_sta_work); |
161 | setup_timer(&ifsta->timer, ieee80211_sta_timer, | 108 | setup_timer(&ifsta->timer, ieee80211_sta_timer, |
@@ -171,153 +118,152 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | 118 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 119 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
173 | 120 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | ||
175 | sdata->bss = &msdata->u.ap; | ||
176 | |||
177 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 121 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
178 | ieee80211_mesh_init_sdata(sdata); | 122 | ieee80211_mesh_init_sdata(sdata); |
179 | break; | 123 | break; |
180 | } | ||
181 | case IEEE80211_IF_TYPE_MNTR: | 124 | case IEEE80211_IF_TYPE_MNTR: |
182 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | 125 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
183 | dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 126 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; |
184 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 127 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
185 | MONITOR_FLAG_OTHER_BSS; | 128 | MONITOR_FLAG_OTHER_BSS; |
186 | break; | 129 | break; |
130 | case IEEE80211_IF_TYPE_WDS: | ||
131 | case IEEE80211_IF_TYPE_VLAN: | ||
132 | break; | ||
187 | case IEEE80211_IF_TYPE_INVALID: | 133 | case IEEE80211_IF_TYPE_INVALID: |
188 | BUG(); | 134 | BUG(); |
189 | break; | 135 | break; |
190 | } | 136 | } |
191 | ieee80211_debugfs_change_if_type(sdata, oldtype); | 137 | |
138 | ieee80211_debugfs_add_netdev(sdata); | ||
192 | } | 139 | } |
193 | 140 | ||
194 | /* Must be called with rtnl lock held. */ | 141 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
195 | void ieee80211_if_reinit(struct net_device *dev) | 142 | enum ieee80211_if_types type) |
196 | { | 143 | { |
197 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 144 | ASSERT_RTNL(); |
198 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 145 | |
199 | struct sk_buff *skb; | 146 | if (type == sdata->vif.type) |
200 | int flushed; | 147 | return 0; |
148 | |||
149 | /* | ||
150 | * We could, here, on changes between IBSS/STA/MESH modes, | ||
151 | * invoke an MLME function instead that disassociates etc. | ||
152 | * and goes into the requested mode. | ||
153 | */ | ||
154 | |||
155 | if (netif_running(sdata->dev)) | ||
156 | return -EBUSY; | ||
157 | |||
158 | /* Purge and reset type-dependent state. */ | ||
159 | ieee80211_teardown_sdata(sdata->dev); | ||
160 | ieee80211_setup_sdata(sdata, type); | ||
161 | |||
162 | /* reset some values that shouldn't be kept across type changes */ | ||
163 | sdata->basic_rates = 0; | ||
164 | sdata->drop_unencrypted = 0; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | ||
170 | struct net_device **new_dev, enum ieee80211_if_types type, | ||
171 | struct vif_params *params) | ||
172 | { | ||
173 | struct net_device *ndev; | ||
174 | struct ieee80211_sub_if_data *sdata = NULL; | ||
175 | int ret, i; | ||
201 | 176 | ||
202 | ASSERT_RTNL(); | 177 | ASSERT_RTNL(); |
203 | 178 | ||
204 | ieee80211_free_keys(sdata); | 179 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, |
180 | name, ieee80211_if_setup); | ||
181 | if (!ndev) | ||
182 | return -ENOMEM; | ||
205 | 183 | ||
206 | ieee80211_if_sdata_deinit(sdata); | 184 | ndev->needed_headroom = local->tx_headroom + |
185 | 4*6 /* four MAC addresses */ | ||
186 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | ||
187 | + 6 /* mesh */ | ||
188 | + 8 /* rfc1042/bridge tunnel */ | ||
189 | - ETH_HLEN /* ethernet hard_header_len */ | ||
190 | + IEEE80211_ENCRYPT_HEADROOM; | ||
191 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
207 | 192 | ||
208 | /* Need to handle mesh specially to allow eliding the function call */ | 193 | ret = dev_alloc_name(ndev, ndev->name); |
209 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 194 | if (ret < 0) |
210 | mesh_rmc_free(dev); | 195 | goto fail; |
211 | 196 | ||
212 | switch (sdata->vif.type) { | 197 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
213 | case IEEE80211_IF_TYPE_INVALID: | 198 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
214 | /* cannot happen */ | ||
215 | WARN_ON(1); | ||
216 | break; | ||
217 | case IEEE80211_IF_TYPE_AP: { | ||
218 | /* Remove all virtual interfaces that use this BSS | ||
219 | * as their sdata->bss */ | ||
220 | struct ieee80211_sub_if_data *tsdata, *n; | ||
221 | struct beacon_data *beacon; | ||
222 | |||
223 | list_for_each_entry_safe(tsdata, n, &local->interfaces, list) { | ||
224 | if (tsdata != sdata && tsdata->bss == &sdata->u.ap) { | ||
225 | printk(KERN_DEBUG "%s: removing virtual " | ||
226 | "interface %s because its BSS interface" | ||
227 | " is being removed\n", | ||
228 | sdata->dev->name, tsdata->dev->name); | ||
229 | list_del_rcu(&tsdata->list); | ||
230 | /* | ||
231 | * We have lots of time and can afford | ||
232 | * to sync for each interface | ||
233 | */ | ||
234 | synchronize_rcu(); | ||
235 | __ieee80211_if_del(local, tsdata); | ||
236 | } | ||
237 | } | ||
238 | 199 | ||
239 | beacon = sdata->u.ap.beacon; | 200 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
240 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 201 | sdata = netdev_priv(ndev); |
241 | synchronize_rcu(); | 202 | ndev->ieee80211_ptr = &sdata->wdev; |
242 | kfree(beacon); | ||
243 | 203 | ||
244 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | 204 | /* initialise type-independent data */ |
245 | local->total_ps_buffered--; | 205 | sdata->wdev.wiphy = local->hw.wiphy; |
246 | dev_kfree_skb(skb); | 206 | sdata->local = local; |
247 | } | 207 | sdata->dev = ndev; |
248 | 208 | ||
249 | break; | 209 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
250 | } | 210 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
251 | case IEEE80211_IF_TYPE_WDS: | ||
252 | /* nothing to do */ | ||
253 | break; | ||
254 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
255 | case IEEE80211_IF_TYPE_STA: | ||
256 | case IEEE80211_IF_TYPE_IBSS: | ||
257 | kfree(sdata->u.sta.extra_ie); | ||
258 | sdata->u.sta.extra_ie = NULL; | ||
259 | kfree(sdata->u.sta.assocreq_ies); | ||
260 | sdata->u.sta.assocreq_ies = NULL; | ||
261 | kfree(sdata->u.sta.assocresp_ies); | ||
262 | sdata->u.sta.assocresp_ies = NULL; | ||
263 | if (sdata->u.sta.probe_resp) { | ||
264 | dev_kfree_skb(sdata->u.sta.probe_resp); | ||
265 | sdata->u.sta.probe_resp = NULL; | ||
266 | } | ||
267 | 211 | ||
268 | break; | 212 | INIT_LIST_HEAD(&sdata->key_list); |
269 | case IEEE80211_IF_TYPE_MNTR: | ||
270 | dev->type = ARPHRD_ETHER; | ||
271 | break; | ||
272 | case IEEE80211_IF_TYPE_VLAN: | ||
273 | sdata->u.vlan.ap = NULL; | ||
274 | break; | ||
275 | } | ||
276 | 213 | ||
277 | flushed = sta_info_flush(local, sdata); | 214 | sdata->force_unicast_rateidx = -1; |
278 | WARN_ON(flushed); | 215 | sdata->max_ratectrl_rateidx = -1; |
279 | 216 | ||
280 | memset(&sdata->u, 0, sizeof(sdata->u)); | 217 | /* setup type-dependent data */ |
281 | ieee80211_if_sdata_init(sdata); | 218 | ieee80211_setup_sdata(sdata, type); |
282 | } | ||
283 | 219 | ||
284 | /* Must be called with rtnl lock held. */ | 220 | ret = register_netdevice(ndev); |
285 | void __ieee80211_if_del(struct ieee80211_local *local, | 221 | if (ret) |
286 | struct ieee80211_sub_if_data *sdata) | 222 | goto fail; |
287 | { | ||
288 | struct net_device *dev = sdata->dev; | ||
289 | 223 | ||
290 | ieee80211_debugfs_remove_netdev(sdata); | 224 | ndev->uninit = ieee80211_teardown_sdata; |
291 | unregister_netdevice(dev); | 225 | |
292 | /* Except master interface, the net_device will be freed by | 226 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
293 | * net_device->destructor (i. e. ieee80211_if_free). */ | 227 | params && params->mesh_id_len) |
228 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | ||
229 | params->mesh_id_len, | ||
230 | params->mesh_id); | ||
231 | |||
232 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
233 | |||
234 | if (new_dev) | ||
235 | *new_dev = ndev; | ||
236 | |||
237 | return 0; | ||
238 | |||
239 | fail: | ||
240 | free_netdev(ndev); | ||
241 | return ret; | ||
294 | } | 242 | } |
295 | 243 | ||
296 | /* Must be called with rtnl lock held. */ | 244 | void ieee80211_if_remove(struct net_device *dev) |
297 | int ieee80211_if_remove(struct net_device *dev, const char *name, int id) | ||
298 | { | 245 | { |
299 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
300 | struct ieee80211_sub_if_data *sdata, *n; | ||
301 | 247 | ||
302 | ASSERT_RTNL(); | 248 | ASSERT_RTNL(); |
303 | 249 | ||
304 | list_for_each_entry_safe(sdata, n, &local->interfaces, list) { | 250 | list_del_rcu(&sdata->list); |
305 | if ((sdata->vif.type == id || id == -1) && | 251 | synchronize_rcu(); |
306 | strcmp(name, sdata->dev->name) == 0 && | 252 | unregister_netdevice(dev); |
307 | sdata->dev != local->mdev) { | ||
308 | list_del_rcu(&sdata->list); | ||
309 | synchronize_rcu(); | ||
310 | __ieee80211_if_del(local, sdata); | ||
311 | return 0; | ||
312 | } | ||
313 | } | ||
314 | return -ENODEV; | ||
315 | } | 253 | } |
316 | 254 | ||
317 | void ieee80211_if_free(struct net_device *dev) | 255 | /* |
256 | * Remove all interfaces, may only be called at hardware unregistration | ||
257 | * time because it doesn't do RCU-safe list removals. | ||
258 | */ | ||
259 | void ieee80211_remove_interfaces(struct ieee80211_local *local) | ||
318 | { | 260 | { |
319 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 261 | struct ieee80211_sub_if_data *sdata, *tmp; |
320 | 262 | ||
321 | ieee80211_if_sdata_deinit(sdata); | 263 | ASSERT_RTNL(); |
322 | free_netdev(dev); | 264 | |
265 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | ||
266 | list_del(&sdata->list); | ||
267 | unregister_netdevice(sdata->dev); | ||
268 | } | ||
323 | } | 269 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1c4d3ba6b878..36859e794928 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct net_device *dev) | |||
105 | 105 | ||
106 | /* we hold the RTNL here so can safely walk the list */ | 106 | /* we hold the RTNL here so can safely walk the list */ |
107 | list_for_each_entry(sdata, &local->interfaces, list) { | 107 | list_for_each_entry(sdata, &local->interfaces, list) { |
108 | if (sdata->dev != dev && netif_running(sdata->dev)) { | 108 | if (netif_running(sdata->dev)) { |
109 | res = 0; | 109 | res = 0; |
110 | break; | 110 | break; |
111 | } | 111 | } |
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
126 | 126 | ||
127 | /* we hold the RTNL here so can safely walk the list */ | 127 | /* we hold the RTNL here so can safely walk the list */ |
128 | list_for_each_entry(sdata, &local->interfaces, list) | 128 | list_for_each_entry(sdata, &local->interfaces, list) |
129 | if (sdata->dev != dev && netif_running(sdata->dev)) | 129 | if (netif_running(sdata->dev)) |
130 | dev_close(sdata->dev); | 130 | dev_close(sdata->dev); |
131 | 131 | ||
132 | return 0; | 132 | return 0; |
@@ -194,7 +194,7 @@ static int ieee80211_open(struct net_device *dev) | |||
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | 194 | list_for_each_entry(nsdata, &local->interfaces, list) { |
195 | struct net_device *ndev = nsdata->dev; | 195 | struct net_device *ndev = nsdata->dev; |
196 | 196 | ||
197 | if (ndev != dev && ndev != local->mdev && netif_running(ndev)) { | 197 | if (ndev != dev && netif_running(ndev)) { |
198 | /* | 198 | /* |
199 | * Allow only a single IBSS interface to be up at any | 199 | * Allow only a single IBSS interface to be up at any |
200 | * time. This is restricted because beacon distribution | 200 | * time. This is restricted because beacon distribution |
@@ -210,30 +210,6 @@ static int ieee80211_open(struct net_device *dev) | |||
210 | return -EBUSY; | 210 | return -EBUSY; |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * Disallow multiple IBSS/STA mode interfaces. | ||
214 | * | ||
215 | * This is a technical restriction, it is possible although | ||
216 | * most likely not IEEE 802.11 compliant to have multiple | ||
217 | * STAs with just a single hardware (the TSF timer will not | ||
218 | * be adjusted properly.) | ||
219 | * | ||
220 | * However, because mac80211 uses the master device's BSS | ||
221 | * information for each STA/IBSS interface, doing this will | ||
222 | * currently corrupt that BSS information completely, unless, | ||
223 | * a not very useful case, both STAs are associated to the | ||
224 | * same BSS. | ||
225 | * | ||
226 | * To remove this restriction, the BSS information needs to | ||
227 | * be embedded in the STA/IBSS mode sdata instead of using | ||
228 | * the master device's BSS structure. | ||
229 | */ | ||
230 | if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
231 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && | ||
232 | (nsdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
233 | nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)) | ||
234 | return -EBUSY; | ||
235 | |||
236 | /* | ||
237 | * The remaining checks are only performed for interfaces | 213 | * The remaining checks are only performed for interfaces |
238 | * with the same MAC address. | 214 | * with the same MAC address. |
239 | */ | 215 | */ |
@@ -252,7 +228,7 @@ static int ieee80211_open(struct net_device *dev) | |||
252 | */ | 228 | */ |
253 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && | 229 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && |
254 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) | 230 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) |
255 | sdata->u.vlan.ap = nsdata; | 231 | sdata->bss = &nsdata->u.ap; |
256 | } | 232 | } |
257 | } | 233 | } |
258 | 234 | ||
@@ -262,10 +238,13 @@ static int ieee80211_open(struct net_device *dev) | |||
262 | return -ENOLINK; | 238 | return -ENOLINK; |
263 | break; | 239 | break; |
264 | case IEEE80211_IF_TYPE_VLAN: | 240 | case IEEE80211_IF_TYPE_VLAN: |
265 | if (!sdata->u.vlan.ap) | 241 | if (!sdata->bss) |
266 | return -ENOLINK; | 242 | return -ENOLINK; |
243 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
267 | break; | 244 | break; |
268 | case IEEE80211_IF_TYPE_AP: | 245 | case IEEE80211_IF_TYPE_AP: |
246 | sdata->bss = &sdata->u.ap; | ||
247 | break; | ||
269 | case IEEE80211_IF_TYPE_STA: | 248 | case IEEE80211_IF_TYPE_STA: |
270 | case IEEE80211_IF_TYPE_MNTR: | 249 | case IEEE80211_IF_TYPE_MNTR: |
271 | case IEEE80211_IF_TYPE_IBSS: | 250 | case IEEE80211_IF_TYPE_IBSS: |
@@ -283,14 +262,13 @@ static int ieee80211_open(struct net_device *dev) | |||
283 | if (local->ops->start) | 262 | if (local->ops->start) |
284 | res = local->ops->start(local_to_hw(local)); | 263 | res = local->ops->start(local_to_hw(local)); |
285 | if (res) | 264 | if (res) |
286 | return res; | 265 | goto err_del_bss; |
287 | need_hw_reconfig = 1; | 266 | need_hw_reconfig = 1; |
288 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | 267 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); |
289 | } | 268 | } |
290 | 269 | ||
291 | switch (sdata->vif.type) { | 270 | switch (sdata->vif.type) { |
292 | case IEEE80211_IF_TYPE_VLAN: | 271 | case IEEE80211_IF_TYPE_VLAN: |
293 | list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans); | ||
294 | /* no need to tell driver */ | 272 | /* no need to tell driver */ |
295 | break; | 273 | break; |
296 | case IEEE80211_IF_TYPE_MNTR: | 274 | case IEEE80211_IF_TYPE_MNTR: |
@@ -329,7 +307,8 @@ static int ieee80211_open(struct net_device *dev) | |||
329 | if (res) | 307 | if (res) |
330 | goto err_stop; | 308 | goto err_stop; |
331 | 309 | ||
332 | ieee80211_if_config(dev); | 310 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
311 | ieee80211_start_mesh(sdata->dev); | ||
333 | changed |= ieee80211_reset_erp_info(dev); | 312 | changed |= ieee80211_reset_erp_info(dev); |
334 | ieee80211_bss_info_change_notify(sdata, changed); | 313 | ieee80211_bss_info_change_notify(sdata, changed); |
335 | ieee80211_enable_keys(sdata); | 314 | ieee80211_enable_keys(sdata); |
@@ -404,6 +383,10 @@ static int ieee80211_open(struct net_device *dev) | |||
404 | err_stop: | 383 | err_stop: |
405 | if (!local->open_count && local->ops->stop) | 384 | if (!local->open_count && local->ops->stop) |
406 | local->ops->stop(local_to_hw(local)); | 385 | local->ops->stop(local_to_hw(local)); |
386 | err_del_bss: | ||
387 | sdata->bss = NULL; | ||
388 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | ||
389 | list_del(&sdata->u.vlan.list); | ||
407 | return res; | 390 | return res; |
408 | } | 391 | } |
409 | 392 | ||
@@ -486,7 +469,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
486 | switch (sdata->vif.type) { | 469 | switch (sdata->vif.type) { |
487 | case IEEE80211_IF_TYPE_VLAN: | 470 | case IEEE80211_IF_TYPE_VLAN: |
488 | list_del(&sdata->u.vlan.list); | 471 | list_del(&sdata->u.vlan.list); |
489 | sdata->u.vlan.ap = NULL; | ||
490 | /* no need to tell driver */ | 472 | /* no need to tell driver */ |
491 | break; | 473 | break; |
492 | case IEEE80211_IF_TYPE_MNTR: | 474 | case IEEE80211_IF_TYPE_MNTR: |
@@ -549,6 +531,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
549 | local->ops->remove_interface(local_to_hw(local), &conf); | 531 | local->ops->remove_interface(local_to_hw(local), &conf); |
550 | } | 532 | } |
551 | 533 | ||
534 | sdata->bss = NULL; | ||
535 | |||
552 | if (local->open_count == 0) { | 536 | if (local->open_count == 0) { |
553 | if (netif_running(local->mdev)) | 537 | if (netif_running(local->mdev)) |
554 | dev_close(local->mdev); | 538 | dev_close(local->mdev); |
@@ -988,7 +972,6 @@ static const struct header_ops ieee80211_header_ops = { | |||
988 | .cache_update = eth_header_cache_update, | 972 | .cache_update = eth_header_cache_update, |
989 | }; | 973 | }; |
990 | 974 | ||
991 | /* Must not be called for mdev */ | ||
992 | void ieee80211_if_setup(struct net_device *dev) | 975 | void ieee80211_if_setup(struct net_device *dev) |
993 | { | 976 | { |
994 | ether_setup(dev); | 977 | ether_setup(dev); |
@@ -998,62 +981,52 @@ void ieee80211_if_setup(struct net_device *dev) | |||
998 | dev->change_mtu = ieee80211_change_mtu; | 981 | dev->change_mtu = ieee80211_change_mtu; |
999 | dev->open = ieee80211_open; | 982 | dev->open = ieee80211_open; |
1000 | dev->stop = ieee80211_stop; | 983 | dev->stop = ieee80211_stop; |
1001 | dev->destructor = ieee80211_if_free; | 984 | dev->destructor = free_netdev; |
1002 | } | 985 | } |
1003 | 986 | ||
1004 | /* everything else */ | 987 | /* everything else */ |
1005 | 988 | ||
1006 | static int __ieee80211_if_config(struct net_device *dev, | 989 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) |
1007 | struct sk_buff *beacon) | ||
1008 | { | 990 | { |
1009 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 991 | struct ieee80211_local *local = sdata->local; |
1010 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1011 | struct ieee80211_if_conf conf; | 992 | struct ieee80211_if_conf conf; |
1012 | 993 | ||
1013 | 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) | ||
1014 | return 0; | 998 | return 0; |
1015 | 999 | ||
1016 | memset(&conf, 0, sizeof(conf)); | 1000 | memset(&conf, 0, sizeof(conf)); |
1017 | conf.type = sdata->vif.type; | 1001 | conf.changed = changed; |
1002 | |||
1018 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1003 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || |
1019 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1004 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
1020 | conf.bssid = sdata->u.sta.bssid; | 1005 | conf.bssid = sdata->u.sta.bssid; |
1021 | conf.ssid = sdata->u.sta.ssid; | 1006 | conf.ssid = sdata->u.sta.ssid; |
1022 | conf.ssid_len = sdata->u.sta.ssid_len; | 1007 | conf.ssid_len = sdata->u.sta.ssid_len; |
1023 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1024 | conf.beacon = beacon; | ||
1025 | ieee80211_start_mesh(dev); | ||
1026 | } 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; | ||
1027 | conf.ssid = sdata->u.ap.ssid; | 1010 | conf.ssid = sdata->u.ap.ssid; |
1028 | conf.ssid_len = sdata->u.ap.ssid_len; | 1011 | conf.ssid_len = sdata->u.ap.ssid_len; |
1029 | 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; | ||
1030 | } | 1020 | } |
1031 | return local->ops->config_interface(local_to_hw(local), | ||
1032 | &sdata->vif, &conf); | ||
1033 | } | ||
1034 | 1021 | ||
1035 | int ieee80211_if_config(struct net_device *dev) | 1022 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) |
1036 | { | 1023 | return -EINVAL; |
1037 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1038 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1039 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | ||
1040 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | ||
1041 | return ieee80211_if_config_beacon(dev); | ||
1042 | return __ieee80211_if_config(dev, NULL); | ||
1043 | } | ||
1044 | 1024 | ||
1045 | int ieee80211_if_config_beacon(struct net_device *dev) | 1025 | if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID))) |
1046 | { | 1026 | return -EINVAL; |
1047 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1048 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1049 | struct sk_buff *skb; | ||
1050 | 1027 | ||
1051 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1028 | return local->ops->config_interface(local_to_hw(local), |
1052 | return 0; | 1029 | &sdata->vif, &conf); |
1053 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); | ||
1054 | if (!skb) | ||
1055 | return -ENOMEM; | ||
1056 | return __ieee80211_if_config(dev, skb); | ||
1057 | } | 1030 | } |
1058 | 1031 | ||
1059 | int ieee80211_hw_config(struct ieee80211_local *local) | 1032 | int ieee80211_hw_config(struct ieee80211_local *local) |
@@ -1659,7 +1632,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1659 | int result; | 1632 | int result; |
1660 | enum ieee80211_band band; | 1633 | enum ieee80211_band band; |
1661 | struct net_device *mdev; | 1634 | struct net_device *mdev; |
1662 | struct ieee80211_sub_if_data *sdata; | 1635 | struct wireless_dev *mwdev; |
1663 | 1636 | ||
1664 | /* | 1637 | /* |
1665 | * generic code guarantees at least one band, | 1638 | * generic code guarantees at least one band, |
@@ -1699,8 +1672,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1699 | hw->ampdu_queues = 0; | 1672 | hw->ampdu_queues = 0; |
1700 | #endif | 1673 | #endif |
1701 | 1674 | ||
1702 | /* for now, mdev needs sub_if_data :/ */ | 1675 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), |
1703 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), | ||
1704 | "wmaster%d", ether_setup, | 1676 | "wmaster%d", ether_setup, |
1705 | ieee80211_num_queues(hw)); | 1677 | ieee80211_num_queues(hw)); |
1706 | if (!mdev) | 1678 | if (!mdev) |
@@ -1709,13 +1681,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1709 | if (ieee80211_num_queues(hw) > 1) | 1681 | if (ieee80211_num_queues(hw) > 1) |
1710 | mdev->features |= NETIF_F_MULTI_QUEUE; | 1682 | mdev->features |= NETIF_F_MULTI_QUEUE; |
1711 | 1683 | ||
1712 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1684 | mwdev = netdev_priv(mdev); |
1713 | mdev->ieee80211_ptr = &sdata->wdev; | 1685 | mdev->ieee80211_ptr = mwdev; |
1714 | sdata->wdev.wiphy = local->hw.wiphy; | 1686 | mwdev->wiphy = local->hw.wiphy; |
1715 | 1687 | ||
1716 | local->mdev = mdev; | 1688 | local->mdev = mdev; |
1717 | 1689 | ||
1718 | ieee80211_rx_bss_list_init(mdev); | 1690 | ieee80211_rx_bss_list_init(local); |
1719 | 1691 | ||
1720 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | 1692 | mdev->hard_start_xmit = ieee80211_master_start_xmit; |
1721 | mdev->open = ieee80211_master_open; | 1693 | mdev->open = ieee80211_master_open; |
@@ -1724,16 +1696,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1724 | mdev->header_ops = &ieee80211_header_ops; | 1696 | mdev->header_ops = &ieee80211_header_ops; |
1725 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | 1697 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; |
1726 | 1698 | ||
1727 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
1728 | sdata->dev = mdev; | ||
1729 | sdata->local = local; | ||
1730 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1731 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1732 | ieee80211_if_sdata_init(sdata); | ||
1733 | |||
1734 | /* no RCU needed since we're still during init phase */ | ||
1735 | list_add_tail(&sdata->list, &local->interfaces); | ||
1736 | |||
1737 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1699 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1738 | local->hw.workqueue = create_freezeable_workqueue(name); | 1700 | local->hw.workqueue = create_freezeable_workqueue(name); |
1739 | if (!local->hw.workqueue) { | 1701 | if (!local->hw.workqueue) { |
@@ -1779,9 +1741,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1779 | if (result < 0) | 1741 | if (result < 0) |
1780 | goto fail_dev; | 1742 | goto fail_dev; |
1781 | 1743 | ||
1782 | ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1783 | ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); | ||
1784 | |||
1785 | result = ieee80211_init_rate_ctrl_alg(local, | 1744 | result = ieee80211_init_rate_ctrl_alg(local, |
1786 | hw->rate_control_algorithm); | 1745 | hw->rate_control_algorithm); |
1787 | if (result < 0) { | 1746 | if (result < 0) { |
@@ -1801,13 +1760,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1801 | ieee80211_install_qdisc(local->mdev); | 1760 | ieee80211_install_qdisc(local->mdev); |
1802 | 1761 | ||
1803 | /* add one default STA interface */ | 1762 | /* add one default STA interface */ |
1804 | result = ieee80211_if_add(local->mdev, "wlan%d", NULL, | 1763 | result = ieee80211_if_add(local, "wlan%d", NULL, |
1805 | IEEE80211_IF_TYPE_STA, NULL); | 1764 | IEEE80211_IF_TYPE_STA, NULL); |
1806 | if (result) | 1765 | if (result) |
1807 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 1766 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", |
1808 | wiphy_name(local->hw.wiphy)); | 1767 | wiphy_name(local->hw.wiphy)); |
1809 | 1768 | ||
1810 | local->reg_state = IEEE80211_DEV_REGISTERED; | ||
1811 | rtnl_unlock(); | 1769 | rtnl_unlock(); |
1812 | 1770 | ||
1813 | ieee80211_led_init(local); | 1771 | ieee80211_led_init(local); |
@@ -1817,7 +1775,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1817 | fail_wep: | 1775 | fail_wep: |
1818 | rate_control_deinitialize(local); | 1776 | rate_control_deinitialize(local); |
1819 | fail_rate: | 1777 | fail_rate: |
1820 | ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1821 | unregister_netdevice(local->mdev); | 1778 | unregister_netdevice(local->mdev); |
1822 | local->mdev = NULL; | 1779 | local->mdev = NULL; |
1823 | fail_dev: | 1780 | fail_dev: |
@@ -1827,10 +1784,8 @@ fail_sta_info: | |||
1827 | debugfs_hw_del(local); | 1784 | debugfs_hw_del(local); |
1828 | destroy_workqueue(local->hw.workqueue); | 1785 | destroy_workqueue(local->hw.workqueue); |
1829 | fail_workqueue: | 1786 | fail_workqueue: |
1830 | if (local->mdev != NULL) { | 1787 | if (local->mdev) |
1831 | ieee80211_if_free(local->mdev); | 1788 | free_netdev(local->mdev); |
1832 | local->mdev = NULL; | ||
1833 | } | ||
1834 | fail_mdev_alloc: | 1789 | fail_mdev_alloc: |
1835 | wiphy_unregister(local->hw.wiphy); | 1790 | wiphy_unregister(local->hw.wiphy); |
1836 | return result; | 1791 | return result; |
@@ -1840,42 +1795,27 @@ EXPORT_SYMBOL(ieee80211_register_hw); | |||
1840 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) | 1795 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) |
1841 | { | 1796 | { |
1842 | struct ieee80211_local *local = hw_to_local(hw); | 1797 | struct ieee80211_local *local = hw_to_local(hw); |
1843 | struct ieee80211_sub_if_data *sdata, *tmp; | ||
1844 | 1798 | ||
1845 | tasklet_kill(&local->tx_pending_tasklet); | 1799 | tasklet_kill(&local->tx_pending_tasklet); |
1846 | tasklet_kill(&local->tasklet); | 1800 | tasklet_kill(&local->tasklet); |
1847 | 1801 | ||
1848 | rtnl_lock(); | 1802 | rtnl_lock(); |
1849 | 1803 | ||
1850 | BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED); | ||
1851 | |||
1852 | local->reg_state = IEEE80211_DEV_UNREGISTERED; | ||
1853 | |||
1854 | /* | 1804 | /* |
1855 | * At this point, interface list manipulations are fine | 1805 | * At this point, interface list manipulations are fine |
1856 | * because the driver cannot be handing us frames any | 1806 | * because the driver cannot be handing us frames any |
1857 | * more and the tasklet is killed. | 1807 | * more and the tasklet is killed. |
1858 | */ | 1808 | */ |
1859 | 1809 | ||
1860 | /* | 1810 | /* First, we remove all virtual interfaces. */ |
1861 | * First, we remove all non-master interfaces. Do this because they | 1811 | ieee80211_remove_interfaces(local); |
1862 | * may have bss pointer dependency on the master, and when we free | ||
1863 | * the master these would be freed as well, breaking our list | ||
1864 | * iteration completely. | ||
1865 | */ | ||
1866 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | ||
1867 | if (sdata->dev == local->mdev) | ||
1868 | continue; | ||
1869 | list_del(&sdata->list); | ||
1870 | __ieee80211_if_del(local, sdata); | ||
1871 | } | ||
1872 | 1812 | ||
1873 | /* then, finally, remove the master interface */ | 1813 | /* then, finally, remove the master interface */ |
1874 | __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev)); | 1814 | unregister_netdevice(local->mdev); |
1875 | 1815 | ||
1876 | rtnl_unlock(); | 1816 | rtnl_unlock(); |
1877 | 1817 | ||
1878 | ieee80211_rx_bss_list_deinit(local->mdev); | 1818 | ieee80211_rx_bss_list_deinit(local); |
1879 | ieee80211_clear_tx_pending(local); | 1819 | ieee80211_clear_tx_pending(local); |
1880 | sta_info_stop(local); | 1820 | sta_info_stop(local); |
1881 | rate_control_deinitialize(local); | 1821 | rate_control_deinitialize(local); |
@@ -1892,8 +1832,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1892 | wiphy_unregister(local->hw.wiphy); | 1832 | wiphy_unregister(local->hw.wiphy); |
1893 | ieee80211_wep_free(local); | 1833 | ieee80211_wep_free(local); |
1894 | ieee80211_led_exit(local); | 1834 | ieee80211_led_exit(local); |
1895 | ieee80211_if_free(local->mdev); | 1835 | free_netdev(local->mdev); |
1896 | local->mdev = NULL; | ||
1897 | } | 1836 | } |
1898 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1837 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1899 | 1838 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dbc8cf454bc0..8f51375317dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -78,7 +78,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | |||
78 | static struct ieee80211_sta_bss * | 78 | static struct ieee80211_sta_bss * |
79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | 79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, |
80 | u8 *ssid, u8 ssid_len); | 80 | u8 *ssid, u8 ssid_len); |
81 | static void ieee80211_rx_bss_put(struct net_device *dev, | 81 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, |
82 | struct ieee80211_sta_bss *bss); | 82 | struct ieee80211_sta_bss *bss); |
83 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 83 | static int ieee80211_sta_find_ibss(struct net_device *dev, |
84 | struct ieee80211_if_sta *ifsta); | 84 | struct ieee80211_if_sta *ifsta); |
@@ -345,7 +345,7 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
345 | params.aifs = pos[0] & 0x0f; | 345 | params.aifs = pos[0] & 0x0f; |
346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | 346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); |
347 | params.cw_min = ecw2cw(pos[1] & 0x0f); | 347 | params.cw_min = ecw2cw(pos[1] & 0x0f); |
348 | params.txop = pos[2] | (pos[3] << 8); | 348 | params.txop = get_unaligned_le16(pos + 2); |
349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | 350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " |
351 | "cWmin=%d cWmax=%d txop=%d\n", | 351 | "cWmin=%d cWmax=%d txop=%d\n", |
@@ -554,7 +554,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
554 | 554 | ||
555 | changed |= ieee80211_handle_bss_capability(sdata, bss); | 555 | changed |= ieee80211_handle_bss_capability(sdata, bss); |
556 | 556 | ||
557 | ieee80211_rx_bss_put(dev, bss); | 557 | ieee80211_rx_bss_put(local, bss); |
558 | } | 558 | } |
559 | 559 | ||
560 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 560 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
@@ -760,7 +760,7 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
760 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | 760 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) |
761 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | 761 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; |
762 | 762 | ||
763 | ieee80211_rx_bss_put(dev, bss); | 763 | ieee80211_rx_bss_put(local, bss); |
764 | } else { | 764 | } else { |
765 | rates = ~0; | 765 | rates = ~0; |
766 | rates_len = sband->n_bitrates; | 766 | rates_len = sband->n_bitrates; |
@@ -992,7 +992,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, | |||
992 | wep_privacy = !!ieee80211_sta_wep_configured(dev); | 992 | wep_privacy = !!ieee80211_sta_wep_configured(dev); |
993 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | 993 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); |
994 | 994 | ||
995 | ieee80211_rx_bss_put(dev, bss); | 995 | ieee80211_rx_bss_put(local, bss); |
996 | 996 | ||
997 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) | 997 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) |
998 | return 0; | 998 | return 0; |
@@ -2094,7 +2094,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2094 | sta->last_signal = bss->signal; | 2094 | sta->last_signal = bss->signal; |
2095 | sta->last_qual = bss->qual; | 2095 | sta->last_qual = bss->qual; |
2096 | sta->last_noise = bss->noise; | 2096 | sta->last_noise = bss->noise; |
2097 | ieee80211_rx_bss_put(dev, bss); | 2097 | ieee80211_rx_bss_put(local, bss); |
2098 | } | 2098 | } |
2099 | 2099 | ||
2100 | err = sta_info_insert(sta); | 2100 | err = sta_info_insert(sta); |
@@ -2212,10 +2212,9 @@ static void __ieee80211_rx_bss_hash_add(struct net_device *dev, | |||
2212 | 2212 | ||
2213 | 2213 | ||
2214 | /* Caller must hold local->sta_bss_lock */ | 2214 | /* Caller must hold local->sta_bss_lock */ |
2215 | static void __ieee80211_rx_bss_hash_del(struct net_device *dev, | 2215 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, |
2216 | struct ieee80211_sta_bss *bss) | 2216 | struct ieee80211_sta_bss *bss) |
2217 | { | 2217 | { |
2218 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2219 | struct ieee80211_sta_bss *b, *prev = NULL; | 2218 | struct ieee80211_sta_bss *b, *prev = NULL; |
2220 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; | 2219 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; |
2221 | while (b) { | 2220 | while (b) { |
@@ -2367,39 +2366,35 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | |||
2367 | } | 2366 | } |
2368 | 2367 | ||
2369 | 2368 | ||
2370 | static void ieee80211_rx_bss_put(struct net_device *dev, | 2369 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, |
2371 | struct ieee80211_sta_bss *bss) | 2370 | struct ieee80211_sta_bss *bss) |
2372 | { | 2371 | { |
2373 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2374 | |||
2375 | local_bh_disable(); | 2372 | local_bh_disable(); |
2376 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { | 2373 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { |
2377 | local_bh_enable(); | 2374 | local_bh_enable(); |
2378 | return; | 2375 | return; |
2379 | } | 2376 | } |
2380 | 2377 | ||
2381 | __ieee80211_rx_bss_hash_del(dev, bss); | 2378 | __ieee80211_rx_bss_hash_del(local, bss); |
2382 | list_del(&bss->list); | 2379 | list_del(&bss->list); |
2383 | spin_unlock_bh(&local->sta_bss_lock); | 2380 | spin_unlock_bh(&local->sta_bss_lock); |
2384 | ieee80211_rx_bss_free(bss); | 2381 | ieee80211_rx_bss_free(bss); |
2385 | } | 2382 | } |
2386 | 2383 | ||
2387 | 2384 | ||
2388 | void ieee80211_rx_bss_list_init(struct net_device *dev) | 2385 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) |
2389 | { | 2386 | { |
2390 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2391 | spin_lock_init(&local->sta_bss_lock); | 2387 | spin_lock_init(&local->sta_bss_lock); |
2392 | INIT_LIST_HEAD(&local->sta_bss_list); | 2388 | INIT_LIST_HEAD(&local->sta_bss_list); |
2393 | } | 2389 | } |
2394 | 2390 | ||
2395 | 2391 | ||
2396 | void ieee80211_rx_bss_list_deinit(struct net_device *dev) | 2392 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) |
2397 | { | 2393 | { |
2398 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2399 | struct ieee80211_sta_bss *bss, *tmp; | 2394 | struct ieee80211_sta_bss *bss, *tmp; |
2400 | 2395 | ||
2401 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) | 2396 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) |
2402 | ieee80211_rx_bss_put(dev, bss); | 2397 | ieee80211_rx_bss_put(local, bss); |
2403 | } | 2398 | } |
2404 | 2399 | ||
2405 | 2400 | ||
@@ -2411,8 +2406,6 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2411 | int res, rates, i, j; | 2406 | int res, rates, i, j; |
2412 | struct sk_buff *skb; | 2407 | struct sk_buff *skb; |
2413 | struct ieee80211_mgmt *mgmt; | 2408 | struct ieee80211_mgmt *mgmt; |
2414 | struct ieee80211_tx_info *control; | ||
2415 | struct rate_selection ratesel; | ||
2416 | u8 *pos; | 2409 | u8 *pos; |
2417 | struct ieee80211_sub_if_data *sdata; | 2410 | struct ieee80211_sub_if_data *sdata; |
2418 | struct ieee80211_supported_band *sband; | 2411 | struct ieee80211_supported_band *sband; |
@@ -2430,7 +2423,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2430 | local->ops->reset_tsf(local_to_hw(local)); | 2423 | local->ops->reset_tsf(local_to_hw(local)); |
2431 | } | 2424 | } |
2432 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 2425 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); |
2433 | res = ieee80211_if_config(dev); | 2426 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
2434 | if (res) | 2427 | if (res) |
2435 | return res; | 2428 | return res; |
2436 | 2429 | ||
@@ -2444,19 +2437,16 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2444 | if (res) | 2437 | if (res) |
2445 | return res; | 2438 | return res; |
2446 | 2439 | ||
2447 | /* Set beacon template */ | 2440 | /* Build IBSS probe response */ |
2448 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 2441 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
2449 | do { | 2442 | if (skb) { |
2450 | if (!skb) | ||
2451 | break; | ||
2452 | |||
2453 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2443 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2454 | 2444 | ||
2455 | mgmt = (struct ieee80211_mgmt *) | 2445 | mgmt = (struct ieee80211_mgmt *) |
2456 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 2446 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
2457 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 2447 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
2458 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 2448 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, |
2459 | IEEE80211_STYPE_BEACON); | 2449 | IEEE80211_STYPE_PROBE_RESP); |
2460 | memset(mgmt->da, 0xff, ETH_ALEN); | 2450 | memset(mgmt->da, 0xff, ETH_ALEN); |
2461 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 2451 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); |
2462 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 2452 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
@@ -2500,61 +2490,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2500 | memcpy(pos, &bss->supp_rates[8], rates); | 2490 | memcpy(pos, &bss->supp_rates[8], rates); |
2501 | } | 2491 | } |
2502 | 2492 | ||
2503 | control = IEEE80211_SKB_CB(skb); | 2493 | ifsta->probe_resp = skb; |
2504 | |||
2505 | rate_control_get_rate(dev, sband, skb, &ratesel); | ||
2506 | if (ratesel.rate_idx < 0) { | ||
2507 | printk(KERN_DEBUG "%s: Failed to determine TX rate " | ||
2508 | "for IBSS beacon\n", dev->name); | ||
2509 | break; | ||
2510 | } | ||
2511 | control->control.vif = &sdata->vif; | ||
2512 | control->tx_rate_idx = ratesel.rate_idx; | ||
2513 | if (sdata->bss_conf.use_short_preamble && | ||
2514 | sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | ||
2515 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | ||
2516 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
2517 | control->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
2518 | control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
2519 | control->control.retry_limit = 1; | ||
2520 | |||
2521 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); | ||
2522 | if (ifsta->probe_resp) { | ||
2523 | mgmt = (struct ieee80211_mgmt *) | ||
2524 | ifsta->probe_resp->data; | ||
2525 | mgmt->frame_control = | ||
2526 | IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
2527 | IEEE80211_STYPE_PROBE_RESP); | ||
2528 | } else { | ||
2529 | printk(KERN_DEBUG "%s: Could not allocate ProbeResp " | ||
2530 | "template for IBSS\n", dev->name); | ||
2531 | } | ||
2532 | 2494 | ||
2533 | if (local->ops->beacon_update && | 2495 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
2534 | local->ops->beacon_update(local_to_hw(local), skb) == 0) { | 2496 | } |
2535 | printk(KERN_DEBUG "%s: Configured IBSS beacon " | ||
2536 | "template\n", dev->name); | ||
2537 | skb = NULL; | ||
2538 | } | ||
2539 | |||
2540 | rates = 0; | ||
2541 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2542 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
2543 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; | ||
2544 | for (j = 0; j < sband->n_bitrates; j++) | ||
2545 | if (sband->bitrates[j].bitrate == bitrate) | ||
2546 | rates |= BIT(j); | ||
2547 | } | ||
2548 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2549 | |||
2550 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2551 | } while (0); | ||
2552 | 2497 | ||
2553 | if (skb) { | 2498 | rates = 0; |
2554 | printk(KERN_DEBUG "%s: Failed to configure IBSS beacon " | 2499 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2555 | "template\n", dev->name); | 2500 | for (i = 0; i < bss->supp_rates_len; i++) { |
2556 | 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); | ||
2557 | } | 2505 | } |
2506 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2507 | |||
2508 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2558 | 2509 | ||
2559 | ifsta->state = IEEE80211_IBSS_JOINED; | 2510 | ifsta->state = IEEE80211_IBSS_JOINED; |
2560 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 2511 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
@@ -2775,7 +2726,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2775 | */ | 2726 | */ |
2776 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 2727 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
2777 | bss->probe_resp && beacon) { | 2728 | bss->probe_resp && beacon) { |
2778 | ieee80211_rx_bss_put(dev, bss); | 2729 | ieee80211_rx_bss_put(local, bss); |
2779 | return; | 2730 | return; |
2780 | } | 2731 | } |
2781 | 2732 | ||
@@ -2918,7 +2869,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2918 | } | 2869 | } |
2919 | } | 2870 | } |
2920 | 2871 | ||
2921 | ieee80211_rx_bss_put(dev, bss); | 2872 | ieee80211_rx_bss_put(local, bss); |
2922 | } | 2873 | } |
2923 | 2874 | ||
2924 | 2875 | ||
@@ -3338,7 +3289,7 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, | |||
3338 | 3289 | ||
3339 | free_plinks = mesh_plink_availables(sdata); | 3290 | free_plinks = mesh_plink_availables(sdata); |
3340 | if (free_plinks != sdata->u.sta.accepting_plinks) | 3291 | if (free_plinks != sdata->u.sta.accepting_plinks) |
3341 | ieee80211_if_config_beacon(dev); | 3292 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
3342 | 3293 | ||
3343 | mod_timer(&ifsta->timer, jiffies + | 3294 | mod_timer(&ifsta->timer, jiffies + |
3344 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | 3295 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); |
@@ -3578,7 +3529,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
3578 | selected->ssid_len); | 3529 | selected->ssid_len); |
3579 | ieee80211_sta_set_bssid(dev, selected->bssid); | 3530 | ieee80211_sta_set_bssid(dev, selected->bssid); |
3580 | ieee80211_sta_def_wmm_params(dev, selected, 0); | 3531 | ieee80211_sta_def_wmm_params(dev, selected, 0); |
3581 | ieee80211_rx_bss_put(dev, selected); | 3532 | ieee80211_rx_bss_put(local, selected); |
3582 | ifsta->state = IEEE80211_AUTHENTICATE; | 3533 | ifsta->state = IEEE80211_AUTHENTICATE; |
3583 | ieee80211_sta_reset_auth(dev, ifsta); | 3534 | ieee80211_sta_reset_auth(dev, ifsta); |
3584 | return 0; | 3535 | return 0; |
@@ -3655,7 +3606,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3655 | } | 3606 | } |
3656 | 3607 | ||
3657 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 3608 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); |
3658 | ieee80211_rx_bss_put(dev, bss); | 3609 | ieee80211_rx_bss_put(local, bss); |
3659 | return ret; | 3610 | return ret; |
3660 | } | 3611 | } |
3661 | 3612 | ||
@@ -3711,7 +3662,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3711 | " based on configured SSID\n", | 3662 | " based on configured SSID\n", |
3712 | dev->name, print_mac(mac, bssid)); | 3663 | dev->name, print_mac(mac, bssid)); |
3713 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 3664 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); |
3714 | ieee80211_rx_bss_put(dev, bss); | 3665 | ieee80211_rx_bss_put(local, bss); |
3715 | return ret; | 3666 | return ret; |
3716 | } | 3667 | } |
3717 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 3668 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
@@ -3762,28 +3713,45 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | |||
3762 | { | 3713 | { |
3763 | 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); |
3764 | struct ieee80211_if_sta *ifsta; | 3715 | struct ieee80211_if_sta *ifsta; |
3716 | int res; | ||
3765 | 3717 | ||
3766 | if (len > IEEE80211_MAX_SSID_LEN) | 3718 | if (len > IEEE80211_MAX_SSID_LEN) |
3767 | return -EINVAL; | 3719 | return -EINVAL; |
3768 | 3720 | ||
3769 | ifsta = &sdata->u.sta; | 3721 | ifsta = &sdata->u.sta; |
3770 | 3722 | ||
3771 | 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; | ||
3772 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | 3727 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
3773 | memcpy(ifsta->ssid, ssid, len); | 3728 | |
3774 | memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len); | 3729 | res = 0; |
3775 | 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 | } | ||
3776 | 3742 | ||
3777 | if (len) | 3743 | if (len) |
3778 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 3744 | ifsta->flags |= IEEE80211_STA_SSID_SET; |
3779 | else | 3745 | else |
3780 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | 3746 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; |
3747 | |||
3781 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | 3748 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && |
3782 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | 3749 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { |
3783 | ifsta->ibss_join_req = jiffies; | 3750 | ifsta->ibss_join_req = jiffies; |
3784 | ifsta->state = IEEE80211_IBSS_SEARCH; | 3751 | ifsta->state = IEEE80211_IBSS_SEARCH; |
3785 | return ieee80211_sta_find_ibss(dev, ifsta); | 3752 | return ieee80211_sta_find_ibss(dev, ifsta); |
3786 | } | 3753 | } |
3754 | |||
3787 | return 0; | 3755 | return 0; |
3788 | } | 3756 | } |
3789 | 3757 | ||
@@ -3809,7 +3777,12 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) | |||
3809 | 3777 | ||
3810 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 3778 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
3811 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 3779 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
3812 | 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); | ||
3813 | if (res) { | 3786 | if (res) { |
3814 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | 3787 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
3815 | "the low-level driver\n", dev->name); | 3788 | "the low-level driver\n", dev->name); |
@@ -3907,11 +3880,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
3907 | 3880 | ||
3908 | rcu_read_lock(); | 3881 | rcu_read_lock(); |
3909 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 3882 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
3910 | |||
3911 | /* No need to wake the master device. */ | ||
3912 | if (sdata->dev == local->mdev) | ||
3913 | continue; | ||
3914 | |||
3915 | /* Tell AP we're back */ | 3883 | /* Tell AP we're back */ |
3916 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 3884 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && |
3917 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) | 3885 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) |
@@ -4077,12 +4045,6 @@ static int ieee80211_sta_start_scan(struct net_device *dev, | |||
4077 | 4045 | ||
4078 | rcu_read_lock(); | 4046 | rcu_read_lock(); |
4079 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 4047 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4080 | |||
4081 | /* Don't stop the master interface, otherwise we can't transmit | ||
4082 | * probes! */ | ||
4083 | if (sdata->dev == local->mdev) | ||
4084 | continue; | ||
4085 | |||
4086 | netif_stop_queue(sdata->dev); | 4048 | netif_stop_queue(sdata->dev); |
4087 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 4049 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && |
4088 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) | 4050 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) |
@@ -4398,7 +4360,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | |||
4398 | return NULL; | 4360 | return NULL; |
4399 | } | 4361 | } |
4400 | 4362 | ||
4401 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) | 4363 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) |
4402 | return NULL; | 4364 | return NULL; |
4403 | 4365 | ||
4404 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 4366 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -4473,12 +4435,10 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
4473 | case IEEE80211_NOTIFY_RE_ASSOC: | 4435 | case IEEE80211_NOTIFY_RE_ASSOC: |
4474 | rcu_read_lock(); | 4436 | rcu_read_lock(); |
4475 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 4437 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4438 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
4439 | continue; | ||
4476 | 4440 | ||
4477 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 4441 | ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); |
4478 | ieee80211_sta_req_auth(sdata->dev, | ||
4479 | &sdata->u.sta); | ||
4480 | } | ||
4481 | |||
4482 | } | 4442 | } |
4483 | rcu_read_unlock(); | 4443 | rcu_read_unlock(); |
4484 | break; | 4444 | break; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 742c5b06cffd..a914ba73ccf5 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -259,8 +259,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
259 | 259 | ||
260 | /* Don't update the state if we're not controlling the rate. */ | 260 | /* Don't update the state if we're not controlling the rate. */ |
261 | sdata = sta->sdata; | 261 | sdata = sta->sdata; |
262 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { | 262 | if (sdata->force_unicast_rateidx > -1) { |
263 | sta->txrate_idx = sdata->bss->max_ratectrl_rateidx; | 263 | sta->txrate_idx = sdata->max_ratectrl_rateidx; |
264 | goto unlock; | 264 | goto unlock; |
265 | } | 265 | } |
266 | 266 | ||
@@ -337,8 +337,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
337 | 337 | ||
338 | /* If a forced rate is in effect, select it. */ | 338 | /* If a forced rate is in effect, select it. */ |
339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
340 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) | 340 | if (sdata->force_unicast_rateidx > -1) |
341 | sta->txrate_idx = sdata->bss->force_unicast_rateidx; | 341 | sta->txrate_idx = sdata->force_unicast_rateidx; |
342 | 342 | ||
343 | rateidx = sta->txrate_idx; | 343 | rateidx = sta->txrate_idx; |
344 | 344 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fab443d717eb..6d9ae67c27ca 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -334,13 +334,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
334 | else | 334 | else |
335 | rx->flags &= ~IEEE80211_RX_AMSDU; | 335 | rx->flags &= ~IEEE80211_RX_AMSDU; |
336 | } else { | 336 | } else { |
337 | if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { | 337 | /* |
338 | /* Separate TID for management frames */ | 338 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
339 | tid = NUM_RX_DATA_QUEUES - 1; | 339 | * |
340 | } else { | 340 | * Sequence numbers for management frames, QoS data |
341 | /* no qos control present */ | 341 | * frames with a broadcast/multicast address in the |
342 | tid = 0; /* 802.1d - Best Effort */ | 342 | * Address 1 field, and all non-QoS data frames sent |
343 | } | 343 | * by QoS STAs are assigned using an additional single |
344 | * modulo-4096 counter, [...] | ||
345 | * | ||
346 | * We also use that counter for non-QoS STAs. | ||
347 | */ | ||
348 | tid = NUM_RX_DATA_QUEUES - 1; | ||
344 | } | 349 | } |
345 | 350 | ||
346 | rx->queue = tid; | 351 | rx->queue = tid; |
@@ -647,8 +652,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | |||
647 | 652 | ||
648 | sdata = sta->sdata; | 653 | sdata = sta->sdata; |
649 | 654 | ||
650 | if (sdata->bss) | 655 | atomic_inc(&sdata->bss->num_sta_ps); |
651 | atomic_inc(&sdata->bss->num_sta_ps); | ||
652 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 656 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
653 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 657 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
654 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 658 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
@@ -667,8 +671,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
667 | 671 | ||
668 | sdata = sta->sdata; | 672 | sdata = sta->sdata; |
669 | 673 | ||
670 | if (sdata->bss) | 674 | atomic_dec(&sdata->bss->num_sta_ps); |
671 | atomic_dec(&sdata->bss->num_sta_ps); | ||
672 | 675 | ||
673 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 676 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
674 | 677 | ||
@@ -742,7 +745,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
742 | sta->last_qual = rx->status->qual; | 745 | sta->last_qual = rx->status->qual; |
743 | sta->last_noise = rx->status->noise; | 746 | sta->last_noise = rx->status->noise; |
744 | 747 | ||
745 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 748 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
749 | (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP || | ||
750 | rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) { | ||
746 | /* Change STA power saving mode only in the end of a frame | 751 | /* Change STA power saving mode only in the end of a frame |
747 | * exchange sequence */ | 752 | * exchange sequence */ |
748 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
@@ -1772,11 +1777,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1772 | return 0; | 1777 | return 0; |
1773 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1778 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1774 | } | 1779 | } |
1775 | if (sdata->dev == sdata->local->mdev && | ||
1776 | !(rx->flags & IEEE80211_RX_IN_SCAN)) | ||
1777 | /* do not receive anything via | ||
1778 | * master device when not scanning */ | ||
1779 | return 0; | ||
1780 | break; | 1780 | break; |
1781 | case IEEE80211_IF_TYPE_WDS: | 1781 | case IEEE80211_IF_TYPE_WDS: |
1782 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 1782 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
@@ -2046,8 +2046,8 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2046 | 2046 | ||
2047 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 2047 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
2048 | 2048 | ||
2049 | /* null data frames are excluded */ | 2049 | /* qos null data frames are excluded */ |
2050 | if (unlikely(ieee80211_is_nullfunc(hdr->frame_control))) | 2050 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
2051 | goto end_reorder; | 2051 | goto end_reorder; |
2052 | 2052 | ||
2053 | /* new un-ordered ampdu frame - process it */ | 2053 | /* new un-ordered ampdu frame - process it */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 47d2c1bbfcaa..f2ba653b9d69 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -320,7 +320,9 @@ int sta_info_insert(struct sta_info *sta) | |||
320 | /* notify driver */ | 320 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 321 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
323 | sdata = sdata->u.vlan.ap; | 323 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | ||
325 | u.ap); | ||
324 | 326 | ||
325 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
326 | STA_NOTIFY_ADD, sta->addr); | 328 | STA_NOTIFY_ADD, sta->addr); |
@@ -375,8 +377,10 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | |||
375 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | 377 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, |
376 | struct sta_info *sta) | 378 | struct sta_info *sta) |
377 | { | 379 | { |
378 | if (bss) | 380 | BUG_ON(!bss); |
379 | __bss_tim_set(bss, sta->aid); | 381 | |
382 | __bss_tim_set(bss, sta->aid); | ||
383 | |||
380 | if (sta->local->ops->set_tim) { | 384 | if (sta->local->ops->set_tim) { |
381 | sta->local->tim_in_locked_section = true; | 385 | sta->local->tim_in_locked_section = true; |
382 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); |
@@ -388,6 +392,8 @@ void sta_info_set_tim_bit(struct sta_info *sta) | |||
388 | { | 392 | { |
389 | unsigned long flags; | 393 | unsigned long flags; |
390 | 394 | ||
395 | BUG_ON(!sta->sdata->bss); | ||
396 | |||
391 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 397 | spin_lock_irqsave(&sta->local->sta_lock, flags); |
392 | __sta_info_set_tim_bit(sta->sdata->bss, sta); | 398 | __sta_info_set_tim_bit(sta->sdata->bss, sta); |
393 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 399 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
@@ -396,8 +402,10 @@ void sta_info_set_tim_bit(struct sta_info *sta) | |||
396 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | 402 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, |
397 | struct sta_info *sta) | 403 | struct sta_info *sta) |
398 | { | 404 | { |
399 | if (bss) | 405 | BUG_ON(!bss); |
400 | __bss_tim_clear(bss, sta->aid); | 406 | |
407 | __bss_tim_clear(bss, sta->aid); | ||
408 | |||
401 | if (sta->local->ops->set_tim) { | 409 | if (sta->local->ops->set_tim) { |
402 | sta->local->tim_in_locked_section = true; | 410 | sta->local->tim_in_locked_section = true; |
403 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); |
@@ -409,6 +417,8 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
409 | { | 417 | { |
410 | unsigned long flags; | 418 | unsigned long flags; |
411 | 419 | ||
420 | BUG_ON(!sta->sdata->bss); | ||
421 | |||
412 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 422 | spin_lock_irqsave(&sta->local->sta_lock, flags); |
413 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); | 423 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); |
414 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
@@ -437,8 +447,9 @@ void __sta_info_unlink(struct sta_info **sta) | |||
437 | list_del(&(*sta)->list); | 447 | list_del(&(*sta)->list); |
438 | 448 | ||
439 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { | 449 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { |
440 | if (sdata->bss) | 450 | BUG_ON(!sdata->bss); |
441 | atomic_dec(&sdata->bss->num_sta_ps); | 451 | |
452 | atomic_dec(&sdata->bss->num_sta_ps); | ||
442 | __sta_info_clear_tim_bit(sdata->bss, *sta); | 453 | __sta_info_clear_tim_bit(sdata->bss, *sta); |
443 | } | 454 | } |
444 | 455 | ||
@@ -446,7 +457,9 @@ void __sta_info_unlink(struct sta_info **sta) | |||
446 | 457 | ||
447 | if (local->ops->sta_notify) { | 458 | if (local->ops->sta_notify) { |
448 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
449 | sdata = sdata->u.vlan.ap; | 460 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | ||
462 | u.ap); | ||
450 | 463 | ||
451 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
452 | STA_NOTIFY_REMOVE, (*sta)->addr); | 465 | STA_NOTIFY_REMOVE, (*sta)->addr); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 94311dcfe043..109db787ccb7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -285,6 +285,7 @@ struct sta_info { | |||
285 | unsigned long tx_fragments; | 285 | unsigned long tx_fragments; |
286 | int txrate_idx; | 286 | int txrate_idx; |
287 | int last_txrate_idx; | 287 | int last_txrate_idx; |
288 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | ||
288 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 289 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
289 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | 290 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; |
290 | #endif | 291 | #endif |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9bd9faac3c3c..0fbadd8b983c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -38,16 +38,6 @@ | |||
38 | 38 | ||
39 | /* misc utils */ | 39 | /* misc utils */ |
40 | 40 | ||
41 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, | ||
42 | struct ieee80211_hdr *hdr) | ||
43 | { | ||
44 | /* Set the sequence number for this frame. */ | ||
45 | hdr->seq_ctrl = cpu_to_le16(sdata->sequence); | ||
46 | |||
47 | /* Increase the sequence number. */ | ||
48 | sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ; | ||
49 | } | ||
50 | |||
51 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP | 41 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP |
52 | static void ieee80211_dump_frame(const char *ifname, const char *title, | 42 | static void ieee80211_dump_frame(const char *ifname, const char *title, |
53 | const struct sk_buff *skb) | 43 | const struct sk_buff *skb) |
@@ -274,17 +264,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
274 | return TX_CONTINUE; | 264 | return TX_CONTINUE; |
275 | } | 265 | } |
276 | 266 | ||
277 | static ieee80211_tx_result debug_noinline | ||
278 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | ||
279 | { | ||
280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
281 | |||
282 | if (ieee80211_hdrlen(hdr->frame_control) >= 24) | ||
283 | ieee80211_include_sequence(tx->sdata, hdr); | ||
284 | |||
285 | return TX_CONTINUE; | ||
286 | } | ||
287 | |||
288 | /* This function is called whenever the AP is about to exceed the maximum limit | 267 | /* This function is called whenever the AP is about to exceed the maximum limit |
289 | * of buffered frames for power saving STAs. This situation should not really | 268 | * of buffered frames for power saving STAs. This situation should not really |
290 | * happen often during normal operation, so dropping the oldest buffered packet | 269 | * happen often during normal operation, so dropping the oldest buffered packet |
@@ -303,8 +282,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
303 | 282 | ||
304 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 283 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
305 | struct ieee80211_if_ap *ap; | 284 | struct ieee80211_if_ap *ap; |
306 | if (sdata->dev == local->mdev || | 285 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) |
307 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | ||
308 | continue; | 286 | continue; |
309 | ap = &sdata->u.ap; | 287 | ap = &sdata->u.ap; |
310 | skb = skb_dequeue(&ap->ps_bc_buf); | 288 | skb = skb_dequeue(&ap->ps_bc_buf); |
@@ -346,8 +324,12 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
346 | * This is done either by the hardware or us. | 324 | * This is done either by the hardware or us. |
347 | */ | 325 | */ |
348 | 326 | ||
349 | /* not AP/IBSS or ordered frame */ | 327 | /* powersaving STAs only in AP/VLAN mode */ |
350 | if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER)) | 328 | if (!tx->sdata->bss) |
329 | return TX_CONTINUE; | ||
330 | |||
331 | /* no buffering for ordered frames */ | ||
332 | if (tx->fc & IEEE80211_FCTL_ORDER) | ||
351 | return TX_CONTINUE; | 333 | return TX_CONTINUE; |
352 | 334 | ||
353 | /* no stations in PS mode */ | 335 | /* no stations in PS mode */ |
@@ -639,6 +621,49 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
639 | } | 621 | } |
640 | 622 | ||
641 | static ieee80211_tx_result debug_noinline | 623 | static ieee80211_tx_result debug_noinline |
624 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | ||
625 | { | ||
626 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
627 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
628 | u16 *seq; | ||
629 | u8 *qc; | ||
630 | int tid; | ||
631 | |||
632 | /* only for injected frames */ | ||
633 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | ||
634 | return TX_CONTINUE; | ||
635 | |||
636 | if (ieee80211_hdrlen(hdr->frame_control) < 24) | ||
637 | return TX_CONTINUE; | ||
638 | |||
639 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | ||
640 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
641 | return TX_CONTINUE; | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * This should be true for injected/management frames only, for | ||
646 | * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ | ||
647 | * above since they are not QoS-data frames. | ||
648 | */ | ||
649 | if (!tx->sta) | ||
650 | return TX_CONTINUE; | ||
651 | |||
652 | /* include per-STA, per-TID sequence counter */ | ||
653 | |||
654 | qc = ieee80211_get_qos_ctl(hdr); | ||
655 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | ||
656 | seq = &tx->sta->tid_seq[tid]; | ||
657 | |||
658 | hdr->seq_ctrl = cpu_to_le16(*seq); | ||
659 | |||
660 | /* Increase the sequence number. */ | ||
661 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; | ||
662 | |||
663 | return TX_CONTINUE; | ||
664 | } | ||
665 | |||
666 | static ieee80211_tx_result debug_noinline | ||
642 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 667 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
643 | { | 668 | { |
644 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
@@ -1107,12 +1132,12 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1107 | goto txh_done; | 1132 | goto txh_done; |
1108 | 1133 | ||
1109 | CALL_TXH(ieee80211_tx_h_check_assoc) | 1134 | CALL_TXH(ieee80211_tx_h_check_assoc) |
1110 | CALL_TXH(ieee80211_tx_h_sequence) | ||
1111 | CALL_TXH(ieee80211_tx_h_ps_buf) | 1135 | CALL_TXH(ieee80211_tx_h_ps_buf) |
1112 | CALL_TXH(ieee80211_tx_h_select_key) | 1136 | CALL_TXH(ieee80211_tx_h_select_key) |
1113 | CALL_TXH(ieee80211_tx_h_michael_mic_add) | 1137 | CALL_TXH(ieee80211_tx_h_michael_mic_add) |
1114 | CALL_TXH(ieee80211_tx_h_rate_ctrl) | 1138 | CALL_TXH(ieee80211_tx_h_rate_ctrl) |
1115 | CALL_TXH(ieee80211_tx_h_misc) | 1139 | CALL_TXH(ieee80211_tx_h_misc) |
1140 | CALL_TXH(ieee80211_tx_h_sequence) | ||
1116 | CALL_TXH(ieee80211_tx_h_fragment) | 1141 | CALL_TXH(ieee80211_tx_h_fragment) |
1117 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1142 | /* handlers after fragment must be aware of tx info fragmentation! */ |
1118 | CALL_TXH(ieee80211_tx_h_encrypt) | 1143 | CALL_TXH(ieee80211_tx_h_encrypt) |
@@ -1785,17 +1810,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1785 | struct ieee80211_vif *vif) | 1810 | struct ieee80211_vif *vif) |
1786 | { | 1811 | { |
1787 | struct ieee80211_local *local = hw_to_local(hw); | 1812 | struct ieee80211_local *local = hw_to_local(hw); |
1788 | struct sk_buff *skb; | 1813 | struct sk_buff *skb = NULL; |
1789 | struct ieee80211_tx_info *info; | 1814 | struct ieee80211_tx_info *info; |
1790 | struct net_device *bdev; | 1815 | struct net_device *bdev; |
1791 | struct ieee80211_sub_if_data *sdata = NULL; | 1816 | struct ieee80211_sub_if_data *sdata = NULL; |
1792 | struct ieee80211_if_ap *ap = NULL; | 1817 | struct ieee80211_if_ap *ap = NULL; |
1818 | struct ieee80211_if_sta *ifsta = NULL; | ||
1793 | struct rate_selection rsel; | 1819 | struct rate_selection rsel; |
1794 | struct beacon_data *beacon; | 1820 | struct beacon_data *beacon; |
1795 | struct ieee80211_supported_band *sband; | 1821 | struct ieee80211_supported_band *sband; |
1796 | struct ieee80211_mgmt *mgmt; | 1822 | struct ieee80211_mgmt *mgmt; |
1797 | int *num_beacons; | 1823 | int *num_beacons; |
1798 | bool err = true; | ||
1799 | enum ieee80211_band band = local->hw.conf.channel->band; | 1824 | enum ieee80211_band band = local->hw.conf.channel->band; |
1800 | u8 *pos; | 1825 | u8 *pos; |
1801 | 1826 | ||
@@ -1824,9 +1849,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1824 | memcpy(skb_put(skb, beacon->head_len), beacon->head, | 1849 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
1825 | beacon->head_len); | 1850 | beacon->head_len); |
1826 | 1851 | ||
1827 | ieee80211_include_sequence(sdata, | ||
1828 | (struct ieee80211_hdr *)skb->data); | ||
1829 | |||
1830 | /* | 1852 | /* |
1831 | * Not very nice, but we want to allow the driver to call | 1853 | * Not very nice, but we want to allow the driver to call |
1832 | * ieee80211_beacon_get() as a response to the set_tim() | 1854 | * ieee80211_beacon_get() as a response to the set_tim() |
@@ -1849,9 +1871,24 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1849 | beacon->tail, beacon->tail_len); | 1871 | beacon->tail, beacon->tail_len); |
1850 | 1872 | ||
1851 | num_beacons = &ap->num_beacons; | 1873 | num_beacons = &ap->num_beacons; |
1874 | } else | ||
1875 | goto out; | ||
1876 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
1877 | struct ieee80211_hdr *hdr; | ||
1878 | ifsta = &sdata->u.sta; | ||
1852 | 1879 | ||
1853 | err = false; | 1880 | if (!ifsta->probe_resp) |
1854 | } | 1881 | goto out; |
1882 | |||
1883 | skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); | ||
1884 | if (!skb) | ||
1885 | goto out; | ||
1886 | |||
1887 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1888 | hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1889 | IEEE80211_STYPE_BEACON); | ||
1890 | |||
1891 | num_beacons = &ifsta->num_beacons; | ||
1855 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1892 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1856 | /* headroom, head length, tail length and maximum TIM length */ | 1893 | /* headroom, head length, tail length and maximum TIM length */ |
1857 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1894 | skb = dev_alloc_skb(local->tx_headroom + 400); |
@@ -1878,17 +1915,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1878 | mesh_mgmt_ies_add(skb, sdata->dev); | 1915 | mesh_mgmt_ies_add(skb, sdata->dev); |
1879 | 1916 | ||
1880 | num_beacons = &sdata->u.sta.num_beacons; | 1917 | num_beacons = &sdata->u.sta.num_beacons; |
1881 | 1918 | } else { | |
1882 | err = false; | 1919 | WARN_ON(1); |
1883 | } | ||
1884 | |||
1885 | if (err) { | ||
1886 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1887 | if (net_ratelimit()) | ||
1888 | printk(KERN_DEBUG "no beacon data avail for %s\n", | ||
1889 | bdev->name); | ||
1890 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
1891 | skb = NULL; | ||
1892 | goto out; | 1920 | goto out; |
1893 | } | 1921 | } |
1894 | 1922 | ||
@@ -1910,14 +1938,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1910 | 1938 | ||
1911 | info->control.vif = vif; | 1939 | info->control.vif = vif; |
1912 | info->tx_rate_idx = rsel.rate_idx; | 1940 | info->tx_rate_idx = rsel.rate_idx; |
1941 | |||
1942 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1943 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
1944 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1945 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
1913 | if (sdata->bss_conf.use_short_preamble && | 1946 | if (sdata->bss_conf.use_short_preamble && |
1914 | sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | 1947 | sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) |
1915 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | 1948 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
1949 | |||
1916 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1950 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
1917 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1918 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
1919 | info->control.retry_limit = 1; | 1951 | info->control.retry_limit = 1; |
1920 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1952 | |
1921 | (*num_beacons)++; | 1953 | (*num_beacons)++; |
1922 | out: | 1954 | out: |
1923 | rcu_read_unlock(); | 1955 | rcu_read_unlock(); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ce62b163b82c..89ce4e07bd84 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -428,8 +428,6 @@ void ieee80211_iterate_active_interfaces( | |||
428 | case IEEE80211_IF_TYPE_MESH_POINT: | 428 | case IEEE80211_IF_TYPE_MESH_POINT: |
429 | break; | 429 | break; |
430 | } | 430 | } |
431 | if (sdata->dev == local->mdev) | ||
432 | continue; | ||
433 | if (netif_running(sdata->dev)) | 431 | if (netif_running(sdata->dev)) |
434 | iterator(data, sdata->dev->dev_addr, | 432 | iterator(data, sdata->dev->dev_addr, |
435 | &sdata->vif); | 433 | &sdata->vif); |
@@ -463,8 +461,6 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
463 | case IEEE80211_IF_TYPE_MESH_POINT: | 461 | case IEEE80211_IF_TYPE_MESH_POINT: |
464 | break; | 462 | break; |
465 | } | 463 | } |
466 | if (sdata->dev == local->mdev) | ||
467 | continue; | ||
468 | if (netif_running(sdata->dev)) | 464 | if (netif_running(sdata->dev)) |
469 | iterator(data, sdata->dev->dev_addr, | 465 | iterator(data, sdata->dev->dev_addr, |
470 | &sdata->vif); | 466 | &sdata->vif); |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 736c32e340f2..34fa8ed1e784 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -296,15 +296,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
299 | if (type == sdata->vif.type) | 299 | return ieee80211_if_change_type(sdata, type); |
300 | return 0; | ||
301 | if (netif_running(dev)) | ||
302 | return -EBUSY; | ||
303 | |||
304 | ieee80211_if_reinit(dev); | ||
305 | ieee80211_if_set_type(dev, type); | ||
306 | |||
307 | return 0; | ||
308 | } | 300 | } |
309 | 301 | ||
310 | 302 | ||
@@ -452,7 +444,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
452 | memset(sdata->u.ap.ssid + len, 0, | 444 | memset(sdata->u.ap.ssid + len, 0, |
453 | IEEE80211_MAX_SSID_LEN - len); | 445 | IEEE80211_MAX_SSID_LEN - len); |
454 | sdata->u.ap.ssid_len = len; | 446 | sdata->u.ap.ssid_len = len; |
455 | return ieee80211_if_config(dev); | 447 | return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); |
456 | } | 448 | } |
457 | return -EOPNOTSUPP; | 449 | return -EOPNOTSUPP; |
458 | } | 450 | } |
@@ -627,16 +619,14 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
627 | struct ieee80211_supported_band *sband; | 619 | struct ieee80211_supported_band *sband; |
628 | 620 | ||
629 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 621 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
630 | if (!sdata->bss) | ||
631 | return -ENODEV; | ||
632 | 622 | ||
633 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 623 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
634 | 624 | ||
635 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | 625 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates |
636 | * target_rate = X, rate->fixed = 1 means only rate X | 626 | * target_rate = X, rate->fixed = 1 means only rate X |
637 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | 627 | * target_rate = X, rate->fixed = 0 means all rates <= X */ |
638 | sdata->bss->max_ratectrl_rateidx = -1; | 628 | sdata->max_ratectrl_rateidx = -1; |
639 | sdata->bss->force_unicast_rateidx = -1; | 629 | sdata->force_unicast_rateidx = -1; |
640 | if (rate->value < 0) | 630 | if (rate->value < 0) |
641 | return 0; | 631 | return 0; |
642 | 632 | ||
@@ -645,9 +635,9 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
645 | int this_rate = brate->bitrate; | 635 | int this_rate = brate->bitrate; |
646 | 636 | ||
647 | if (target_rate == this_rate) { | 637 | if (target_rate == this_rate) { |
648 | sdata->bss->max_ratectrl_rateidx = i; | 638 | sdata->max_ratectrl_rateidx = i; |
649 | if (rate->fixed) | 639 | if (rate->fixed) |
650 | sdata->bss->force_unicast_rateidx = i; | 640 | sdata->force_unicast_rateidx = i; |
651 | err = 0; | 641 | err = 0; |
652 | break; | 642 | break; |
653 | } | 643 | } |
@@ -1009,6 +999,45 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
1009 | return 0; | 999 | return 0; |
1010 | } | 1000 | } |
1011 | 1001 | ||
1002 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | ||
1003 | struct iw_request_info *info, | ||
1004 | struct iw_param *wrq, | ||
1005 | char *extra) | ||
1006 | { | ||
1007 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1008 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1009 | |||
1010 | if (wrq->disabled) { | ||
1011 | conf->flags &= ~IEEE80211_CONF_PS; | ||
1012 | return ieee80211_hw_config(local); | ||
1013 | } | ||
1014 | |||
1015 | switch (wrq->flags & IW_POWER_MODE) { | ||
1016 | case IW_POWER_ON: /* If not specified */ | ||
1017 | case IW_POWER_MODE: /* If set all mask */ | ||
1018 | case IW_POWER_ALL_R: /* If explicitely state all */ | ||
1019 | conf->flags |= IEEE80211_CONF_PS; | ||
1020 | break; | ||
1021 | default: /* Otherwise we don't support it */ | ||
1022 | return -EINVAL; | ||
1023 | } | ||
1024 | |||
1025 | return ieee80211_hw_config(local); | ||
1026 | } | ||
1027 | |||
1028 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | ||
1029 | struct iw_request_info *info, | ||
1030 | union iwreq_data *wrqu, | ||
1031 | char *extra) | ||
1032 | { | ||
1033 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1034 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1035 | |||
1036 | wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); | ||
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1012 | static int ieee80211_ioctl_siwauth(struct net_device *dev, | 1041 | static int ieee80211_ioctl_siwauth(struct net_device *dev, |
1013 | struct iw_request_info *info, | 1042 | struct iw_request_info *info, |
1014 | struct iw_param *data, char *extra) | 1043 | struct iw_param *data, char *extra) |
@@ -1211,8 +1240,8 @@ static const iw_handler ieee80211_handler[] = | |||
1211 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ | 1240 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ |
1212 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ | 1241 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ |
1213 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ | 1242 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ |
1214 | (iw_handler) NULL, /* SIOCSIWPOWER */ | 1243 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ |
1215 | (iw_handler) NULL, /* SIOCGIWPOWER */ | 1244 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
1216 | (iw_handler) NULL, /* -- hole -- */ | 1245 | (iw_handler) NULL, /* -- hole -- */ |
1217 | (iw_handler) NULL, /* -- hole -- */ | 1246 | (iw_handler) NULL, /* -- hole -- */ |
1218 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ | 1247 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 79270903bda6..ab015c62d561 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -29,3 +29,14 @@ config WIRELESS_EXT | |||
29 | 29 | ||
30 | Say N (if you can) unless you know you need wireless | 30 | Say N (if you can) unless you know you need wireless |
31 | extensions for external modules. | 31 | extensions for external modules. |
32 | |||
33 | config WIRELESS_EXT_SYSFS | ||
34 | bool "Wireless extensions sysfs files" | ||
35 | default y | ||
36 | depends on WIRELESS_EXT && SYSFS | ||
37 | help | ||
38 | This option enables the deprecated wireless statistics | ||
39 | files in /sys/class/net/*/wireless/. The same information | ||
40 | is available via the ioctls as well. | ||
41 | |||
42 | Say Y if you have programs using it (we don't know of any). | ||