diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-25 19:34:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-25 19:34:56 -0500 |
commit | d346f49d0badd80aa9fc699fa9c6d5b23e778eb6 (patch) | |
tree | 9e9698ffe7966fbe7ce924a30843f87cdfa2646e | |
parent | d87fd25d5ac4cd044e21b749a8f6cac90f093c71 (diff) | |
parent | b6ce5c33001b1dc83e6a1a6f30c5dccccea651b6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
117 files changed, 2965 insertions, 1122 deletions
diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt index ee31369e9e5b..9551622d0a7b 100644 --- a/Documentation/networking/regulatory.txt +++ b/Documentation/networking/regulatory.txt | |||
@@ -188,3 +188,27 @@ Then in some part of your code after your wiphy has been registered: | |||
188 | &mydriver_jp_regdom.reg_rules[i], | 188 | &mydriver_jp_regdom.reg_rules[i], |
189 | sizeof(struct ieee80211_reg_rule)); | 189 | sizeof(struct ieee80211_reg_rule)); |
190 | regulatory_struct_hint(rd); | 190 | regulatory_struct_hint(rd); |
191 | |||
192 | Statically compiled regulatory database | ||
193 | --------------------------------------- | ||
194 | |||
195 | In most situations the userland solution using CRDA as described | ||
196 | above is the preferred solution. However in some cases a set of | ||
197 | rules built into the kernel itself may be desirable. To account | ||
198 | for this situation, a configuration option has been provided | ||
199 | (i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled, | ||
200 | the wireless database information contained in net/wireless/db.txt is | ||
201 | used to generate a data structure encoded in net/wireless/regdb.c. | ||
202 | That option also enables code in net/wireless/reg.c which queries | ||
203 | the data in regdb.c as an alternative to using CRDA. | ||
204 | |||
205 | The file net/wireless/db.txt should be kept up-to-date with the db.txt | ||
206 | file available in the git repository here: | ||
207 | |||
208 | git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git | ||
209 | |||
210 | Again, most users in most situations should be using the CRDA package | ||
211 | provided with their distribution, and in most other situations users | ||
212 | should be building and using CRDA on their own rather than using | ||
213 | this option. If you are not absolutely sure that you should be using | ||
214 | CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_. | ||
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 9f9459860d82..b99a8c2053d8 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -109,7 +109,6 @@ struct ar9170_rxstream_mpdu_merge { | |||
109 | bool has_plcp; | 109 | bool has_plcp; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define AR9170_NUM_MAX_BA_RETRY 5 | ||
113 | #define AR9170_NUM_TID 16 | 112 | #define AR9170_NUM_TID 16 |
114 | #define WME_BA_BMP_SIZE 64 | 113 | #define WME_BA_BMP_SIZE 64 |
115 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) | 114 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) |
@@ -143,7 +142,6 @@ struct ar9170_sta_tid { | |||
143 | u16 tid; | 142 | u16 tid; |
144 | enum ar9170_tid_state state; | 143 | enum ar9170_tid_state state; |
145 | bool active; | 144 | bool active; |
146 | u8 retry; | ||
147 | }; | 145 | }; |
148 | 146 | ||
149 | #define AR9170_QUEUE_TIMEOUT 64 | 147 | #define AR9170_QUEUE_TIMEOUT 64 |
@@ -154,6 +152,8 @@ struct ar9170_sta_tid { | |||
154 | 152 | ||
155 | #define AR9170_NUM_TX_STATUS 128 | 153 | #define AR9170_NUM_TX_STATUS 128 |
156 | #define AR9170_NUM_TX_AGG_MAX 30 | 154 | #define AR9170_NUM_TX_AGG_MAX 30 |
155 | #define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH | ||
156 | #define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) | ||
157 | 157 | ||
158 | struct ar9170 { | 158 | struct ar9170 { |
159 | struct ieee80211_hw *hw; | 159 | struct ieee80211_hw *hw; |
@@ -248,13 +248,8 @@ struct ar9170_sta_info { | |||
248 | unsigned int ampdu_max_len; | 248 | unsigned int ampdu_max_len; |
249 | }; | 249 | }; |
250 | 250 | ||
251 | #define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) | ||
252 | #define AR9170_TX_FLAG_NO_ACK BIT(1) | ||
253 | #define AR9170_TX_FLAG_BLOCK_ACK BIT(2) | ||
254 | |||
255 | struct ar9170_tx_info { | 251 | struct ar9170_tx_info { |
256 | unsigned long timeout; | 252 | unsigned long timeout; |
257 | unsigned int flags; | ||
258 | }; | 253 | }; |
259 | 254 | ||
260 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) | 255 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 701ddb7d8400..0a1d4c28e68a 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -276,6 +276,7 @@ struct ar9170_tx_control { | |||
276 | #define AR9170_TX_MAC_RATE_PROBE 0x8000 | 276 | #define AR9170_TX_MAC_RATE_PROBE 0x8000 |
277 | 277 | ||
278 | /* either-or */ | 278 | /* either-or */ |
279 | #define AR9170_TX_PHY_MOD_MASK 0x00000003 | ||
279 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 | 280 | #define AR9170_TX_PHY_MOD_CCK 0x00000000 |
280 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 | 281 | #define AR9170_TX_PHY_MOD_OFDM 0x00000001 |
281 | #define AR9170_TX_PHY_MOD_HT 0x00000002 | 282 | #define AR9170_TX_PHY_MOD_HT 0x00000002 |
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index ddc8c09dc79e..857e86104295 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c | |||
@@ -117,7 +117,7 @@ int ar9170_set_qos(struct ar9170 *ar) | |||
117 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, | 117 | ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, |
118 | ar->edcf[0].txop | ar->edcf[1].txop << 16); | 118 | ar->edcf[0].txop | ar->edcf[1].txop << 16); |
119 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, | 119 | ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, |
120 | ar->edcf[1].txop | ar->edcf[3].txop << 16); | 120 | ar->edcf[2].txop | ar->edcf[3].txop << 16); |
121 | 121 | ||
122 | ar9170_regwrite_finish(); | 122 | ar9170_regwrite_finish(); |
123 | 123 | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f9d6db8d013e..20f04ab2b13e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -194,12 +194,15 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) | |||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | 194 | return ar9170_get_seq_h((void *) txc->frame_data); |
195 | } | 195 | } |
196 | 196 | ||
197 | static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) | ||
198 | { | ||
199 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
200 | } | ||
201 | |||
197 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | 202 | static inline u16 ar9170_get_tid(struct sk_buff *skb) |
198 | { | 203 | { |
199 | struct ar9170_tx_control *txc = (void *) skb->data; | 204 | struct ar9170_tx_control *txc = (void *) skb->data; |
200 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 205 | return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); |
201 | |||
202 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
203 | } | 206 | } |
204 | 207 | ||
205 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | 208 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) |
@@ -213,10 +216,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | |||
213 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | 216 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; |
214 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 217 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; |
215 | 218 | ||
216 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " | 219 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " |
217 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | 220 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", |
218 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), | 221 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), |
219 | ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), | 222 | ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), |
220 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | 223 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), |
221 | jiffies_to_msecs(arinfo->timeout - jiffies)); | 224 | jiffies_to_msecs(arinfo->timeout - jiffies)); |
222 | } | 225 | } |
@@ -430,7 +433,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
430 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 433 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
431 | ar->tx_stats[queue].len--; | 434 | ar->tx_stats[queue].len--; |
432 | 435 | ||
433 | if (skb_queue_empty(&ar->tx_pending[queue])) { | 436 | if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { |
434 | #ifdef AR9170_QUEUE_STOP_DEBUG | 437 | #ifdef AR9170_QUEUE_STOP_DEBUG |
435 | printk(KERN_DEBUG "%s: wake queue %d\n", | 438 | printk(KERN_DEBUG "%s: wake queue %d\n", |
436 | wiphy_name(ar->hw->wiphy), queue); | 439 | wiphy_name(ar->hw->wiphy), queue); |
@@ -440,22 +443,17 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
440 | } | 443 | } |
441 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 444 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
442 | 445 | ||
443 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { | 446 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) { |
444 | ar9170_tx_ampdu_callback(ar, skb); | ||
445 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { | ||
446 | arinfo->timeout = jiffies + | ||
447 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | ||
448 | |||
449 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
450 | } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { | ||
451 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); | 447 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); |
452 | } else { | 448 | } else { |
453 | #ifdef AR9170_QUEUE_DEBUG | 449 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
454 | printk(KERN_DEBUG "%s: unsupported frame flags!\n", | 450 | ar9170_tx_ampdu_callback(ar, skb); |
455 | wiphy_name(ar->hw->wiphy)); | 451 | } else { |
456 | ar9170_print_txheader(ar, skb); | 452 | arinfo->timeout = jiffies + |
457 | #endif /* AR9170_QUEUE_DEBUG */ | 453 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
458 | dev_kfree_skb_any(skb); | 454 | |
455 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
456 | } | ||
459 | } | 457 | } |
460 | 458 | ||
461 | if (!ar->tx_stats[queue].len && | 459 | if (!ar->tx_stats[queue].len && |
@@ -1407,17 +1405,6 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1407 | 1405 | ||
1408 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 1406 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
1409 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { | 1407 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { |
1410 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1411 | if (unlikely(!info->control.sta)) | ||
1412 | goto err_out; | ||
1413 | |||
1414 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1415 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; | ||
1416 | |||
1417 | goto out; | ||
1418 | } | ||
1419 | |||
1420 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1421 | /* | 1408 | /* |
1422 | * WARNING: | 1409 | * WARNING: |
1423 | * Putting the QoS queue bits into an unexplored territory is | 1410 | * Putting the QoS queue bits into an unexplored territory is |
@@ -1431,12 +1418,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1431 | 1418 | ||
1432 | txc->phy_control |= | 1419 | txc->phy_control |= |
1433 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); | 1420 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); |
1434 | arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; | 1421 | |
1435 | } else { | 1422 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1436 | arinfo->flags = AR9170_TX_FLAG_NO_ACK; | 1423 | if (unlikely(!info->control.sta)) |
1424 | goto err_out; | ||
1425 | |||
1426 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1427 | } else { | ||
1428 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1429 | } | ||
1437 | } | 1430 | } |
1438 | 1431 | ||
1439 | out: | ||
1440 | return 0; | 1432 | return 0; |
1441 | 1433 | ||
1442 | err_out: | 1434 | err_out: |
@@ -1671,8 +1663,7 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar) | |||
1671 | * tell the FW/HW that this is the last frame, | 1663 | * tell the FW/HW that this is the last frame, |
1672 | * that way it will wait for the immediate block ack. | 1664 | * that way it will wait for the immediate block ack. |
1673 | */ | 1665 | */ |
1674 | if (likely(skb_peek_tail(&agg))) | 1666 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); |
1675 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1676 | 1667 | ||
1677 | #ifdef AR9170_TXAGG_DEBUG | 1668 | #ifdef AR9170_TXAGG_DEBUG |
1678 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | 1669 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", |
@@ -1716,6 +1707,21 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1716 | 1707 | ||
1717 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 1708 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
1718 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 1709 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
1710 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1711 | skb_queue_len(&ar->tx_pending[i])); | ||
1712 | |||
1713 | if (remaining_space < frames) { | ||
1714 | #ifdef AR9170_QUEUE_DEBUG | ||
1715 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1716 | "remaining slots:%d, needed:%d\n", | ||
1717 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1718 | frames); | ||
1719 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1720 | frames = remaining_space; | ||
1721 | } | ||
1722 | |||
1723 | ar->tx_stats[i].len += frames; | ||
1724 | ar->tx_stats[i].count += frames; | ||
1719 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | 1725 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { |
1720 | #ifdef AR9170_QUEUE_DEBUG | 1726 | #ifdef AR9170_QUEUE_DEBUG |
1721 | printk(KERN_DEBUG "%s: queue %d full\n", | 1727 | printk(KERN_DEBUG "%s: queue %d full\n", |
@@ -1733,25 +1739,8 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1733 | __ar9170_dump_txstats(ar); | 1739 | __ar9170_dump_txstats(ar); |
1734 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | 1740 | #endif /* AR9170_QUEUE_STOP_DEBUG */ |
1735 | ieee80211_stop_queue(ar->hw, i); | 1741 | ieee80211_stop_queue(ar->hw, i); |
1736 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
1737 | continue; | ||
1738 | } | 1742 | } |
1739 | 1743 | ||
1740 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1741 | skb_queue_len(&ar->tx_pending[i])); | ||
1742 | |||
1743 | if (remaining_space < frames) { | ||
1744 | #ifdef AR9170_QUEUE_DEBUG | ||
1745 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1746 | "remaining slots:%d, needed:%d\n", | ||
1747 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1748 | frames); | ||
1749 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1750 | frames = remaining_space; | ||
1751 | } | ||
1752 | |||
1753 | ar->tx_stats[i].len += frames; | ||
1754 | ar->tx_stats[i].count += frames; | ||
1755 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1744 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1756 | 1745 | ||
1757 | if (!frames) | 1746 | if (!frames) |
@@ -1773,7 +1762,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | arinfo->timeout = jiffies + | 1762 | arinfo->timeout = jiffies + |
1774 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1763 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1775 | 1764 | ||
1776 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1765 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1777 | atomic_inc(&ar->tx_ampdu_pending); | 1766 | atomic_inc(&ar->tx_ampdu_pending); |
1778 | 1767 | ||
1779 | #ifdef AR9170_QUEUE_DEBUG | 1768 | #ifdef AR9170_QUEUE_DEBUG |
@@ -1784,7 +1773,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1784 | 1773 | ||
1785 | err = ar->tx(ar, skb); | 1774 | err = ar->tx(ar, skb); |
1786 | if (unlikely(err)) { | 1775 | if (unlikely(err)) { |
1787 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1776 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1788 | atomic_dec(&ar->tx_ampdu_pending); | 1777 | atomic_dec(&ar->tx_ampdu_pending); |
1789 | 1778 | ||
1790 | frames_failed++; | 1779 | frames_failed++; |
@@ -2366,7 +2355,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, | |||
2366 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | 2355 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; |
2367 | sta_info->agg[i].active = false; | 2356 | sta_info->agg[i].active = false; |
2368 | sta_info->agg[i].ssn = 0; | 2357 | sta_info->agg[i].ssn = 0; |
2369 | sta_info->agg[i].retry = 0; | ||
2370 | sta_info->agg[i].tid = i; | 2358 | sta_info->agg[i].tid = i; |
2371 | INIT_LIST_HEAD(&sta_info->agg[i].list); | 2359 | INIT_LIST_HEAD(&sta_info->agg[i].list); |
2372 | skb_queue_head_init(&sta_info->agg[i].queue); | 2360 | skb_queue_head_init(&sta_info->agg[i].queue); |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e0799d924057..0f361186b78f 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -84,6 +84,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
84 | { USB_DEVICE(0x0cde, 0x0023) }, | 84 | { USB_DEVICE(0x0cde, 0x0023) }, |
85 | /* Z-Com UB82 ABG */ | 85 | /* Z-Com UB82 ABG */ |
86 | { USB_DEVICE(0x0cde, 0x0026) }, | 86 | { USB_DEVICE(0x0cde, 0x0026) }, |
87 | /* Sphairon Homelink 1202 */ | ||
88 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
87 | /* Arcadyan WN7512 */ | 89 | /* Arcadyan WN7512 */ |
88 | { USB_DEVICE(0x083a, 0xf522) }, | 90 | { USB_DEVICE(0x083a, 0xf522) }, |
89 | /* Planex GWUS300 */ | 91 | /* Planex GWUS300 */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index e2cef2ff5d8f..9f1f523e02eb 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -453,7 +453,6 @@ struct ath_softc { | |||
453 | int irq; | 453 | int irq; |
454 | spinlock_t sc_resetlock; | 454 | spinlock_t sc_resetlock; |
455 | spinlock_t sc_serial_rw; | 455 | spinlock_t sc_serial_rw; |
456 | spinlock_t ani_lock; | ||
457 | spinlock_t sc_pm_lock; | 456 | spinlock_t sc_pm_lock; |
458 | struct mutex mutex; | 457 | struct mutex mutex; |
459 | 458 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index b66f72dbf7b9..592f1b70f55a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -289,23 +289,49 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | |||
289 | if (sc->cur_rate_table == NULL) | 289 | if (sc->cur_rate_table == NULL) |
290 | return 0; | 290 | return 0; |
291 | 291 | ||
292 | max = 80 + sc->cur_rate_table->rate_cnt * 64; | 292 | max = 80 + sc->cur_rate_table->rate_cnt * 1024; |
293 | buf = kmalloc(max + 1, GFP_KERNEL); | 293 | buf = kmalloc(max + 1, GFP_KERNEL); |
294 | if (buf == NULL) | 294 | if (buf == NULL) |
295 | return 0; | 295 | return 0; |
296 | buf[max] = 0; | 296 | buf[max] = 0; |
297 | 297 | ||
298 | len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success", | 298 | len += sprintf(buf, "%6s %6s %6s " |
299 | "Retries", "XRetries", "PER"); | 299 | "%10s %10s %10s %10s\n", |
300 | "HT", "MCS", "Rate", | ||
301 | "Success", "Retries", "XRetries", "PER"); | ||
300 | 302 | ||
301 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { | 303 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { |
302 | u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; | 304 | u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; |
303 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; | 305 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; |
306 | char mcs[5]; | ||
307 | char htmode[5]; | ||
308 | int used_mcs = 0, used_htmode = 0; | ||
309 | |||
310 | if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { | ||
311 | used_mcs = snprintf(mcs, 5, "%d", | ||
312 | sc->cur_rate_table->info[i].ratecode); | ||
313 | |||
314 | if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) | ||
315 | used_htmode = snprintf(htmode, 5, "HT40"); | ||
316 | else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) | ||
317 | used_htmode = snprintf(htmode, 5, "HT20"); | ||
318 | else | ||
319 | used_htmode = snprintf(htmode, 5, "????"); | ||
320 | } | ||
321 | |||
322 | mcs[used_mcs] = '\0'; | ||
323 | htmode[used_htmode] = '\0'; | ||
304 | 324 | ||
305 | len += snprintf(buf + len, max - len, | 325 | len += snprintf(buf + len, max - len, |
306 | "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000, | 326 | "%6s %6s %3u.%d: " |
307 | (ratekbps % 1000) / 100, stats->success, | 327 | "%10u %10u %10u %10u\n", |
308 | stats->retries, stats->xretries, | 328 | htmode, |
329 | mcs, | ||
330 | ratekbps / 1000, | ||
331 | (ratekbps % 1000) / 100, | ||
332 | stats->success, | ||
333 | stats->retries, | ||
334 | stats->xretries, | ||
309 | stats->per); | 335 | stats->per); |
310 | } | 336 | } |
311 | 337 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2ec61f08cfdb..9474f9f6d400 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -343,30 +343,6 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
343 | return true; | 343 | return true; |
344 | } | 344 | } |
345 | 345 | ||
346 | static const char *ath9k_hw_devname(u16 devid) | ||
347 | { | ||
348 | switch (devid) { | ||
349 | case AR5416_DEVID_PCI: | ||
350 | return "Atheros 5416"; | ||
351 | case AR5416_DEVID_PCIE: | ||
352 | return "Atheros 5418"; | ||
353 | case AR9160_DEVID_PCI: | ||
354 | return "Atheros 9160"; | ||
355 | case AR5416_AR9100_DEVID: | ||
356 | return "Atheros 9100"; | ||
357 | case AR9280_DEVID_PCI: | ||
358 | case AR9280_DEVID_PCIE: | ||
359 | return "Atheros 9280"; | ||
360 | case AR9285_DEVID_PCIE: | ||
361 | return "Atheros 9285"; | ||
362 | case AR5416_DEVID_AR9287_PCI: | ||
363 | case AR5416_DEVID_AR9287_PCIE: | ||
364 | return "Atheros 9287"; | ||
365 | } | ||
366 | |||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | static void ath9k_hw_init_config(struct ath_hw *ah) | 346 | static void ath9k_hw_init_config(struct ath_hw *ah) |
371 | { | 347 | { |
372 | int i; | 348 | int i; |
@@ -392,7 +368,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
392 | ah->config.spurchans[i][1] = AR_NO_SPUR; | 368 | ah->config.spurchans[i][1] = AR_NO_SPUR; |
393 | } | 369 | } |
394 | 370 | ||
395 | ah->config.intr_mitigation = true; | 371 | ah->config.rx_intr_mitigation = true; |
396 | 372 | ||
397 | /* | 373 | /* |
398 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 374 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
@@ -1184,7 +1160,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1184 | AR_IMR_RXORN | | 1160 | AR_IMR_RXORN | |
1185 | AR_IMR_BCNMISC; | 1161 | AR_IMR_BCNMISC; |
1186 | 1162 | ||
1187 | if (ah->config.intr_mitigation) | 1163 | if (ah->config.rx_intr_mitigation) |
1188 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | 1164 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; |
1189 | else | 1165 | else |
1190 | ah->mask_reg |= AR_IMR_RXOK; | 1166 | ah->mask_reg |= AR_IMR_RXOK; |
@@ -1266,12 +1242,6 @@ static void ath9k_hw_init_user_settings(struct ath_hw *ah) | |||
1266 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); | 1242 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); |
1267 | } | 1243 | } |
1268 | 1244 | ||
1269 | const char *ath9k_hw_probe(u16 vendorid, u16 devid) | ||
1270 | { | ||
1271 | return vendorid == ATHEROS_VENDOR_ID ? | ||
1272 | ath9k_hw_devname(devid) : NULL; | ||
1273 | } | ||
1274 | |||
1275 | void ath9k_hw_detach(struct ath_hw *ah) | 1245 | void ath9k_hw_detach(struct ath_hw *ah) |
1276 | { | 1246 | { |
1277 | struct ath_common *common = ath9k_hw_common(ah); | 1247 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -2121,7 +2091,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2121 | 2091 | ||
2122 | REG_WRITE(ah, AR_OBS, 8); | 2092 | REG_WRITE(ah, AR_OBS, 8); |
2123 | 2093 | ||
2124 | if (ah->config.intr_mitigation) { | 2094 | if (ah->config.rx_intr_mitigation) { |
2125 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | 2095 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); |
2126 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); | 2096 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); |
2127 | } | 2097 | } |
@@ -2781,7 +2751,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
2781 | 2751 | ||
2782 | *masked = isr & ATH9K_INT_COMMON; | 2752 | *masked = isr & ATH9K_INT_COMMON; |
2783 | 2753 | ||
2784 | if (ah->config.intr_mitigation) { | 2754 | if (ah->config.rx_intr_mitigation) { |
2785 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | 2755 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) |
2786 | *masked |= ATH9K_INT_RX; | 2756 | *masked |= ATH9K_INT_RX; |
2787 | } | 2757 | } |
@@ -2914,7 +2884,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
2914 | } | 2884 | } |
2915 | if (ints & ATH9K_INT_RX) { | 2885 | if (ints & ATH9K_INT_RX) { |
2916 | mask |= AR_IMR_RXERR; | 2886 | mask |= AR_IMR_RXERR; |
2917 | if (ah->config.intr_mitigation) | 2887 | if (ah->config.rx_intr_mitigation) |
2918 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | 2888 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; |
2919 | else | 2889 | else |
2920 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | 2890 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e2b0c73a616f..8849450dc591 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -212,7 +212,7 @@ struct ath9k_ops_config { | |||
212 | u32 cck_trig_low; | 212 | u32 cck_trig_low; |
213 | u32 enable_ani; | 213 | u32 enable_ani; |
214 | int serialize_regmode; | 214 | int serialize_regmode; |
215 | bool intr_mitigation; | 215 | bool rx_intr_mitigation; |
216 | #define SPUR_DISABLE 0 | 216 | #define SPUR_DISABLE 0 |
217 | #define SPUR_ENABLE_IOCTL 1 | 217 | #define SPUR_ENABLE_IOCTL 1 |
218 | #define SPUR_ENABLE_EEPROM 2 | 218 | #define SPUR_ENABLE_EEPROM 2 |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9e68c1a8aef0..3f5b887d0fcd 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -363,14 +363,6 @@ static void ath_ani_calibrate(unsigned long data) | |||
363 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | 363 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
364 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 364 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
365 | 365 | ||
366 | /* | ||
367 | * don't calibrate when we're scanning. | ||
368 | * we are most likely not on our home channel. | ||
369 | */ | ||
370 | spin_lock(&sc->ani_lock); | ||
371 | if (sc->sc_flags & SC_OP_SCANNING) | ||
372 | goto set_timer; | ||
373 | |||
374 | /* Only calibrate if awake */ | 366 | /* Only calibrate if awake */ |
375 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | 367 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) |
376 | goto set_timer; | 368 | goto set_timer; |
@@ -437,7 +429,6 @@ static void ath_ani_calibrate(unsigned long data) | |||
437 | ath9k_ps_restore(sc); | 429 | ath9k_ps_restore(sc); |
438 | 430 | ||
439 | set_timer: | 431 | set_timer: |
440 | spin_unlock(&sc->ani_lock); | ||
441 | /* | 432 | /* |
442 | * Set timer interval based on previous results. | 433 | * Set timer interval based on previous results. |
443 | * The interval must be the shortest necessary to satisfy ANI, | 434 | * The interval must be the shortest necessary to satisfy ANI, |
@@ -1610,7 +1601,6 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
1610 | spin_lock_init(&sc->wiphy_lock); | 1601 | spin_lock_init(&sc->wiphy_lock); |
1611 | spin_lock_init(&sc->sc_resetlock); | 1602 | spin_lock_init(&sc->sc_resetlock); |
1612 | spin_lock_init(&sc->sc_serial_rw); | 1603 | spin_lock_init(&sc->sc_serial_rw); |
1613 | spin_lock_init(&sc->ani_lock); | ||
1614 | spin_lock_init(&sc->sc_pm_lock); | 1604 | spin_lock_init(&sc->sc_pm_lock); |
1615 | mutex_init(&sc->mutex); | 1605 | mutex_init(&sc->mutex); |
1616 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | 1606 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); |
@@ -3119,6 +3109,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3119 | { | 3109 | { |
3120 | struct ath_wiphy *aphy = hw->priv; | 3110 | struct ath_wiphy *aphy = hw->priv; |
3121 | struct ath_softc *sc = aphy->sc; | 3111 | struct ath_softc *sc = aphy->sc; |
3112 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3122 | 3113 | ||
3123 | mutex_lock(&sc->mutex); | 3114 | mutex_lock(&sc->mutex); |
3124 | if (ath9k_wiphy_scanning(sc)) { | 3115 | if (ath9k_wiphy_scanning(sc)) { |
@@ -3134,10 +3125,9 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3134 | 3125 | ||
3135 | aphy->state = ATH_WIPHY_SCAN; | 3126 | aphy->state = ATH_WIPHY_SCAN; |
3136 | ath9k_wiphy_pause_all_forced(sc, aphy); | 3127 | ath9k_wiphy_pause_all_forced(sc, aphy); |
3137 | |||
3138 | spin_lock_bh(&sc->ani_lock); | ||
3139 | sc->sc_flags |= SC_OP_SCANNING; | 3128 | sc->sc_flags |= SC_OP_SCANNING; |
3140 | spin_unlock_bh(&sc->ani_lock); | 3129 | del_timer_sync(&common->ani.timer); |
3130 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
3141 | mutex_unlock(&sc->mutex); | 3131 | mutex_unlock(&sc->mutex); |
3142 | } | 3132 | } |
3143 | 3133 | ||
@@ -3145,13 +3135,14 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3145 | { | 3135 | { |
3146 | struct ath_wiphy *aphy = hw->priv; | 3136 | struct ath_wiphy *aphy = hw->priv; |
3147 | struct ath_softc *sc = aphy->sc; | 3137 | struct ath_softc *sc = aphy->sc; |
3138 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3148 | 3139 | ||
3149 | mutex_lock(&sc->mutex); | 3140 | mutex_lock(&sc->mutex); |
3150 | spin_lock_bh(&sc->ani_lock); | ||
3151 | aphy->state = ATH_WIPHY_ACTIVE; | 3141 | aphy->state = ATH_WIPHY_ACTIVE; |
3152 | sc->sc_flags &= ~SC_OP_SCANNING; | 3142 | sc->sc_flags &= ~SC_OP_SCANNING; |
3153 | sc->sc_flags |= SC_OP_FULL_RESET; | 3143 | sc->sc_flags |= SC_OP_FULL_RESET; |
3154 | spin_unlock_bh(&sc->ani_lock); | 3144 | ath_start_ani(common); |
3145 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
3155 | ath_beacon_config(sc, NULL); | 3146 | ath_beacon_config(sc, NULL); |
3156 | mutex_unlock(&sc->mutex); | 3147 | mutex_unlock(&sc->mutex); |
3157 | } | 3148 | } |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 9eb96f506998..4f6d6fd442f4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -57,6 +57,10 @@ enum { | |||
57 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 57 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
58 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ | 58 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ |
59 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) | 59 | || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) |
60 | #define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \ | ||
61 | || (_phy == WLAN_RC_PHY_HT_20_DS) \ | ||
62 | || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ | ||
63 | || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)) | ||
60 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ | 64 | #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ |
61 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 65 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
62 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ | 66 | || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ff9b5c882184..d70732819423 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -2618,6 +2618,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) | |||
2618 | int events = 0; | 2618 | int events = 0; |
2619 | u16 ev; | 2619 | u16 ev; |
2620 | 2620 | ||
2621 | /* Detect early interrupt before driver is fully configued */ | ||
2622 | if (!dev->base_addr) { | ||
2623 | if (net_ratelimit()) { | ||
2624 | printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", | ||
2625 | dev->name); | ||
2626 | } | ||
2627 | return IRQ_HANDLED; | ||
2628 | } | ||
2629 | |||
2621 | iface = netdev_priv(dev); | 2630 | iface = netdev_priv(dev); |
2622 | local = iface->local; | 2631 | local = iface->local; |
2623 | 2632 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8414178bcff4..0db1fda94a65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -105,6 +105,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
105 | .load_ucode = iwl5000_load_ucode, | 105 | .load_ucode = iwl5000_load_ucode, |
106 | .dump_nic_event_log = iwl_dump_nic_event_log, | 106 | .dump_nic_event_log = iwl_dump_nic_event_log, |
107 | .dump_nic_error_log = iwl_dump_nic_error_log, | 107 | .dump_nic_error_log = iwl_dump_nic_error_log, |
108 | .dump_csr = iwl_dump_csr, | ||
108 | .init_alive_start = iwl5000_init_alive_start, | 109 | .init_alive_start = iwl5000_init_alive_start, |
109 | .alive_notify = iwl5000_alive_notify, | 110 | .alive_notify = iwl5000_alive_notify, |
110 | .send_tx_power = iwl5000_send_tx_power, | 111 | .send_tx_power = iwl5000_send_tx_power, |
@@ -140,7 +141,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
140 | }, | 141 | }, |
141 | }; | 142 | }; |
142 | 143 | ||
143 | static struct iwl_ops iwl1000_ops = { | 144 | static const struct iwl_ops iwl1000_ops = { |
144 | .ucode = &iwl5000_ucode, | 145 | .ucode = &iwl5000_ucode, |
145 | .lib = &iwl1000_lib, | 146 | .lib = &iwl1000_lib, |
146 | .hcmd = &iwl5000_hcmd, | 147 | .hcmd = &iwl5000_hcmd, |
@@ -173,7 +174,6 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
173 | .use_rts_for_ht = true, /* use rts/cts protection */ | 174 | .use_rts_for_ht = true, /* use rts/cts protection */ |
174 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 175 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
175 | .support_ct_kill_exit = true, | 176 | .support_ct_kill_exit = true, |
176 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
177 | }; | 177 | }; |
178 | 178 | ||
179 | struct iwl_cfg iwl1000_bg_cfg = { | 179 | struct iwl_cfg iwl1000_bg_cfg = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e413bd35bc41..d1bab141508a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -2810,7 +2810,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | |||
2810 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2810 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2811 | }; | 2811 | }; |
2812 | 2812 | ||
2813 | static struct iwl_ops iwl3945_ops = { | 2813 | static const struct iwl_ops iwl3945_ops = { |
2814 | .ucode = &iwl3945_ucode, | 2814 | .ucode = &iwl3945_ucode, |
2815 | .lib = &iwl3945_lib, | 2815 | .lib = &iwl3945_lib, |
2816 | .hcmd = &iwl3945_hcmd, | 2816 | .hcmd = &iwl3945_hcmd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ecc23ec1f6a4..28f6eb5f2cba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -227,7 +227,8 @@ extern void iwl3945_rx_replenish(void *data); | |||
227 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 227 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
228 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 228 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
229 | struct ieee80211_hdr *hdr,int left); | 229 | struct ieee80211_hdr *hdr,int left); |
230 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 230 | extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
231 | char **buf, bool display); | ||
231 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 232 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
232 | 233 | ||
233 | /* | 234 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 484c5fdf7c2a..78706ce8b7ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2208,7 +2208,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2208 | }, | 2208 | }, |
2209 | }; | 2209 | }; |
2210 | 2210 | ||
2211 | static struct iwl_ops iwl4965_ops = { | 2211 | static const struct iwl_ops iwl4965_ops = { |
2212 | .ucode = &iwl4965_ucode, | 2212 | .ucode = &iwl4965_ucode, |
2213 | .lib = &iwl4965_lib, | 2213 | .lib = &iwl4965_lib, |
2214 | .hcmd = &iwl4965_hcmd, | 2214 | .hcmd = &iwl4965_hcmd, |
@@ -2239,7 +2239,6 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2239 | .broken_powersave = true, | 2239 | .broken_powersave = true, |
2240 | .led_compensation = 61, | 2240 | .led_compensation = 61, |
2241 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2241 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2242 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
2243 | }; | 2242 | }; |
2244 | 2243 | ||
2245 | /* Module firmware */ | 2244 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 33a5866538e7..ec6b27689fa8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -1466,6 +1466,7 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1466 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1466 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1467 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1467 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1468 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1468 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1469 | .dump_csr = iwl_dump_csr, | ||
1469 | .load_ucode = iwl5000_load_ucode, | 1470 | .load_ucode = iwl5000_load_ucode, |
1470 | .init_alive_start = iwl5000_init_alive_start, | 1471 | .init_alive_start = iwl5000_init_alive_start, |
1471 | .alive_notify = iwl5000_alive_notify, | 1472 | .alive_notify = iwl5000_alive_notify, |
@@ -1518,6 +1519,7 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1518 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 1519 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, |
1519 | .dump_nic_event_log = iwl_dump_nic_event_log, | 1520 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1520 | .dump_nic_error_log = iwl_dump_nic_error_log, | 1521 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1522 | .dump_csr = iwl_dump_csr, | ||
1521 | .load_ucode = iwl5000_load_ucode, | 1523 | .load_ucode = iwl5000_load_ucode, |
1522 | .init_alive_start = iwl5000_init_alive_start, | 1524 | .init_alive_start = iwl5000_init_alive_start, |
1523 | .alive_notify = iwl5000_alive_notify, | 1525 | .alive_notify = iwl5000_alive_notify, |
@@ -1555,7 +1557,7 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1555 | }, | 1557 | }, |
1556 | }; | 1558 | }; |
1557 | 1559 | ||
1558 | static struct iwl_ops iwl5000_ops = { | 1560 | static const struct iwl_ops iwl5000_ops = { |
1559 | .ucode = &iwl5000_ucode, | 1561 | .ucode = &iwl5000_ucode, |
1560 | .lib = &iwl5000_lib, | 1562 | .lib = &iwl5000_lib, |
1561 | .hcmd = &iwl5000_hcmd, | 1563 | .hcmd = &iwl5000_hcmd, |
@@ -1563,7 +1565,7 @@ static struct iwl_ops iwl5000_ops = { | |||
1563 | .led = &iwlagn_led_ops, | 1565 | .led = &iwlagn_led_ops, |
1564 | }; | 1566 | }; |
1565 | 1567 | ||
1566 | static struct iwl_ops iwl5150_ops = { | 1568 | static const struct iwl_ops iwl5150_ops = { |
1567 | .ucode = &iwl5000_ucode, | 1569 | .ucode = &iwl5000_ucode, |
1568 | .lib = &iwl5150_lib, | 1570 | .lib = &iwl5150_lib, |
1569 | .hcmd = &iwl5000_hcmd, | 1571 | .hcmd = &iwl5000_hcmd, |
@@ -1599,7 +1601,6 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1599 | .ht_greenfield_support = true, | 1601 | .ht_greenfield_support = true, |
1600 | .led_compensation = 51, | 1602 | .led_compensation = 51, |
1601 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1603 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1602 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1603 | }; | 1604 | }; |
1604 | 1605 | ||
1605 | struct iwl_cfg iwl5100_bgn_cfg = { | 1606 | struct iwl_cfg iwl5100_bgn_cfg = { |
@@ -1668,7 +1669,6 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1668 | .ht_greenfield_support = true, | 1669 | .ht_greenfield_support = true, |
1669 | .led_compensation = 51, | 1670 | .led_compensation = 51, |
1670 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1671 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1671 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1672 | }; | 1672 | }; |
1673 | 1673 | ||
1674 | struct iwl_cfg iwl5350_agn_cfg = { | 1674 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1692,7 +1692,6 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1692 | .ht_greenfield_support = true, | 1692 | .ht_greenfield_support = true, |
1693 | .led_compensation = 51, | 1693 | .led_compensation = 51, |
1694 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1694 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1695 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1696 | }; | 1695 | }; |
1697 | 1696 | ||
1698 | struct iwl_cfg iwl5150_agn_cfg = { | 1697 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1716,7 +1715,6 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1716 | .ht_greenfield_support = true, | 1715 | .ht_greenfield_support = true, |
1717 | .led_compensation = 51, | 1716 | .led_compensation = 51, |
1718 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1717 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1719 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1720 | }; | 1718 | }; |
1721 | 1719 | ||
1722 | struct iwl_cfg iwl5150_abg_cfg = { | 1720 | struct iwl_cfg iwl5150_abg_cfg = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 74e571049273..a5a0ed4817a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -215,6 +215,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
215 | .load_ucode = iwl5000_load_ucode, | 215 | .load_ucode = iwl5000_load_ucode, |
216 | .dump_nic_event_log = iwl_dump_nic_event_log, | 216 | .dump_nic_event_log = iwl_dump_nic_event_log, |
217 | .dump_nic_error_log = iwl_dump_nic_error_log, | 217 | .dump_nic_error_log = iwl_dump_nic_error_log, |
218 | .dump_csr = iwl_dump_csr, | ||
218 | .init_alive_start = iwl5000_init_alive_start, | 219 | .init_alive_start = iwl5000_init_alive_start, |
219 | .alive_notify = iwl5000_alive_notify, | 220 | .alive_notify = iwl5000_alive_notify, |
220 | .send_tx_power = iwl5000_send_tx_power, | 221 | .send_tx_power = iwl5000_send_tx_power, |
@@ -252,7 +253,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
252 | }, | 253 | }, |
253 | }; | 254 | }; |
254 | 255 | ||
255 | static struct iwl_ops iwl6000_ops = { | 256 | static const struct iwl_ops iwl6000_ops = { |
256 | .ucode = &iwl5000_ucode, | 257 | .ucode = &iwl5000_ucode, |
257 | .lib = &iwl6000_lib, | 258 | .lib = &iwl6000_lib, |
258 | .hcmd = &iwl5000_hcmd, | 259 | .hcmd = &iwl5000_hcmd, |
@@ -267,7 +268,7 @@ static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = { | |||
267 | .calc_rssi = iwl5000_calc_rssi, | 268 | .calc_rssi = iwl5000_calc_rssi, |
268 | }; | 269 | }; |
269 | 270 | ||
270 | static struct iwl_ops iwl6050_ops = { | 271 | static const struct iwl_ops iwl6050_ops = { |
271 | .ucode = &iwl5000_ucode, | 272 | .ucode = &iwl5000_ucode, |
272 | .lib = &iwl6000_lib, | 273 | .lib = &iwl6000_lib, |
273 | .hcmd = &iwl5000_hcmd, | 274 | .hcmd = &iwl5000_hcmd, |
@@ -306,7 +307,6 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
306 | .supports_idle = true, | 307 | .supports_idle = true, |
307 | .adv_thermal_throttle = true, | 308 | .adv_thermal_throttle = true, |
308 | .support_ct_kill_exit = true, | 309 | .support_ct_kill_exit = true, |
309 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
310 | }; | 310 | }; |
311 | 311 | ||
312 | struct iwl_cfg iwl6000i_2abg_cfg = { | 312 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -395,7 +395,6 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
395 | .supports_idle = true, | 395 | .supports_idle = true, |
396 | .adv_thermal_throttle = true, | 396 | .adv_thermal_throttle = true, |
397 | .support_ct_kill_exit = true, | 397 | .support_ct_kill_exit = true, |
398 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC, | ||
399 | }; | 398 | }; |
400 | 399 | ||
401 | struct iwl_cfg iwl6050_2abg_cfg = { | 400 | struct iwl_cfg iwl6050_2abg_cfg = { |
@@ -455,7 +454,6 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
455 | .supports_idle = true, | 454 | .supports_idle = true, |
456 | .adv_thermal_throttle = true, | 455 | .adv_thermal_throttle = true, |
457 | .support_ct_kill_exit = true, | 456 | .support_ct_kill_exit = true, |
458 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
459 | }; | 457 | }; |
460 | 458 | ||
461 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 459 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1c9866daf815..771b03c1c7c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -657,6 +657,131 @@ static void iwl_bg_statistics_periodic(unsigned long data) | |||
657 | iwl_send_statistics_request(priv, CMD_ASYNC, false); | 657 | iwl_send_statistics_request(priv, CMD_ASYNC, false); |
658 | } | 658 | } |
659 | 659 | ||
660 | |||
661 | static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, | ||
662 | u32 start_idx, u32 num_events, | ||
663 | u32 mode) | ||
664 | { | ||
665 | u32 i; | ||
666 | u32 ptr; /* SRAM byte address of log data */ | ||
667 | u32 ev, time, data; /* event log data */ | ||
668 | unsigned long reg_flags; | ||
669 | |||
670 | if (mode == 0) | ||
671 | ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32)); | ||
672 | else | ||
673 | ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); | ||
674 | |||
675 | /* Make sure device is powered up for SRAM reads */ | ||
676 | spin_lock_irqsave(&priv->reg_lock, reg_flags); | ||
677 | if (iwl_grab_nic_access(priv)) { | ||
678 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
679 | return; | ||
680 | } | ||
681 | |||
682 | /* Set starting address; reads will auto-increment */ | ||
683 | _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); | ||
684 | rmb(); | ||
685 | |||
686 | /* | ||
687 | * "time" is actually "data" for mode 0 (no timestamp). | ||
688 | * place event id # at far right for easier visual parsing. | ||
689 | */ | ||
690 | for (i = 0; i < num_events; i++) { | ||
691 | ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
692 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
693 | if (mode == 0) { | ||
694 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
695 | 0, time, ev); | ||
696 | } else { | ||
697 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | ||
698 | trace_iwlwifi_dev_ucode_cont_event(priv, | ||
699 | time, data, ev); | ||
700 | } | ||
701 | } | ||
702 | /* Allow device to power down */ | ||
703 | iwl_release_nic_access(priv); | ||
704 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | ||
705 | } | ||
706 | |||
707 | void iwl_continuous_event_trace(struct iwl_priv *priv) | ||
708 | { | ||
709 | u32 capacity; /* event log capacity in # entries */ | ||
710 | u32 base; /* SRAM byte address of event log header */ | ||
711 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
712 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
713 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
714 | |||
715 | if (priv->ucode_type == UCODE_INIT) | ||
716 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | ||
717 | else | ||
718 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | ||
719 | if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { | ||
720 | capacity = iwl_read_targ_mem(priv, base); | ||
721 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | ||
722 | mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); | ||
723 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | ||
724 | } else | ||
725 | return; | ||
726 | |||
727 | if (num_wraps == priv->event_log.num_wraps) { | ||
728 | iwl_print_cont_event_trace(priv, | ||
729 | base, priv->event_log.next_entry, | ||
730 | next_entry - priv->event_log.next_entry, | ||
731 | mode); | ||
732 | priv->event_log.non_wraps_count++; | ||
733 | } else { | ||
734 | if ((num_wraps - priv->event_log.num_wraps) > 1) | ||
735 | priv->event_log.wraps_more_count++; | ||
736 | else | ||
737 | priv->event_log.wraps_once_count++; | ||
738 | trace_iwlwifi_dev_ucode_wrap_event(priv, | ||
739 | num_wraps - priv->event_log.num_wraps, | ||
740 | next_entry, priv->event_log.next_entry); | ||
741 | if (next_entry < priv->event_log.next_entry) { | ||
742 | iwl_print_cont_event_trace(priv, base, | ||
743 | priv->event_log.next_entry, | ||
744 | capacity - priv->event_log.next_entry, | ||
745 | mode); | ||
746 | |||
747 | iwl_print_cont_event_trace(priv, base, 0, | ||
748 | next_entry, mode); | ||
749 | } else { | ||
750 | iwl_print_cont_event_trace(priv, base, | ||
751 | next_entry, capacity - next_entry, | ||
752 | mode); | ||
753 | |||
754 | iwl_print_cont_event_trace(priv, base, 0, | ||
755 | next_entry, mode); | ||
756 | } | ||
757 | } | ||
758 | priv->event_log.num_wraps = num_wraps; | ||
759 | priv->event_log.next_entry = next_entry; | ||
760 | } | ||
761 | |||
762 | /** | ||
763 | * iwl_bg_ucode_trace - Timer callback to log ucode event | ||
764 | * | ||
765 | * The timer is continually set to execute every | ||
766 | * UCODE_TRACE_PERIOD milliseconds after the last timer expired | ||
767 | * this function is to perform continuous uCode event logging operation | ||
768 | * if enabled | ||
769 | */ | ||
770 | static void iwl_bg_ucode_trace(unsigned long data) | ||
771 | { | ||
772 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
773 | |||
774 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
775 | return; | ||
776 | |||
777 | if (priv->event_log.ucode_trace) { | ||
778 | iwl_continuous_event_trace(priv); | ||
779 | /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */ | ||
780 | mod_timer(&priv->ucode_trace, | ||
781 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
782 | } | ||
783 | } | ||
784 | |||
660 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 785 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
661 | struct iwl_rx_mem_buffer *rxb) | 786 | struct iwl_rx_mem_buffer *rxb) |
662 | { | 787 | { |
@@ -689,12 +814,14 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
689 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 814 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
690 | unsigned long status = priv->status; | 815 | unsigned long status = priv->status; |
691 | 816 | ||
692 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", | 817 | IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", |
693 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", | 818 | (flags & HW_CARD_DISABLED) ? "Kill" : "On", |
694 | (flags & SW_CARD_DISABLED) ? "Kill" : "On"); | 819 | (flags & SW_CARD_DISABLED) ? "Kill" : "On", |
820 | (flags & CT_CARD_DISABLED) ? | ||
821 | "Reached" : "Not reached"); | ||
695 | 822 | ||
696 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | | 823 | if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | |
697 | RF_CARD_DISABLED)) { | 824 | CT_CARD_DISABLED)) { |
698 | 825 | ||
699 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | 826 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, |
700 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | 827 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); |
@@ -708,10 +835,10 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, | |||
708 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, | 835 | iwl_write_direct32(priv, HBUS_TARG_MBX_C, |
709 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); | 836 | HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); |
710 | } | 837 | } |
711 | if (flags & RF_CARD_DISABLED) | 838 | if (flags & CT_CARD_DISABLED) |
712 | iwl_tt_enter_ct_kill(priv); | 839 | iwl_tt_enter_ct_kill(priv); |
713 | } | 840 | } |
714 | if (!(flags & RF_CARD_DISABLED)) | 841 | if (!(flags & CT_CARD_DISABLED)) |
715 | iwl_tt_exit_ct_kill(priv); | 842 | iwl_tt_exit_ct_kill(priv); |
716 | 843 | ||
717 | if (flags & HW_CARD_DISABLED) | 844 | if (flags & HW_CARD_DISABLED) |
@@ -1705,8 +1832,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1705 | * iwl_print_event_log - Dump error event log to syslog | 1832 | * iwl_print_event_log - Dump error event log to syslog |
1706 | * | 1833 | * |
1707 | */ | 1834 | */ |
1708 | static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1835 | static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1709 | u32 num_events, u32 mode) | 1836 | u32 num_events, u32 mode, |
1837 | int pos, char **buf, size_t bufsz) | ||
1710 | { | 1838 | { |
1711 | u32 i; | 1839 | u32 i; |
1712 | u32 base; /* SRAM byte address of event log header */ | 1840 | u32 base; /* SRAM byte address of event log header */ |
@@ -1716,7 +1844,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1716 | unsigned long reg_flags; | 1844 | unsigned long reg_flags; |
1717 | 1845 | ||
1718 | if (num_events == 0) | 1846 | if (num_events == 0) |
1719 | return; | 1847 | return pos; |
1720 | if (priv->ucode_type == UCODE_INIT) | 1848 | if (priv->ucode_type == UCODE_INIT) |
1721 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1849 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
1722 | else | 1850 | else |
@@ -1744,27 +1872,44 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1744 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1872 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1745 | if (mode == 0) { | 1873 | if (mode == 0) { |
1746 | /* data, ev */ | 1874 | /* data, ev */ |
1747 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1875 | if (bufsz) { |
1748 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | 1876 | pos += scnprintf(*buf + pos, bufsz - pos, |
1877 | "EVT_LOG:0x%08x:%04u\n", | ||
1878 | time, ev); | ||
1879 | } else { | ||
1880 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1881 | time, ev); | ||
1882 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", | ||
1883 | time, ev); | ||
1884 | } | ||
1749 | } else { | 1885 | } else { |
1750 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1886 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1751 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | 1887 | if (bufsz) { |
1888 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1889 | "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1890 | time, data, ev); | ||
1891 | } else { | ||
1892 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1752 | time, data, ev); | 1893 | time, data, ev); |
1753 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1894 | trace_iwlwifi_dev_ucode_event(priv, time, |
1895 | data, ev); | ||
1896 | } | ||
1754 | } | 1897 | } |
1755 | } | 1898 | } |
1756 | 1899 | ||
1757 | /* Allow device to power down */ | 1900 | /* Allow device to power down */ |
1758 | iwl_release_nic_access(priv); | 1901 | iwl_release_nic_access(priv); |
1759 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1902 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1903 | return pos; | ||
1760 | } | 1904 | } |
1761 | 1905 | ||
1762 | /** | 1906 | /** |
1763 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | 1907 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog |
1764 | */ | 1908 | */ |
1765 | static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | 1909 | static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, |
1766 | u32 num_wraps, u32 next_entry, | 1910 | u32 num_wraps, u32 next_entry, |
1767 | u32 size, u32 mode) | 1911 | u32 size, u32 mode, |
1912 | int pos, char **buf, size_t bufsz) | ||
1768 | { | 1913 | { |
1769 | /* | 1914 | /* |
1770 | * display the newest DEFAULT_LOG_ENTRIES entries | 1915 | * display the newest DEFAULT_LOG_ENTRIES entries |
@@ -1772,21 +1917,26 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1772 | */ | 1917 | */ |
1773 | if (num_wraps) { | 1918 | if (num_wraps) { |
1774 | if (next_entry < size) { | 1919 | if (next_entry < size) { |
1775 | iwl_print_event_log(priv, | 1920 | pos = iwl_print_event_log(priv, |
1776 | capacity - (size - next_entry), | 1921 | capacity - (size - next_entry), |
1777 | size - next_entry, mode); | 1922 | size - next_entry, mode, |
1778 | iwl_print_event_log(priv, 0, | 1923 | pos, buf, bufsz); |
1779 | next_entry, mode); | 1924 | pos = iwl_print_event_log(priv, 0, |
1925 | next_entry, mode, | ||
1926 | pos, buf, bufsz); | ||
1780 | } else | 1927 | } else |
1781 | iwl_print_event_log(priv, next_entry - size, | 1928 | pos = iwl_print_event_log(priv, next_entry - size, |
1782 | size, mode); | 1929 | size, mode, pos, buf, bufsz); |
1783 | } else { | 1930 | } else { |
1784 | if (next_entry < size) | 1931 | if (next_entry < size) { |
1785 | iwl_print_event_log(priv, 0, next_entry, mode); | 1932 | pos = iwl_print_event_log(priv, 0, next_entry, |
1786 | else | 1933 | mode, pos, buf, bufsz); |
1787 | iwl_print_event_log(priv, next_entry - size, | 1934 | } else { |
1788 | size, mode); | 1935 | pos = iwl_print_event_log(priv, next_entry - size, |
1936 | size, mode, pos, buf, bufsz); | ||
1937 | } | ||
1789 | } | 1938 | } |
1939 | return pos; | ||
1790 | } | 1940 | } |
1791 | 1941 | ||
1792 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1942 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
@@ -1794,7 +1944,8 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1794 | 1944 | ||
1795 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | 1945 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1796 | 1946 | ||
1797 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | 1947 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
1948 | char **buf, bool display) | ||
1798 | { | 1949 | { |
1799 | u32 base; /* SRAM byte address of event log header */ | 1950 | u32 base; /* SRAM byte address of event log header */ |
1800 | u32 capacity; /* event log capacity in # entries */ | 1951 | u32 capacity; /* event log capacity in # entries */ |
@@ -1802,6 +1953,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1802 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1953 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1803 | u32 next_entry; /* index of next entry to be written by uCode */ | 1954 | u32 next_entry; /* index of next entry to be written by uCode */ |
1804 | u32 size; /* # entries that we'll print */ | 1955 | u32 size; /* # entries that we'll print */ |
1956 | int pos = 0; | ||
1957 | size_t bufsz = 0; | ||
1805 | 1958 | ||
1806 | if (priv->ucode_type == UCODE_INIT) | 1959 | if (priv->ucode_type == UCODE_INIT) |
1807 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); | 1960 | base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); |
@@ -1812,7 +1965,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1812 | IWL_ERR(priv, | 1965 | IWL_ERR(priv, |
1813 | "Invalid event log pointer 0x%08X for %s uCode\n", | 1966 | "Invalid event log pointer 0x%08X for %s uCode\n", |
1814 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); | 1967 | base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); |
1815 | return; | 1968 | return pos; |
1816 | } | 1969 | } |
1817 | 1970 | ||
1818 | /* event log header */ | 1971 | /* event log header */ |
@@ -1838,7 +1991,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1838 | /* bail out if nothing in log */ | 1991 | /* bail out if nothing in log */ |
1839 | if (size == 0) { | 1992 | if (size == 0) { |
1840 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1993 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1841 | return; | 1994 | return pos; |
1842 | } | 1995 | } |
1843 | 1996 | ||
1844 | #ifdef CONFIG_IWLWIFI_DEBUG | 1997 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1853,6 +2006,15 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1853 | size); | 2006 | size); |
1854 | 2007 | ||
1855 | #ifdef CONFIG_IWLWIFI_DEBUG | 2008 | #ifdef CONFIG_IWLWIFI_DEBUG |
2009 | if (display) { | ||
2010 | if (full_log) | ||
2011 | bufsz = capacity * 48; | ||
2012 | else | ||
2013 | bufsz = size * 48; | ||
2014 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
2015 | if (!*buf) | ||
2016 | return pos; | ||
2017 | } | ||
1856 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | 2018 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { |
1857 | /* | 2019 | /* |
1858 | * if uCode has wrapped back to top of log, | 2020 | * if uCode has wrapped back to top of log, |
@@ -1860,17 +2022,22 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1860 | * i.e the next one that uCode would fill. | 2022 | * i.e the next one that uCode would fill. |
1861 | */ | 2023 | */ |
1862 | if (num_wraps) | 2024 | if (num_wraps) |
1863 | iwl_print_event_log(priv, next_entry, | 2025 | pos = iwl_print_event_log(priv, next_entry, |
1864 | capacity - next_entry, mode); | 2026 | capacity - next_entry, mode, |
2027 | pos, buf, bufsz); | ||
1865 | /* (then/else) start at top of log */ | 2028 | /* (then/else) start at top of log */ |
1866 | iwl_print_event_log(priv, 0, next_entry, mode); | 2029 | pos = iwl_print_event_log(priv, 0, |
2030 | next_entry, mode, pos, buf, bufsz); | ||
1867 | } else | 2031 | } else |
1868 | iwl_print_last_event_logs(priv, capacity, num_wraps, | 2032 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, |
1869 | next_entry, size, mode); | 2033 | next_entry, size, mode, |
2034 | pos, buf, bufsz); | ||
1870 | #else | 2035 | #else |
1871 | iwl_print_last_event_logs(priv, capacity, num_wraps, | 2036 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, |
1872 | next_entry, size, mode); | 2037 | next_entry, size, mode, |
2038 | pos, buf, bufsz); | ||
1873 | #endif | 2039 | #endif |
2040 | return pos; | ||
1874 | } | 2041 | } |
1875 | 2042 | ||
1876 | /** | 2043 | /** |
@@ -2456,6 +2623,10 @@ static int iwl_setup_mac(struct iwl_priv *priv) | |||
2456 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 2623 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
2457 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 2624 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
2458 | 2625 | ||
2626 | if (priv->cfg->sku & IWL_SKU_N) | ||
2627 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | ||
2628 | IEEE80211_HW_SUPPORTS_STATIC_SMPS; | ||
2629 | |||
2459 | hw->sta_data_size = sizeof(struct iwl_station_priv); | 2630 | hw->sta_data_size = sizeof(struct iwl_station_priv); |
2460 | hw->wiphy->interface_modes = | 2631 | hw->wiphy->interface_modes = |
2461 | BIT(NL80211_IFTYPE_STATION) | | 2632 | BIT(NL80211_IFTYPE_STATION) | |
@@ -3126,6 +3297,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3126 | priv->statistics_periodic.data = (unsigned long)priv; | 3297 | priv->statistics_periodic.data = (unsigned long)priv; |
3127 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; | 3298 | priv->statistics_periodic.function = iwl_bg_statistics_periodic; |
3128 | 3299 | ||
3300 | init_timer(&priv->ucode_trace); | ||
3301 | priv->ucode_trace.data = (unsigned long)priv; | ||
3302 | priv->ucode_trace.function = iwl_bg_ucode_trace; | ||
3303 | |||
3129 | if (!priv->cfg->use_isr_legacy) | 3304 | if (!priv->cfg->use_isr_legacy) |
3130 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3305 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3131 | iwl_irq_tasklet, (unsigned long)priv); | 3306 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -3144,6 +3319,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3144 | cancel_delayed_work(&priv->alive_start); | 3319 | cancel_delayed_work(&priv->alive_start); |
3145 | cancel_work_sync(&priv->beacon_update); | 3320 | cancel_work_sync(&priv->beacon_update); |
3146 | del_timer_sync(&priv->statistics_periodic); | 3321 | del_timer_sync(&priv->statistics_periodic); |
3322 | del_timer_sync(&priv->ucode_trace); | ||
3147 | } | 3323 | } |
3148 | 3324 | ||
3149 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 3325 | static void iwl_init_hw_rates(struct iwl_priv *priv, |
@@ -3188,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3188 | priv->band = IEEE80211_BAND_2GHZ; | 3364 | priv->band = IEEE80211_BAND_2GHZ; |
3189 | 3365 | ||
3190 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3366 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3367 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | ||
3191 | 3368 | ||
3192 | /* Choose which receivers/antennas to use */ | 3369 | /* Choose which receivers/antennas to use */ |
3193 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3370 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 95a57b36a7ea..dc61906290e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -414,7 +414,6 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, | |||
414 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ | 414 | /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ |
415 | static int iwl_sensitivity_write(struct iwl_priv *priv) | 415 | static int iwl_sensitivity_write(struct iwl_priv *priv) |
416 | { | 416 | { |
417 | int ret = 0; | ||
418 | struct iwl_sensitivity_cmd cmd ; | 417 | struct iwl_sensitivity_cmd cmd ; |
419 | struct iwl_sensitivity_data *data = NULL; | 418 | struct iwl_sensitivity_data *data = NULL; |
420 | struct iwl_host_cmd cmd_out = { | 419 | struct iwl_host_cmd cmd_out = { |
@@ -477,11 +476,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
477 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), | 476 | memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), |
478 | sizeof(u16)*HD_TABLE_SIZE); | 477 | sizeof(u16)*HD_TABLE_SIZE); |
479 | 478 | ||
480 | ret = iwl_send_cmd(priv, &cmd_out); | 479 | return iwl_send_cmd(priv, &cmd_out); |
481 | if (ret) | ||
482 | IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); | ||
483 | |||
484 | return ret; | ||
485 | } | 480 | } |
486 | 481 | ||
487 | void iwl_init_sensitivity(struct iwl_priv *priv) | 482 | void iwl_init_sensitivity(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e91507531923..28f3800c560e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -2510,7 +2510,7 @@ struct iwl_card_state_notif { | |||
2510 | 2510 | ||
2511 | #define HW_CARD_DISABLED 0x01 | 2511 | #define HW_CARD_DISABLED 0x01 |
2512 | #define SW_CARD_DISABLED 0x02 | 2512 | #define SW_CARD_DISABLED 0x02 |
2513 | #define RF_CARD_DISABLED 0x04 | 2513 | #define CT_CARD_DISABLED 0x04 |
2514 | #define RXON_CARD_DISABLED 0x10 | 2514 | #define RXON_CARD_DISABLED 0x10 |
2515 | 2515 | ||
2516 | struct iwl_ct_kill_config { | 2516 | struct iwl_ct_kill_config { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 574d36658702..e3b96b48b7fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -450,8 +450,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
450 | if (priv->cfg->ht_greenfield_support) | 450 | if (priv->cfg->ht_greenfield_support) |
451 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 451 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
452 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 452 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
453 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | ||
454 | (priv->cfg->sm_ps_mode << 2)); | ||
455 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 453 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
456 | if (priv->hw_params.ht40_channel & BIT(band)) { | 454 | if (priv->hw_params.ht40_channel & BIT(band)) { |
457 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 455 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -636,7 +634,7 @@ EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); | |||
636 | 634 | ||
637 | static bool is_single_rx_stream(struct iwl_priv *priv) | 635 | static bool is_single_rx_stream(struct iwl_priv *priv) |
638 | { | 636 | { |
639 | return !priv->current_ht_config.is_ht || | 637 | return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || |
640 | priv->current_ht_config.single_chain_sufficient; | 638 | priv->current_ht_config.single_chain_sufficient; |
641 | } | 639 | } |
642 | 640 | ||
@@ -1003,28 +1001,18 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | |||
1003 | */ | 1001 | */ |
1004 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | 1002 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) |
1005 | { | 1003 | { |
1006 | int idle_cnt = active_cnt; | 1004 | /* # Rx chains when idling, depending on SMPS mode */ |
1007 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | 1005 | switch (priv->current_ht_config.smps) { |
1008 | 1006 | case IEEE80211_SMPS_STATIC: | |
1009 | /* # Rx chains when idling and maybe trying to save power */ | 1007 | case IEEE80211_SMPS_DYNAMIC: |
1010 | switch (priv->cfg->sm_ps_mode) { | 1008 | return IWL_NUM_IDLE_CHAINS_SINGLE; |
1011 | case WLAN_HT_CAP_SM_PS_STATIC: | 1009 | case IEEE80211_SMPS_OFF: |
1012 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; | 1010 | return active_cnt; |
1013 | break; | ||
1014 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | ||
1015 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : | ||
1016 | IWL_NUM_IDLE_CHAINS_SINGLE; | ||
1017 | break; | ||
1018 | case WLAN_HT_CAP_SM_PS_DISABLED: | ||
1019 | break; | ||
1020 | case WLAN_HT_CAP_SM_PS_INVALID: | ||
1021 | default: | 1011 | default: |
1022 | IWL_ERR(priv, "invalid sm_ps mode %u\n", | 1012 | WARN(1, "invalid SMPS mode %d", |
1023 | priv->cfg->sm_ps_mode); | 1013 | priv->current_ht_config.smps); |
1024 | WARN_ON(1); | 1014 | return active_cnt; |
1025 | break; | ||
1026 | } | 1015 | } |
1027 | return idle_cnt; | ||
1028 | } | 1016 | } |
1029 | 1017 | ||
1030 | /* up to 4 chains */ | 1018 | /* up to 4 chains */ |
@@ -1363,7 +1351,9 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1363 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1351 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1364 | 1352 | ||
1365 | priv->cfg->ops->lib->dump_nic_error_log(priv); | 1353 | priv->cfg->ops->lib->dump_nic_error_log(priv); |
1366 | priv->cfg->ops->lib->dump_nic_event_log(priv, false); | 1354 | if (priv->cfg->ops->lib->dump_csr) |
1355 | priv->cfg->ops->lib->dump_csr(priv); | ||
1356 | priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); | ||
1367 | #ifdef CONFIG_IWLWIFI_DEBUG | 1357 | #ifdef CONFIG_IWLWIFI_DEBUG |
1368 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) | 1358 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
1369 | iwl_print_rx_config_cmd(priv); | 1359 | iwl_print_rx_config_cmd(priv); |
@@ -2684,6 +2674,21 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2684 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); | 2674 | IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); |
2685 | } | 2675 | } |
2686 | 2676 | ||
2677 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | ||
2678 | IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2679 | /* mac80211 uses static for non-HT which is what we want */ | ||
2680 | priv->current_ht_config.smps = conf->smps_mode; | ||
2681 | |||
2682 | /* | ||
2683 | * Recalculate chain counts. | ||
2684 | * | ||
2685 | * If monitor mode is enabled then mac80211 will | ||
2686 | * set up the SM PS mode to OFF if an HT channel is | ||
2687 | * configured. | ||
2688 | */ | ||
2689 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2690 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2691 | } | ||
2687 | 2692 | ||
2688 | /* during scanning mac80211 will delay channel setting until | 2693 | /* during scanning mac80211 will delay channel setting until |
2689 | * scan finish with changed = 0 | 2694 | * scan finish with changed = 0 |
@@ -2780,10 +2785,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2780 | iwl_set_tx_power(priv, conf->power_level, false); | 2785 | iwl_set_tx_power(priv, conf->power_level, false); |
2781 | } | 2786 | } |
2782 | 2787 | ||
2783 | /* call to ensure that 4965 rx_chain is set properly in monitor mode */ | ||
2784 | if (priv->cfg->ops->hcmd->set_rxon_chain) | ||
2785 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | ||
2786 | |||
2787 | if (!iwl_is_ready(priv)) { | 2788 | if (!iwl_is_ready(priv)) { |
2788 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2789 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2789 | goto out; | 2790 | goto out; |
@@ -3191,6 +3192,77 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
3191 | EXPORT_SYMBOL(iwl_update_stats); | 3192 | EXPORT_SYMBOL(iwl_update_stats); |
3192 | #endif | 3193 | #endif |
3193 | 3194 | ||
3195 | const static char *get_csr_string(int cmd) | ||
3196 | { | ||
3197 | switch (cmd) { | ||
3198 | IWL_CMD(CSR_HW_IF_CONFIG_REG); | ||
3199 | IWL_CMD(CSR_INT_COALESCING); | ||
3200 | IWL_CMD(CSR_INT); | ||
3201 | IWL_CMD(CSR_INT_MASK); | ||
3202 | IWL_CMD(CSR_FH_INT_STATUS); | ||
3203 | IWL_CMD(CSR_GPIO_IN); | ||
3204 | IWL_CMD(CSR_RESET); | ||
3205 | IWL_CMD(CSR_GP_CNTRL); | ||
3206 | IWL_CMD(CSR_HW_REV); | ||
3207 | IWL_CMD(CSR_EEPROM_REG); | ||
3208 | IWL_CMD(CSR_EEPROM_GP); | ||
3209 | IWL_CMD(CSR_OTP_GP_REG); | ||
3210 | IWL_CMD(CSR_GIO_REG); | ||
3211 | IWL_CMD(CSR_GP_UCODE_REG); | ||
3212 | IWL_CMD(CSR_GP_DRIVER_REG); | ||
3213 | IWL_CMD(CSR_UCODE_DRV_GP1); | ||
3214 | IWL_CMD(CSR_UCODE_DRV_GP2); | ||
3215 | IWL_CMD(CSR_LED_REG); | ||
3216 | IWL_CMD(CSR_DRAM_INT_TBL_REG); | ||
3217 | IWL_CMD(CSR_GIO_CHICKEN_BITS); | ||
3218 | IWL_CMD(CSR_ANA_PLL_CFG); | ||
3219 | IWL_CMD(CSR_HW_REV_WA_REG); | ||
3220 | IWL_CMD(CSR_DBG_HPET_MEM_REG); | ||
3221 | default: | ||
3222 | return "UNKNOWN"; | ||
3223 | |||
3224 | } | ||
3225 | } | ||
3226 | |||
3227 | void iwl_dump_csr(struct iwl_priv *priv) | ||
3228 | { | ||
3229 | int i; | ||
3230 | u32 csr_tbl[] = { | ||
3231 | CSR_HW_IF_CONFIG_REG, | ||
3232 | CSR_INT_COALESCING, | ||
3233 | CSR_INT, | ||
3234 | CSR_INT_MASK, | ||
3235 | CSR_FH_INT_STATUS, | ||
3236 | CSR_GPIO_IN, | ||
3237 | CSR_RESET, | ||
3238 | CSR_GP_CNTRL, | ||
3239 | CSR_HW_REV, | ||
3240 | CSR_EEPROM_REG, | ||
3241 | CSR_EEPROM_GP, | ||
3242 | CSR_OTP_GP_REG, | ||
3243 | CSR_GIO_REG, | ||
3244 | CSR_GP_UCODE_REG, | ||
3245 | CSR_GP_DRIVER_REG, | ||
3246 | CSR_UCODE_DRV_GP1, | ||
3247 | CSR_UCODE_DRV_GP2, | ||
3248 | CSR_LED_REG, | ||
3249 | CSR_DRAM_INT_TBL_REG, | ||
3250 | CSR_GIO_CHICKEN_BITS, | ||
3251 | CSR_ANA_PLL_CFG, | ||
3252 | CSR_HW_REV_WA_REG, | ||
3253 | CSR_DBG_HPET_MEM_REG | ||
3254 | }; | ||
3255 | IWL_ERR(priv, "CSR values:\n"); | ||
3256 | IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " | ||
3257 | "CSR_INT_PERIODIC_REG)\n"); | ||
3258 | for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { | ||
3259 | IWL_ERR(priv, " %25s: 0X%08x\n", | ||
3260 | get_csr_string(csr_tbl[i]), | ||
3261 | iwl_read32(priv, csr_tbl[i])); | ||
3262 | } | ||
3263 | } | ||
3264 | EXPORT_SYMBOL(iwl_dump_csr); | ||
3265 | |||
3194 | #ifdef CONFIG_PM | 3266 | #ifdef CONFIG_PM |
3195 | 3267 | ||
3196 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 3268 | int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 27ca859e7453..308f679ef81c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -169,8 +169,10 @@ struct iwl_lib_ops { | |||
169 | int (*is_valid_rtc_data_addr)(u32 addr); | 169 | int (*is_valid_rtc_data_addr)(u32 addr); |
170 | /* 1st ucode load */ | 170 | /* 1st ucode load */ |
171 | int (*load_ucode)(struct iwl_priv *priv); | 171 | int (*load_ucode)(struct iwl_priv *priv); |
172 | void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); | 172 | int (*dump_nic_event_log)(struct iwl_priv *priv, |
173 | bool full_log, char **buf, bool display); | ||
173 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 174 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
175 | void (*dump_csr)(struct iwl_priv *priv); | ||
174 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 176 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); |
175 | /* power management */ | 177 | /* power management */ |
176 | struct iwl_apm_ops apm_ops; | 178 | struct iwl_apm_ops apm_ops; |
@@ -230,7 +232,6 @@ struct iwl_mod_params { | |||
230 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 232 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
231 | * @adv_thermal_throttle: support advance thermal throttle | 233 | * @adv_thermal_throttle: support advance thermal throttle |
232 | * @support_ct_kill_exit: support ct kill exit condition | 234 | * @support_ct_kill_exit: support ct kill exit condition |
233 | * @sm_ps_mode: spatial multiplexing power save mode | ||
234 | * @support_wimax_coexist: support wimax/wifi co-exist | 235 | * @support_wimax_coexist: support wimax/wifi co-exist |
235 | * | 236 | * |
236 | * We enable the driver to be backward compatible wrt API version. The | 237 | * We enable the driver to be backward compatible wrt API version. The |
@@ -287,7 +288,6 @@ struct iwl_cfg { | |||
287 | const bool supports_idle; | 288 | const bool supports_idle; |
288 | bool adv_thermal_throttle; | 289 | bool adv_thermal_throttle; |
289 | bool support_ct_kill_exit; | 290 | bool support_ct_kill_exit; |
290 | u8 sm_ps_mode; | ||
291 | const bool support_wimax_coexist; | 291 | const bool support_wimax_coexist; |
292 | }; | 292 | }; |
293 | 293 | ||
@@ -581,7 +581,9 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
581 | * Error Handling Debugging | 581 | * Error Handling Debugging |
582 | ******************************************************/ | 582 | ******************************************************/ |
583 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 583 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
584 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 584 | int iwl_dump_nic_event_log(struct iwl_priv *priv, |
585 | bool full_log, char **buf, bool display); | ||
586 | void iwl_dump_csr(struct iwl_priv *priv); | ||
585 | #ifdef CONFIG_IWLWIFI_DEBUG | 587 | #ifdef CONFIG_IWLWIFI_DEBUG |
586 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 588 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); |
587 | #else | 589 | #else |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d61293ab67c9..58e0462cafa3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -109,6 +109,8 @@ struct iwl_debugfs { | |||
109 | struct dentry *file_power_save_status; | 109 | struct dentry *file_power_save_status; |
110 | struct dentry *file_clear_ucode_statistics; | 110 | struct dentry *file_clear_ucode_statistics; |
111 | struct dentry *file_clear_traffic_statistics; | 111 | struct dentry *file_clear_traffic_statistics; |
112 | struct dentry *file_csr; | ||
113 | struct dentry *file_ucode_tracing; | ||
112 | } dbgfs_debug_files; | 114 | } dbgfs_debug_files; |
113 | u32 sram_offset; | 115 | u32 sram_offset; |
114 | u32 sram_len; | 116 | u32 sram_len; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 21e0f6699daf..ee5aed12a4b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -420,6 +420,23 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
420 | return ret; | 420 | return ret; |
421 | } | 421 | } |
422 | 422 | ||
423 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
424 | char __user *user_buf, | ||
425 | size_t count, loff_t *ppos) | ||
426 | { | ||
427 | struct iwl_priv *priv = file->private_data; | ||
428 | char *buf; | ||
429 | int pos = 0; | ||
430 | ssize_t ret = -ENOMEM; | ||
431 | |||
432 | pos = priv->cfg->ops->lib->dump_nic_event_log(priv, true, &buf, true); | ||
433 | if (pos && buf) { | ||
434 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
435 | kfree(buf); | ||
436 | } | ||
437 | return ret; | ||
438 | } | ||
439 | |||
423 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | 440 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, |
424 | const char __user *user_buf, | 441 | const char __user *user_buf, |
425 | size_t count, loff_t *ppos) | 442 | size_t count, loff_t *ppos) |
@@ -436,7 +453,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
436 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 453 | if (sscanf(buf, "%d", &event_log_flag) != 1) |
437 | return -EFAULT; | 454 | return -EFAULT; |
438 | if (event_log_flag == 1) | 455 | if (event_log_flag == 1) |
439 | priv->cfg->ops->lib->dump_nic_event_log(priv, true); | 456 | priv->cfg->ops->lib->dump_nic_event_log(priv, true, |
457 | NULL, false); | ||
440 | 458 | ||
441 | return count; | 459 | return count; |
442 | } | 460 | } |
@@ -859,7 +877,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, | |||
859 | } | 877 | } |
860 | 878 | ||
861 | DEBUGFS_READ_WRITE_FILE_OPS(sram); | 879 | DEBUGFS_READ_WRITE_FILE_OPS(sram); |
862 | DEBUGFS_WRITE_FILE_OPS(log_event); | 880 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); |
863 | DEBUGFS_READ_FILE_OPS(nvm); | 881 | DEBUGFS_READ_FILE_OPS(nvm); |
864 | DEBUGFS_READ_FILE_OPS(stations); | 882 | DEBUGFS_READ_FILE_OPS(stations); |
865 | DEBUGFS_READ_FILE_OPS(channels); | 883 | DEBUGFS_READ_FILE_OPS(channels); |
@@ -1845,6 +1863,80 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, | |||
1845 | return count; | 1863 | return count; |
1846 | } | 1864 | } |
1847 | 1865 | ||
1866 | static ssize_t iwl_dbgfs_csr_write(struct file *file, | ||
1867 | const char __user *user_buf, | ||
1868 | size_t count, loff_t *ppos) | ||
1869 | { | ||
1870 | struct iwl_priv *priv = file->private_data; | ||
1871 | char buf[8]; | ||
1872 | int buf_size; | ||
1873 | int csr; | ||
1874 | |||
1875 | memset(buf, 0, sizeof(buf)); | ||
1876 | buf_size = min(count, sizeof(buf) - 1); | ||
1877 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1878 | return -EFAULT; | ||
1879 | if (sscanf(buf, "%d", &csr) != 1) | ||
1880 | return -EFAULT; | ||
1881 | |||
1882 | if (priv->cfg->ops->lib->dump_csr) | ||
1883 | priv->cfg->ops->lib->dump_csr(priv); | ||
1884 | |||
1885 | return count; | ||
1886 | } | ||
1887 | |||
1888 | static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, | ||
1889 | char __user *user_buf, | ||
1890 | size_t count, loff_t *ppos) { | ||
1891 | |||
1892 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
1893 | int pos = 0; | ||
1894 | char buf[128]; | ||
1895 | const size_t bufsz = sizeof(buf); | ||
1896 | ssize_t ret; | ||
1897 | |||
1898 | pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", | ||
1899 | priv->event_log.ucode_trace ? "On" : "Off"); | ||
1900 | pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", | ||
1901 | priv->event_log.non_wraps_count); | ||
1902 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", | ||
1903 | priv->event_log.wraps_once_count); | ||
1904 | pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", | ||
1905 | priv->event_log.wraps_more_count); | ||
1906 | |||
1907 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1908 | return ret; | ||
1909 | } | ||
1910 | |||
1911 | static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, | ||
1912 | const char __user *user_buf, | ||
1913 | size_t count, loff_t *ppos) | ||
1914 | { | ||
1915 | struct iwl_priv *priv = file->private_data; | ||
1916 | char buf[8]; | ||
1917 | int buf_size; | ||
1918 | int trace; | ||
1919 | |||
1920 | memset(buf, 0, sizeof(buf)); | ||
1921 | buf_size = min(count, sizeof(buf) - 1); | ||
1922 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1923 | return -EFAULT; | ||
1924 | if (sscanf(buf, "%d", &trace) != 1) | ||
1925 | return -EFAULT; | ||
1926 | |||
1927 | if (trace) { | ||
1928 | priv->event_log.ucode_trace = true; | ||
1929 | /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ | ||
1930 | mod_timer(&priv->ucode_trace, | ||
1931 | jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); | ||
1932 | } else { | ||
1933 | priv->event_log.ucode_trace = false; | ||
1934 | del_timer_sync(&priv->ucode_trace); | ||
1935 | } | ||
1936 | |||
1937 | return count; | ||
1938 | } | ||
1939 | |||
1848 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 1940 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
1849 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 1941 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
1850 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 1942 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1859,6 +1951,8 @@ DEBUGFS_READ_FILE_OPS(tx_power); | |||
1859 | DEBUGFS_READ_FILE_OPS(power_save_status); | 1951 | DEBUGFS_READ_FILE_OPS(power_save_status); |
1860 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | 1952 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); |
1861 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | 1953 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); |
1954 | DEBUGFS_WRITE_FILE_OPS(csr); | ||
1955 | DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); | ||
1862 | 1956 | ||
1863 | /* | 1957 | /* |
1864 | * Create the debugfs files and directories | 1958 | * Create the debugfs files and directories |
@@ -1889,7 +1983,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1889 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); | 1983 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); |
1890 | DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); | 1984 | DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); |
1891 | DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); | 1985 | DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); |
1892 | DEBUGFS_ADD_FILE(log_event, data, S_IWUSR); | 1986 | DEBUGFS_ADD_FILE(log_event, data, S_IWUSR | S_IRUSR); |
1893 | DEBUGFS_ADD_FILE(stations, data, S_IRUSR); | 1987 | DEBUGFS_ADD_FILE(stations, data, S_IRUSR); |
1894 | DEBUGFS_ADD_FILE(channels, data, S_IRUSR); | 1988 | DEBUGFS_ADD_FILE(channels, data, S_IRUSR); |
1895 | DEBUGFS_ADD_FILE(status, data, S_IRUSR); | 1989 | DEBUGFS_ADD_FILE(status, data, S_IRUSR); |
@@ -1909,12 +2003,14 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1909 | DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); | 2003 | DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); |
1910 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); | 2004 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); |
1911 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); | 2005 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); |
2006 | DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); | ||
1912 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2007 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1913 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); | 2008 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); |
1914 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); | 2009 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); |
1915 | DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); | 2010 | DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); |
1916 | DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); | 2011 | DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); |
1917 | DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); | 2012 | DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); |
2013 | DEBUGFS_ADD_FILE(ucode_tracing, debug, S_IWUSR | S_IRUSR); | ||
1918 | } | 2014 | } |
1919 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 2015 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); |
1920 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 2016 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, |
@@ -1966,6 +2062,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1966 | file_clear_ucode_statistics); | 2062 | file_clear_ucode_statistics); |
1967 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 2063 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
1968 | file_clear_traffic_statistics); | 2064 | file_clear_traffic_statistics); |
2065 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); | ||
1969 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2066 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1970 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 2067 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
1971 | file_ucode_rx_stats); | 2068 | file_ucode_rx_stats); |
@@ -1977,6 +2074,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1977 | file_sensitivity); | 2074 | file_sensitivity); |
1978 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 2075 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
1979 | file_chain_noise); | 2076 | file_chain_noise); |
2077 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
2078 | file_ucode_tracing); | ||
1980 | } | 2079 | } |
1981 | DEBUGFS_REMOVE(priv->dbgfs->dir_debug); | 2080 | DEBUGFS_REMOVE(priv->dbgfs->dir_debug); |
1982 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); | 2081 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 165d1f6e2dd9..42f9b17327c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -512,6 +512,7 @@ struct iwl_ht_config { | |||
512 | bool is_ht; | 512 | bool is_ht; |
513 | bool is_40mhz; | 513 | bool is_40mhz; |
514 | bool single_chain_sufficient; | 514 | bool single_chain_sufficient; |
515 | enum ieee80211_smps_mode smps; /* current smps mode */ | ||
515 | /* BSS related data */ | 516 | /* BSS related data */ |
516 | u8 extension_chan_offset; | 517 | u8 extension_chan_offset; |
517 | u8 ht_protection; | 518 | u8 ht_protection; |
@@ -984,6 +985,32 @@ struct iwl_switch_rxon { | |||
984 | __le16 channel; | 985 | __le16 channel; |
985 | }; | 986 | }; |
986 | 987 | ||
988 | /* | ||
989 | * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds | ||
990 | * to perform continuous uCode event logging operation if enabled | ||
991 | */ | ||
992 | #define UCODE_TRACE_PERIOD (100) | ||
993 | |||
994 | /* | ||
995 | * iwl_event_log: current uCode event log position | ||
996 | * | ||
997 | * @ucode_trace: enable/disable ucode continuous trace timer | ||
998 | * @num_wraps: how many times the event buffer wraps | ||
999 | * @next_entry: the entry just before the next one that uCode would fill | ||
1000 | * @non_wraps_count: counter for no wrap detected when dump ucode events | ||
1001 | * @wraps_once_count: counter for wrap once detected when dump ucode events | ||
1002 | * @wraps_more_count: counter for wrap more than once detected | ||
1003 | * when dump ucode events | ||
1004 | */ | ||
1005 | struct iwl_event_log { | ||
1006 | bool ucode_trace; | ||
1007 | u32 num_wraps; | ||
1008 | u32 next_entry; | ||
1009 | int non_wraps_count; | ||
1010 | int wraps_once_count; | ||
1011 | int wraps_more_count; | ||
1012 | }; | ||
1013 | |||
987 | struct iwl_priv { | 1014 | struct iwl_priv { |
988 | 1015 | ||
989 | /* ieee device used by generic ieee processing code */ | 1016 | /* ieee device used by generic ieee processing code */ |
@@ -1261,6 +1288,7 @@ struct iwl_priv { | |||
1261 | u32 disable_tx_power_cal; | 1288 | u32 disable_tx_power_cal; |
1262 | struct work_struct run_time_calib_work; | 1289 | struct work_struct run_time_calib_work; |
1263 | struct timer_list statistics_periodic; | 1290 | struct timer_list statistics_periodic; |
1291 | struct timer_list ucode_trace; | ||
1264 | bool hw_ready; | 1292 | bool hw_ready; |
1265 | /*For 3945*/ | 1293 | /*For 3945*/ |
1266 | #define IWL_DEFAULT_TX_POWER 0x0F | 1294 | #define IWL_DEFAULT_TX_POWER 0x0F |
@@ -1268,6 +1296,8 @@ struct iwl_priv { | |||
1268 | struct iwl3945_notif_statistics statistics_39; | 1296 | struct iwl3945_notif_statistics statistics_39; |
1269 | 1297 | ||
1270 | u32 sta_supp_rates; | 1298 | u32 sta_supp_rates; |
1299 | |||
1300 | struct iwl_event_log event_log; | ||
1271 | }; /*iwl_priv */ | 1301 | }; /*iwl_priv */ |
1272 | 1302 | ||
1273 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | 1303 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index e7d88d1da15d..bf46308b17fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -11,4 +11,6 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | |||
11 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 11 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
12 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | 12 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); |
13 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 13 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
14 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | ||
15 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); | ||
14 | #endif | 16 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 21361968ab7e..0819f990be6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -65,6 +65,50 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, | |||
65 | ); | 65 | ); |
66 | 66 | ||
67 | #undef TRACE_SYSTEM | 67 | #undef TRACE_SYSTEM |
68 | #define TRACE_SYSTEM iwlwifi_ucode | ||
69 | |||
70 | TRACE_EVENT(iwlwifi_dev_ucode_cont_event, | ||
71 | TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), | ||
72 | TP_ARGS(priv, time, data, ev), | ||
73 | TP_STRUCT__entry( | ||
74 | PRIV_ENTRY | ||
75 | |||
76 | __field(u32, time) | ||
77 | __field(u32, data) | ||
78 | __field(u32, ev) | ||
79 | ), | ||
80 | TP_fast_assign( | ||
81 | PRIV_ASSIGN; | ||
82 | __entry->time = time; | ||
83 | __entry->data = data; | ||
84 | __entry->ev = ev; | ||
85 | ), | ||
86 | TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", | ||
87 | __entry->priv, __entry->time, __entry->data, __entry->ev) | ||
88 | ); | ||
89 | |||
90 | TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, | ||
91 | TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry), | ||
92 | TP_ARGS(priv, wraps, n_entry, p_entry), | ||
93 | TP_STRUCT__entry( | ||
94 | PRIV_ENTRY | ||
95 | |||
96 | __field(u32, wraps) | ||
97 | __field(u32, n_entry) | ||
98 | __field(u32, p_entry) | ||
99 | ), | ||
100 | TP_fast_assign( | ||
101 | PRIV_ASSIGN; | ||
102 | __entry->wraps = wraps; | ||
103 | __entry->n_entry = n_entry; | ||
104 | __entry->p_entry = p_entry; | ||
105 | ), | ||
106 | TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", | ||
107 | __entry->priv, __entry->wraps, __entry->n_entry, | ||
108 | __entry->p_entry) | ||
109 | ); | ||
110 | |||
111 | #undef TRACE_SYSTEM | ||
68 | #define TRACE_SYSTEM iwlwifi | 112 | #define TRACE_SYSTEM iwlwifi |
69 | 113 | ||
70 | TRACE_EVENT(iwlwifi_dev_hcmd, | 114 | TRACE_EVENT(iwlwifi_dev_hcmd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e5d8fa38432e..6533122ed87a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1559,8 +1559,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1559 | * iwl3945_print_event_log - Dump error event log to syslog | 1559 | * iwl3945_print_event_log - Dump error event log to syslog |
1560 | * | 1560 | * |
1561 | */ | 1561 | */ |
1562 | static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1562 | static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1563 | u32 num_events, u32 mode) | 1563 | u32 num_events, u32 mode, |
1564 | int pos, char **buf, size_t bufsz) | ||
1564 | { | 1565 | { |
1565 | u32 i; | 1566 | u32 i; |
1566 | u32 base; /* SRAM byte address of event log header */ | 1567 | u32 base; /* SRAM byte address of event log header */ |
@@ -1570,7 +1571,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1570 | unsigned long reg_flags; | 1571 | unsigned long reg_flags; |
1571 | 1572 | ||
1572 | if (num_events == 0) | 1573 | if (num_events == 0) |
1573 | return; | 1574 | return pos; |
1574 | 1575 | ||
1575 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1576 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1576 | 1577 | ||
@@ -1596,26 +1597,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1596 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1597 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1597 | if (mode == 0) { | 1598 | if (mode == 0) { |
1598 | /* data, ev */ | 1599 | /* data, ev */ |
1599 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1600 | if (bufsz) { |
1600 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1601 | pos += scnprintf(*buf + pos, bufsz - pos, |
1602 | "0x%08x:%04u\n", | ||
1603 | time, ev); | ||
1604 | } else { | ||
1605 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | ||
1606 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1607 | time, ev); | ||
1608 | } | ||
1601 | } else { | 1609 | } else { |
1602 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1610 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1603 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1611 | if (bufsz) { |
1604 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1612 | pos += scnprintf(*buf + pos, bufsz - pos, |
1613 | "%010u:0x%08x:%04u\n", | ||
1614 | time, data, ev); | ||
1615 | } else { | ||
1616 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", | ||
1617 | time, data, ev); | ||
1618 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1619 | data, ev); | ||
1620 | } | ||
1605 | } | 1621 | } |
1606 | } | 1622 | } |
1607 | 1623 | ||
1608 | /* Allow device to power down */ | 1624 | /* Allow device to power down */ |
1609 | iwl_release_nic_access(priv); | 1625 | iwl_release_nic_access(priv); |
1610 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1626 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1627 | return pos; | ||
1611 | } | 1628 | } |
1612 | 1629 | ||
1613 | /** | 1630 | /** |
1614 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | 1631 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog |
1615 | */ | 1632 | */ |
1616 | static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | 1633 | static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, |
1617 | u32 num_wraps, u32 next_entry, | 1634 | u32 num_wraps, u32 next_entry, |
1618 | u32 size, u32 mode) | 1635 | u32 size, u32 mode, |
1636 | int pos, char **buf, size_t bufsz) | ||
1619 | { | 1637 | { |
1620 | /* | 1638 | /* |
1621 | * display the newest DEFAULT_LOG_ENTRIES entries | 1639 | * display the newest DEFAULT_LOG_ENTRIES entries |
@@ -1623,21 +1641,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1623 | */ | 1641 | */ |
1624 | if (num_wraps) { | 1642 | if (num_wraps) { |
1625 | if (next_entry < size) { | 1643 | if (next_entry < size) { |
1626 | iwl3945_print_event_log(priv, | 1644 | pos = iwl3945_print_event_log(priv, |
1627 | capacity - (size - next_entry), | 1645 | capacity - (size - next_entry), |
1628 | size - next_entry, mode); | 1646 | size - next_entry, mode, |
1629 | iwl3945_print_event_log(priv, 0, | 1647 | pos, buf, bufsz); |
1630 | next_entry, mode); | 1648 | pos = iwl3945_print_event_log(priv, 0, |
1649 | next_entry, mode, | ||
1650 | pos, buf, bufsz); | ||
1631 | } else | 1651 | } else |
1632 | iwl3945_print_event_log(priv, next_entry - size, | 1652 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1633 | size, mode); | 1653 | size, mode, |
1654 | pos, buf, bufsz); | ||
1634 | } else { | 1655 | } else { |
1635 | if (next_entry < size) | 1656 | if (next_entry < size) |
1636 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1657 | pos = iwl3945_print_event_log(priv, 0, |
1658 | next_entry, mode, | ||
1659 | pos, buf, bufsz); | ||
1637 | else | 1660 | else |
1638 | iwl3945_print_event_log(priv, next_entry - size, | 1661 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1639 | size, mode); | 1662 | size, mode, |
1663 | pos, buf, bufsz); | ||
1640 | } | 1664 | } |
1665 | return pos; | ||
1641 | } | 1666 | } |
1642 | 1667 | ||
1643 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1668 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
@@ -1645,7 +1670,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1645 | 1670 | ||
1646 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | 1671 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1647 | 1672 | ||
1648 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | 1673 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
1674 | char **buf, bool display) | ||
1649 | { | 1675 | { |
1650 | u32 base; /* SRAM byte address of event log header */ | 1676 | u32 base; /* SRAM byte address of event log header */ |
1651 | u32 capacity; /* event log capacity in # entries */ | 1677 | u32 capacity; /* event log capacity in # entries */ |
@@ -1653,11 +1679,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1653 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1679 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1654 | u32 next_entry; /* index of next entry to be written by uCode */ | 1680 | u32 next_entry; /* index of next entry to be written by uCode */ |
1655 | u32 size; /* # entries that we'll print */ | 1681 | u32 size; /* # entries that we'll print */ |
1682 | int pos = 0; | ||
1683 | size_t bufsz = 0; | ||
1656 | 1684 | ||
1657 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1685 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1658 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | 1686 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { |
1659 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | 1687 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); |
1660 | return; | 1688 | return pos; |
1661 | } | 1689 | } |
1662 | 1690 | ||
1663 | /* event log header */ | 1691 | /* event log header */ |
@@ -1683,7 +1711,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1683 | /* bail out if nothing in log */ | 1711 | /* bail out if nothing in log */ |
1684 | if (size == 0) { | 1712 | if (size == 0) { |
1685 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1713 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1686 | return; | 1714 | return pos; |
1687 | } | 1715 | } |
1688 | 1716 | ||
1689 | #ifdef CONFIG_IWLWIFI_DEBUG | 1717 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1699,25 +1727,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1699 | size); | 1727 | size); |
1700 | 1728 | ||
1701 | #ifdef CONFIG_IWLWIFI_DEBUG | 1729 | #ifdef CONFIG_IWLWIFI_DEBUG |
1730 | if (display) { | ||
1731 | if (full_log) | ||
1732 | bufsz = capacity * 48; | ||
1733 | else | ||
1734 | bufsz = size * 48; | ||
1735 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1736 | if (!*buf) | ||
1737 | return pos; | ||
1738 | } | ||
1702 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | 1739 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { |
1703 | /* if uCode has wrapped back to top of log, | 1740 | /* if uCode has wrapped back to top of log, |
1704 | * start at the oldest entry, | 1741 | * start at the oldest entry, |
1705 | * i.e the next one that uCode would fill. | 1742 | * i.e the next one that uCode would fill. |
1706 | */ | 1743 | */ |
1707 | if (num_wraps) | 1744 | if (num_wraps) |
1708 | iwl3945_print_event_log(priv, next_entry, | 1745 | pos = iwl3945_print_event_log(priv, next_entry, |
1709 | capacity - next_entry, mode); | 1746 | capacity - next_entry, mode, |
1747 | pos, buf, bufsz); | ||
1710 | 1748 | ||
1711 | /* (then/else) start at top of log */ | 1749 | /* (then/else) start at top of log */ |
1712 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1750 | pos = iwl3945_print_event_log(priv, 0, next_entry, mode, |
1751 | pos, buf, bufsz); | ||
1713 | } else | 1752 | } else |
1714 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1753 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1715 | next_entry, size, mode); | 1754 | next_entry, size, mode, |
1755 | pos, buf, bufsz); | ||
1716 | #else | 1756 | #else |
1717 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1757 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1718 | next_entry, size, mode); | 1758 | next_entry, size, mode, |
1759 | pos, buf, bufsz); | ||
1719 | #endif | 1760 | #endif |
1720 | 1761 | return pos; | |
1721 | } | 1762 | } |
1722 | 1763 | ||
1723 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1764 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 6d6ed7485175..d32adeab68a3 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -868,36 +868,35 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, | |||
868 | struct iwm_umac_notif_mgt_frame *mgt_frame = | 868 | struct iwm_umac_notif_mgt_frame *mgt_frame = |
869 | (struct iwm_umac_notif_mgt_frame *)buf; | 869 | (struct iwm_umac_notif_mgt_frame *)buf; |
870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; | 870 | struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; |
871 | u8 *ie; | ||
872 | 871 | ||
873 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, | 872 | IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, |
874 | le16_to_cpu(mgt_frame->len)); | 873 | le16_to_cpu(mgt_frame->len)); |
875 | 874 | ||
876 | if (ieee80211_is_assoc_req(mgt->frame_control)) { | 875 | if (ieee80211_is_assoc_req(mgt->frame_control)) { |
877 | ie = mgt->u.assoc_req.variable;; | 876 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
878 | iwm->req_ie_len = | 877 | - offsetof(struct ieee80211_mgmt, |
879 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 878 | u.assoc_req.variable); |
880 | kfree(iwm->req_ie); | 879 | kfree(iwm->req_ie); |
881 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, | 880 | iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, |
882 | iwm->req_ie_len, GFP_KERNEL); | 881 | iwm->req_ie_len, GFP_KERNEL); |
883 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { | 882 | } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { |
884 | ie = mgt->u.reassoc_req.variable;; | 883 | iwm->req_ie_len = le16_to_cpu(mgt_frame->len) |
885 | iwm->req_ie_len = | 884 | - offsetof(struct ieee80211_mgmt, |
886 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 885 | u.reassoc_req.variable); |
887 | kfree(iwm->req_ie); | 886 | kfree(iwm->req_ie); |
888 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, | 887 | iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, |
889 | iwm->req_ie_len, GFP_KERNEL); | 888 | iwm->req_ie_len, GFP_KERNEL); |
890 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { | 889 | } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { |
891 | ie = mgt->u.assoc_resp.variable;; | 890 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
892 | iwm->resp_ie_len = | 891 | - offsetof(struct ieee80211_mgmt, |
893 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 892 | u.assoc_resp.variable); |
894 | kfree(iwm->resp_ie); | 893 | kfree(iwm->resp_ie); |
895 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, | 894 | iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, |
896 | iwm->resp_ie_len, GFP_KERNEL); | 895 | iwm->resp_ie_len, GFP_KERNEL); |
897 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { | 896 | } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { |
898 | ie = mgt->u.reassoc_resp.variable;; | 897 | iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) |
899 | iwm->resp_ie_len = | 898 | - offsetof(struct ieee80211_mgmt, |
900 | le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); | 899 | u.reassoc_resp.variable); |
901 | kfree(iwm->resp_ie); | 900 | kfree(iwm->resp_ie); |
902 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, | 901 | iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, |
903 | iwm->resp_ie_len, GFP_KERNEL); | 902 | iwm->resp_ie_len, GFP_KERNEL); |
@@ -1534,6 +1533,33 @@ static void classify8023(struct sk_buff *skb) | |||
1534 | } | 1533 | } |
1535 | } | 1534 | } |
1536 | 1535 | ||
1536 | static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) | ||
1537 | { | ||
1538 | struct wireless_dev *wdev = iwm_to_wdev(iwm); | ||
1539 | struct net_device *ndev = iwm_to_ndev(iwm); | ||
1540 | struct sk_buff_head list; | ||
1541 | struct sk_buff *frame; | ||
1542 | |||
1543 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); | ||
1544 | |||
1545 | __skb_queue_head_init(&list); | ||
1546 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); | ||
1547 | |||
1548 | while ((frame = __skb_dequeue(&list))) { | ||
1549 | ndev->stats.rx_packets++; | ||
1550 | ndev->stats.rx_bytes += frame->len; | ||
1551 | |||
1552 | frame->protocol = eth_type_trans(frame, ndev); | ||
1553 | frame->ip_summed = CHECKSUM_NONE; | ||
1554 | memset(frame->cb, 0, sizeof(frame->cb)); | ||
1555 | |||
1556 | if (netif_rx_ni(frame) == NET_RX_DROP) { | ||
1557 | IWM_ERR(iwm, "Packet dropped\n"); | ||
1558 | ndev->stats.rx_dropped++; | ||
1559 | } | ||
1560 | } | ||
1561 | } | ||
1562 | |||
1537 | static void iwm_rx_process_packet(struct iwm_priv *iwm, | 1563 | static void iwm_rx_process_packet(struct iwm_priv *iwm, |
1538 | struct iwm_rx_packet *packet, | 1564 | struct iwm_rx_packet *packet, |
1539 | struct iwm_rx_ticket_node *ticket_node) | 1565 | struct iwm_rx_ticket_node *ticket_node) |
@@ -1548,25 +1574,34 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1548 | switch (le16_to_cpu(ticket_node->ticket->action)) { | 1574 | switch (le16_to_cpu(ticket_node->ticket->action)) { |
1549 | case IWM_RX_TICKET_RELEASE: | 1575 | case IWM_RX_TICKET_RELEASE: |
1550 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); | 1576 | IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); |
1551 | classify8023(skb); | 1577 | |
1552 | iwm_rx_adjust_packet(iwm, packet, ticket_node); | 1578 | iwm_rx_adjust_packet(iwm, packet, ticket_node); |
1579 | skb->dev = iwm_to_ndev(iwm); | ||
1580 | classify8023(skb); | ||
1581 | |||
1582 | if (le16_to_cpu(ticket_node->ticket->flags) & | ||
1583 | IWM_RX_TICKET_AMSDU_MSK) { | ||
1584 | iwm_rx_process_amsdu(iwm, skb); | ||
1585 | break; | ||
1586 | } | ||
1587 | |||
1553 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); | 1588 | ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); |
1554 | if (ret < 0) { | 1589 | if (ret < 0) { |
1555 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " | 1590 | IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " |
1556 | "%d\n", ret); | 1591 | "%d\n", ret); |
1592 | kfree_skb(packet->skb); | ||
1557 | break; | 1593 | break; |
1558 | } | 1594 | } |
1559 | 1595 | ||
1560 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); | 1596 | IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); |
1561 | 1597 | ||
1562 | skb->dev = iwm_to_ndev(iwm); | 1598 | ndev->stats.rx_packets++; |
1599 | ndev->stats.rx_bytes += skb->len; | ||
1600 | |||
1563 | skb->protocol = eth_type_trans(skb, ndev); | 1601 | skb->protocol = eth_type_trans(skb, ndev); |
1564 | skb->ip_summed = CHECKSUM_NONE; | 1602 | skb->ip_summed = CHECKSUM_NONE; |
1565 | memset(skb->cb, 0, sizeof(skb->cb)); | 1603 | memset(skb->cb, 0, sizeof(skb->cb)); |
1566 | 1604 | ||
1567 | ndev->stats.rx_packets++; | ||
1568 | ndev->stats.rx_bytes += skb->len; | ||
1569 | |||
1570 | if (netif_rx_ni(skb) == NET_RX_DROP) { | 1605 | if (netif_rx_ni(skb) == NET_RX_DROP) { |
1571 | IWM_ERR(iwm, "Packet dropped\n"); | 1606 | IWM_ERR(iwm, "Packet dropped\n"); |
1572 | ndev->stats.rx_dropped++; | 1607 | ndev->stats.rx_dropped++; |
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig index 30aa9d48d67e..0485c9957575 100644 --- a/drivers/net/wireless/libertas/Kconfig +++ b/drivers/net/wireless/libertas/Kconfig | |||
@@ -37,3 +37,9 @@ config LIBERTAS_DEBUG | |||
37 | depends on LIBERTAS | 37 | depends on LIBERTAS |
38 | ---help--- | 38 | ---help--- |
39 | Debugging support. | 39 | Debugging support. |
40 | |||
41 | config LIBERTAS_MESH | ||
42 | bool "Enable mesh support" | ||
43 | depends on LIBERTAS | ||
44 | help | ||
45 | This enables Libertas' MESH support, used by e.g. the OLPC people. | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index b188cd97a053..45e870e33117 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -5,11 +5,11 @@ libertas-y += cmdresp.o | |||
5 | libertas-y += debugfs.o | 5 | libertas-y += debugfs.o |
6 | libertas-y += ethtool.o | 6 | libertas-y += ethtool.o |
7 | libertas-y += main.o | 7 | libertas-y += main.o |
8 | libertas-y += mesh.o | ||
9 | libertas-y += rx.o | 8 | libertas-y += rx.o |
10 | libertas-y += scan.o | 9 | libertas-y += scan.o |
11 | libertas-y += tx.o | 10 | libertas-y += tx.o |
12 | libertas-y += wext.o | 11 | libertas-y += wext.o |
12 | libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o | ||
13 | 13 | ||
14 | usb8xxx-objs += if_usb.o | 14 | usb8xxx-objs += if_usb.o |
15 | libertas_cs-objs += if_cs.o | 15 | libertas_cs-objs += if_cs.o |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 751067369ba8..5e650f358415 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -390,10 +390,8 @@ int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | |||
390 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | 390 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); |
391 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | 391 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); |
392 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | 392 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); |
393 | if (!ret && cmd_action == CMD_ACT_GET) { | 393 | if (!ret && cmd_action == CMD_ACT_GET) |
394 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
395 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | 394 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); |
396 | } | ||
397 | 395 | ||
398 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 396 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
399 | return ret; | 397 | return ret; |
@@ -807,8 +805,7 @@ static int lbs_try_associate(struct lbs_private *priv, | |||
807 | } | 805 | } |
808 | 806 | ||
809 | /* Use short preamble only when both the BSS and firmware support it */ | 807 | /* Use short preamble only when both the BSS and firmware support it */ |
810 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 808 | if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) |
811 | (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
812 | preamble = RADIO_PREAMBLE_SHORT; | 809 | preamble = RADIO_PREAMBLE_SHORT; |
813 | 810 | ||
814 | ret = lbs_set_radio(priv, preamble, 1); | 811 | ret = lbs_set_radio(priv, preamble, 1); |
@@ -939,8 +936,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
939 | } | 936 | } |
940 | 937 | ||
941 | /* Use short preamble only when both the BSS and firmware support it */ | 938 | /* Use short preamble only when both the BSS and firmware support it */ |
942 | if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && | 939 | if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { |
943 | (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { | ||
944 | lbs_deb_join("AdhocJoin: Short preamble\n"); | 940 | lbs_deb_join("AdhocJoin: Short preamble\n"); |
945 | preamble = RADIO_PREAMBLE_SHORT; | 941 | preamble = RADIO_PREAMBLE_SHORT; |
946 | } | 942 | } |
@@ -1049,7 +1045,7 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
1049 | struct assoc_request *assoc_req) | 1045 | struct assoc_request *assoc_req) |
1050 | { | 1046 | { |
1051 | struct cmd_ds_802_11_ad_hoc_start cmd; | 1047 | struct cmd_ds_802_11_ad_hoc_start cmd; |
1052 | u8 preamble = RADIO_PREAMBLE_LONG; | 1048 | u8 preamble = RADIO_PREAMBLE_SHORT; |
1053 | size_t ratesize = 0; | 1049 | size_t ratesize = 0; |
1054 | u16 tmpcap = 0; | 1050 | u16 tmpcap = 0; |
1055 | int ret = 0; | 1051 | int ret = 0; |
@@ -1057,11 +1053,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
1057 | 1053 | ||
1058 | lbs_deb_enter(LBS_DEB_ASSOC); | 1054 | lbs_deb_enter(LBS_DEB_ASSOC); |
1059 | 1055 | ||
1060 | if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { | ||
1061 | lbs_deb_join("ADHOC_START: Will use short preamble\n"); | ||
1062 | preamble = RADIO_PREAMBLE_SHORT; | ||
1063 | } | ||
1064 | |||
1065 | ret = lbs_set_radio(priv, preamble, 1); | 1056 | ret = lbs_set_radio(priv, preamble, 1); |
1066 | if (ret) | 1057 | if (ret) |
1067 | goto out; | 1058 | goto out; |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 42611bea76a3..82371ef39524 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -143,19 +143,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
143 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", | 143 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", |
144 | cmd.hwifversion, cmd.version); | 144 | cmd.hwifversion, cmd.version); |
145 | 145 | ||
146 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
147 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
148 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
149 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
150 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
151 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
152 | priv->mesh_fw_ver = MESH_FW_OLD; | ||
153 | else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
154 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) | ||
155 | priv->mesh_fw_ver = MESH_FW_NEW; | ||
156 | else | ||
157 | priv->mesh_fw_ver = MESH_NONE; | ||
158 | |||
159 | /* Clamp region code to 8-bit since FW spec indicates that it should | 146 | /* Clamp region code to 8-bit since FW spec indicates that it should |
160 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware | 147 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware |
161 | * returns non-zero high 8 bits here. | 148 | * returns non-zero high 8 bits here. |
@@ -855,9 +842,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) | |||
855 | if (priv->fwrelease < 0x09000000) { | 842 | if (priv->fwrelease < 0x09000000) { |
856 | switch (preamble) { | 843 | switch (preamble) { |
857 | case RADIO_PREAMBLE_SHORT: | 844 | case RADIO_PREAMBLE_SHORT: |
858 | if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
859 | goto out; | ||
860 | /* Fall through */ | ||
861 | case RADIO_PREAMBLE_AUTO: | 845 | case RADIO_PREAMBLE_AUTO: |
862 | case RADIO_PREAMBLE_LONG: | 846 | case RADIO_PREAMBLE_LONG: |
863 | cmd.control = cpu_to_le16(preamble); | 847 | cmd.control = cpu_to_le16(preamble); |
@@ -1011,6 +995,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1011 | ret = 0; | 995 | ret = 0; |
1012 | break; | 996 | break; |
1013 | 997 | ||
998 | #ifdef CONFIG_LIBERTAS_MESH | ||
999 | |||
1014 | case CMD_BT_ACCESS: | 1000 | case CMD_BT_ACCESS: |
1015 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); | 1001 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); |
1016 | break; | 1002 | break; |
@@ -1019,6 +1005,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1019 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); | 1005 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); |
1020 | break; | 1006 | break; |
1021 | 1007 | ||
1008 | #endif | ||
1009 | |||
1022 | case CMD_802_11_BEACON_CTRL: | 1010 | case CMD_802_11_BEACON_CTRL: |
1023 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1011 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1024 | break; | 1012 | break; |
@@ -1317,7 +1305,7 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1317 | if ((priv->psmode != LBS802_11POWERMODECAM) && | 1305 | if ((priv->psmode != LBS802_11POWERMODECAM) && |
1318 | (priv->psstate == PS_STATE_FULL_POWER) && | 1306 | (priv->psstate == PS_STATE_FULL_POWER) && |
1319 | ((priv->connect_status == LBS_CONNECTED) || | 1307 | ((priv->connect_status == LBS_CONNECTED) || |
1320 | (priv->mesh_connect_status == LBS_CONNECTED))) { | 1308 | lbs_mesh_connected(priv))) { |
1321 | if (priv->secinfo.WPAenabled || | 1309 | if (priv->secinfo.WPAenabled || |
1322 | priv->secinfo.WPA2enabled) { | 1310 | priv->secinfo.WPA2enabled) { |
1323 | /* check for valid WPA group keys */ | 1311 | /* check for valid WPA group keys */ |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 2862748aef70..cb4138a55fdf 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -110,18 +110,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); | |||
110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); | 110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); |
111 | 111 | ||
112 | 112 | ||
113 | /* Mesh related */ | ||
114 | |||
115 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
116 | struct cmd_ds_mesh_access *cmd); | ||
117 | |||
118 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
119 | struct cmd_ds_mesh_config *cmd, | ||
120 | uint16_t action, uint16_t type); | ||
121 | |||
122 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
123 | |||
124 | |||
125 | /* Commands only used in wext.c, assoc. and scan.c */ | 113 | /* Commands only used in wext.c, assoc. and scan.c */ |
126 | 114 | ||
127 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 115 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 21d57690c20a..0334a58820ee 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -485,20 +485,8 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
485 | break; | 485 | break; |
486 | 486 | ||
487 | case MACREG_INT_CODE_MESH_AUTO_STARTED: | 487 | case MACREG_INT_CODE_MESH_AUTO_STARTED: |
488 | /* Ignore spurious autostart events if autostart is disabled */ | 488 | /* Ignore spurious autostart events */ |
489 | if (!priv->mesh_autostart_enabled) { | 489 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); |
490 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); | ||
491 | break; | ||
492 | } | ||
493 | lbs_pr_info("EVENT: MESH_AUTO_STARTED\n"); | ||
494 | priv->mesh_connect_status = LBS_CONNECTED; | ||
495 | if (priv->mesh_open) { | ||
496 | netif_carrier_on(priv->mesh_dev); | ||
497 | if (!priv->tx_pending_len) | ||
498 | netif_wake_queue(priv->mesh_dev); | ||
499 | } | ||
500 | priv->mode = IW_MODE_ADHOC; | ||
501 | schedule_work(&priv->sync_channel); | ||
502 | break; | 490 | break; |
503 | 491 | ||
504 | default: | 492 | default: |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 6b6ea9f7bf5b..ea3f10ef4e00 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -397,13 +397,6 @@ enum KEY_INFO_WPA { | |||
397 | KEY_INFO_WPA_ENABLED = 0x04 | 397 | KEY_INFO_WPA_ENABLED = 0x04 |
398 | }; | 398 | }; |
399 | 399 | ||
400 | /** mesh_fw_ver */ | ||
401 | enum _mesh_fw_ver { | ||
402 | MESH_NONE = 0, /* MESH is not supported */ | ||
403 | MESH_FW_OLD, /* MESH is supported in FW V5 */ | ||
404 | MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ | ||
405 | }; | ||
406 | |||
407 | /* Default values for fwt commands. */ | 400 | /* Default values for fwt commands. */ |
408 | #define FWT_DEFAULT_METRIC 0 | 401 | #define FWT_DEFAULT_METRIC 0 |
409 | #define FWT_DEFAULT_DIR 1 | 402 | #define FWT_DEFAULT_DIR 1 |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 05bb298dfae9..c348aff8f309 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -39,15 +39,14 @@ struct lbs_private { | |||
39 | 39 | ||
40 | /* Mesh */ | 40 | /* Mesh */ |
41 | struct net_device *mesh_dev; /* Virtual device */ | 41 | struct net_device *mesh_dev; /* Virtual device */ |
42 | #ifdef CONFIG_LIBERTAS_MESH | ||
42 | u32 mesh_connect_status; | 43 | u32 mesh_connect_status; |
43 | struct lbs_mesh_stats mstats; | 44 | struct lbs_mesh_stats mstats; |
44 | int mesh_open; | 45 | int mesh_open; |
45 | int mesh_fw_ver; | ||
46 | int mesh_autostart_enabled; | ||
47 | uint16_t mesh_tlv; | 46 | uint16_t mesh_tlv; |
48 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; | 47 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; |
49 | u8 mesh_ssid_len; | 48 | u8 mesh_ssid_len; |
50 | struct work_struct sync_channel; | 49 | #endif |
51 | 50 | ||
52 | /* Monitor mode */ | 51 | /* Monitor mode */ |
53 | struct net_device *rtap_net_dev; | 52 | struct net_device *rtap_net_dev; |
@@ -176,9 +175,7 @@ struct lbs_private { | |||
176 | struct bss_descriptor *networks; | 175 | struct bss_descriptor *networks; |
177 | struct assoc_request * pending_assoc_req; | 176 | struct assoc_request * pending_assoc_req; |
178 | struct assoc_request * in_progress_assoc_req; | 177 | struct assoc_request * in_progress_assoc_req; |
179 | u16 capability; | ||
180 | uint16_t enablehwauto; | 178 | uint16_t enablehwauto; |
181 | uint16_t ratebitmap; | ||
182 | 179 | ||
183 | /* ADHOC */ | 180 | /* ADHOC */ |
184 | u16 beacon_period; | 181 | u16 beacon_period; |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 63d020374c2b..3804a58d7f4e 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -114,9 +114,11 @@ const struct ethtool_ops lbs_ethtool_ops = { | |||
114 | .get_drvinfo = lbs_ethtool_get_drvinfo, | 114 | .get_drvinfo = lbs_ethtool_get_drvinfo, |
115 | .get_eeprom = lbs_ethtool_get_eeprom, | 115 | .get_eeprom = lbs_ethtool_get_eeprom, |
116 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, | 116 | .get_eeprom_len = lbs_ethtool_get_eeprom_len, |
117 | #ifdef CONFIG_LIBERTAS_MESH | ||
117 | .get_sset_count = lbs_mesh_ethtool_get_sset_count, | 118 | .get_sset_count = lbs_mesh_ethtool_get_sset_count, |
118 | .get_ethtool_stats = lbs_mesh_ethtool_get_stats, | 119 | .get_ethtool_stats = lbs_mesh_ethtool_get_stats, |
119 | .get_strings = lbs_mesh_ethtool_get_strings, | 120 | .get_strings = lbs_mesh_ethtool_get_strings, |
121 | #endif | ||
120 | .get_wol = lbs_ethtool_get_wol, | 122 | .get_wol = lbs_ethtool_get_wol, |
121 | .set_wol = lbs_ethtool_set_wol, | 123 | .set_wol = lbs_ethtool_set_wol, |
122 | }; | 124 | }; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index c2975c8e2f21..60bde1233a30 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -123,7 +123,7 @@ static ssize_t lbs_rtap_set(struct device *dev, | |||
123 | if (priv->monitormode == monitor_mode) | 123 | if (priv->monitormode == monitor_mode) |
124 | return strlen(buf); | 124 | return strlen(buf); |
125 | if (!priv->monitormode) { | 125 | if (!priv->monitormode) { |
126 | if (priv->infra_open || priv->mesh_open) | 126 | if (priv->infra_open || lbs_mesh_open(priv)) |
127 | return -EBUSY; | 127 | return -EBUSY; |
128 | if (priv->mode == IW_MODE_INFRA) | 128 | if (priv->mode == IW_MODE_INFRA) |
129 | lbs_cmd_80211_deauthenticate(priv, | 129 | lbs_cmd_80211_deauthenticate(priv, |
@@ -622,7 +622,7 @@ static int lbs_thread(void *data) | |||
622 | if (priv->connect_status == LBS_CONNECTED) | 622 | if (priv->connect_status == LBS_CONNECTED) |
623 | netif_wake_queue(priv->dev); | 623 | netif_wake_queue(priv->dev); |
624 | if (priv->mesh_dev && | 624 | if (priv->mesh_dev && |
625 | priv->mesh_connect_status == LBS_CONNECTED) | 625 | lbs_mesh_connected(priv)) |
626 | netif_wake_queue(priv->mesh_dev); | 626 | netif_wake_queue(priv->mesh_dev); |
627 | } | 627 | } |
628 | } | 628 | } |
@@ -809,18 +809,6 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | |||
809 | return 0; | 809 | return 0; |
810 | } | 810 | } |
811 | 811 | ||
812 | static void lbs_sync_channel_worker(struct work_struct *work) | ||
813 | { | ||
814 | struct lbs_private *priv = container_of(work, struct lbs_private, | ||
815 | sync_channel); | ||
816 | |||
817 | lbs_deb_enter(LBS_DEB_MAIN); | ||
818 | if (lbs_update_channel(priv)) | ||
819 | lbs_pr_info("Channel synchronization failed."); | ||
820 | lbs_deb_leave(LBS_DEB_MAIN); | ||
821 | } | ||
822 | |||
823 | |||
824 | static int lbs_init_adapter(struct lbs_private *priv) | 812 | static int lbs_init_adapter(struct lbs_private *priv) |
825 | { | 813 | { |
826 | size_t bufsize; | 814 | size_t bufsize; |
@@ -848,14 +836,12 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
848 | memset(priv->current_addr, 0xff, ETH_ALEN); | 836 | memset(priv->current_addr, 0xff, ETH_ALEN); |
849 | 837 | ||
850 | priv->connect_status = LBS_DISCONNECTED; | 838 | priv->connect_status = LBS_DISCONNECTED; |
851 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
852 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 839 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
853 | priv->mode = IW_MODE_INFRA; | 840 | priv->mode = IW_MODE_INFRA; |
854 | priv->channel = DEFAULT_AD_HOC_CHANNEL; | 841 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
855 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 842 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
856 | priv->radio_on = 1; | 843 | priv->radio_on = 1; |
857 | priv->enablehwauto = 1; | 844 | priv->enablehwauto = 1; |
858 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
859 | priv->psmode = LBS802_11POWERMODECAM; | 845 | priv->psmode = LBS802_11POWERMODECAM; |
860 | priv->psstate = PS_STATE_FULL_POWER; | 846 | priv->psstate = PS_STATE_FULL_POWER; |
861 | priv->is_deep_sleep = 0; | 847 | priv->is_deep_sleep = 0; |
@@ -998,11 +984,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
998 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 984 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
999 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 985 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
1000 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | 986 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); |
1001 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | ||
1002 | |||
1003 | priv->mesh_open = 0; | ||
1004 | sprintf(priv->mesh_ssid, "mesh"); | ||
1005 | priv->mesh_ssid_len = 4; | ||
1006 | 987 | ||
1007 | priv->wol_criteria = 0xffffffff; | 988 | priv->wol_criteria = 0xffffffff; |
1008 | priv->wol_gpio = 0xff; | 989 | priv->wol_gpio = 0xff; |
@@ -1076,6 +1057,17 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1076 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 1057 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1077 | 1058 | ||
1078 | 1059 | ||
1060 | static int lbs_rtap_supported(struct lbs_private *priv) | ||
1061 | { | ||
1062 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
1063 | return 1; | ||
1064 | |||
1065 | /* newer firmware use a capability mask */ | ||
1066 | return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
1067 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); | ||
1068 | } | ||
1069 | |||
1070 | |||
1079 | int lbs_start_card(struct lbs_private *priv) | 1071 | int lbs_start_card(struct lbs_private *priv) |
1080 | { | 1072 | { |
1081 | struct net_device *dev = priv->dev; | 1073 | struct net_device *dev = priv->dev; |
@@ -1095,12 +1087,14 @@ int lbs_start_card(struct lbs_private *priv) | |||
1095 | 1087 | ||
1096 | lbs_update_channel(priv); | 1088 | lbs_update_channel(priv); |
1097 | 1089 | ||
1090 | lbs_init_mesh(priv); | ||
1091 | |||
1098 | /* | 1092 | /* |
1099 | * While rtap isn't related to mesh, only mesh-enabled | 1093 | * While rtap isn't related to mesh, only mesh-enabled |
1100 | * firmware implements the rtap functionality via | 1094 | * firmware implements the rtap functionality via |
1101 | * CMD_802_11_MONITOR_MODE. | 1095 | * CMD_802_11_MONITOR_MODE. |
1102 | */ | 1096 | */ |
1103 | if (lbs_init_mesh(priv)) { | 1097 | if (lbs_rtap_supported(priv)) { |
1104 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) | 1098 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) |
1105 | lbs_pr_err("cannot register lbs_rtap attribute\n"); | 1099 | lbs_pr_err("cannot register lbs_rtap attribute\n"); |
1106 | } | 1100 | } |
@@ -1134,7 +1128,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1134 | netif_carrier_off(dev); | 1128 | netif_carrier_off(dev); |
1135 | 1129 | ||
1136 | lbs_debugfs_remove_one(priv); | 1130 | lbs_debugfs_remove_one(priv); |
1137 | if (lbs_deinit_mesh(priv)) | 1131 | lbs_deinit_mesh(priv); |
1132 | |||
1133 | if (lbs_rtap_supported(priv)) | ||
1138 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1134 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1139 | 1135 | ||
1140 | /* Delete the timeout of the currently processing command */ | 1136 | /* Delete the timeout of the currently processing command */ |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 2f91c9b808af..954cd00f7452 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <linux/moduleparam.h> | ||
2 | #include <linux/delay.h> | 1 | #include <linux/delay.h> |
3 | #include <linux/etherdevice.h> | 2 | #include <linux/etherdevice.h> |
4 | #include <linux/netdevice.h> | 3 | #include <linux/netdevice.h> |
@@ -196,7 +195,14 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
196 | 195 | ||
197 | lbs_deb_enter(LBS_DEB_MESH); | 196 | lbs_deb_enter(LBS_DEB_MESH); |
198 | 197 | ||
199 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 198 | priv->mesh_connect_status = LBS_DISCONNECTED; |
199 | |||
200 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
201 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
202 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
203 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
204 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
205 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { | ||
200 | /* Enable mesh, if supported, and work out which TLV it uses. | 206 | /* Enable mesh, if supported, and work out which TLV it uses. |
201 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX | 207 | 0x100 + 291 is an unofficial value used in 5.110.20.pXX |
202 | 0x100 + 37 is the official value used in 5.110.21.pXX | 208 | 0x100 + 37 is the official value used in 5.110.21.pXX |
@@ -218,7 +224,9 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
218 | priv->channel)) | 224 | priv->channel)) |
219 | priv->mesh_tlv = 0; | 225 | priv->mesh_tlv = 0; |
220 | } | 226 | } |
221 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | 227 | } else |
228 | if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
229 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { | ||
222 | /* 10.0.0.pXX new firmwares should succeed with TLV | 230 | /* 10.0.0.pXX new firmwares should succeed with TLV |
223 | * 0x100+37; Do not invoke command with old TLV. | 231 | * 0x100+37; Do not invoke command with old TLV. |
224 | */ | 232 | */ |
@@ -227,7 +235,12 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
227 | priv->channel)) | 235 | priv->channel)) |
228 | priv->mesh_tlv = 0; | 236 | priv->mesh_tlv = 0; |
229 | } | 237 | } |
238 | |||
239 | |||
230 | if (priv->mesh_tlv) { | 240 | if (priv->mesh_tlv) { |
241 | sprintf(priv->mesh_ssid, "mesh"); | ||
242 | priv->mesh_ssid_len = 4; | ||
243 | |||
231 | lbs_add_mesh(priv); | 244 | lbs_add_mesh(priv); |
232 | 245 | ||
233 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) | 246 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) |
@@ -416,10 +429,10 @@ struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, | |||
416 | struct net_device *dev, struct rxpd *rxpd) | 429 | struct net_device *dev, struct rxpd *rxpd) |
417 | { | 430 | { |
418 | if (priv->mesh_dev) { | 431 | if (priv->mesh_dev) { |
419 | if (priv->mesh_fw_ver == MESH_FW_OLD) { | 432 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { |
420 | if (rxpd->rx_control & RxPD_MESH_FRAME) | 433 | if (rxpd->rx_control & RxPD_MESH_FRAME) |
421 | dev = priv->mesh_dev; | 434 | dev = priv->mesh_dev; |
422 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | 435 | } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { |
423 | if (rxpd->u.bss.bss_num == MESH_IFACE_ID) | 436 | if (rxpd->u.bss.bss_num == MESH_IFACE_ID) |
424 | dev = priv->mesh_dev; | 437 | dev = priv->mesh_dev; |
425 | } | 438 | } |
@@ -432,9 +445,9 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
432 | struct net_device *dev, struct txpd *txpd) | 445 | struct net_device *dev, struct txpd *txpd) |
433 | { | 446 | { |
434 | if (dev == priv->mesh_dev) { | 447 | if (dev == priv->mesh_dev) { |
435 | if (priv->mesh_fw_ver == MESH_FW_OLD) | 448 | if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) |
436 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); | 449 | txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); |
437 | else if (priv->mesh_fw_ver == MESH_FW_NEW) | 450 | else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) |
438 | txpd->u.bss.bss_num = MESH_IFACE_ID; | 451 | txpd->u.bss.bss_num = MESH_IFACE_ID; |
439 | } | 452 | } |
440 | } | 453 | } |
@@ -538,7 +551,7 @@ static int __lbs_mesh_config_send(struct lbs_private *priv, | |||
538 | * Command id is 0xac for v10 FW along with mesh interface | 551 | * Command id is 0xac for v10 FW along with mesh interface |
539 | * id in bits 14-13-12. | 552 | * id in bits 14-13-12. |
540 | */ | 553 | */ |
541 | if (priv->mesh_fw_ver == MESH_FW_NEW) | 554 | if (priv->mesh_tlv == TLV_TYPE_MESH_ID) |
542 | command = CMD_MESH_CONFIG | | 555 | command = CMD_MESH_CONFIG | |
543 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | 556 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); |
544 | 557 | ||
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index fea9b5d005fc..e2573303a328 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #include <net/lib80211.h> | 9 | #include <net/lib80211.h> |
10 | 10 | ||
11 | 11 | ||
12 | #ifdef CONFIG_LIBERTAS_MESH | ||
13 | |||
12 | /* Mesh statistics */ | 14 | /* Mesh statistics */ |
13 | struct lbs_mesh_stats { | 15 | struct lbs_mesh_stats { |
14 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ | 16 | u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ |
@@ -46,11 +48,20 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, | |||
46 | /* Command handling */ | 48 | /* Command handling */ |
47 | 49 | ||
48 | struct cmd_ds_command; | 50 | struct cmd_ds_command; |
51 | struct cmd_ds_mesh_access; | ||
52 | struct cmd_ds_mesh_config; | ||
49 | 53 | ||
50 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | 54 | int lbs_cmd_bt_access(struct cmd_ds_command *cmd, |
51 | u16 cmd_action, void *pdata_buf); | 55 | u16 cmd_action, void *pdata_buf); |
52 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | 56 | int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, |
53 | u16 cmd_action, void *pdata_buf); | 57 | u16 cmd_action, void *pdata_buf); |
58 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
59 | struct cmd_ds_mesh_access *cmd); | ||
60 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
61 | struct cmd_ds_mesh_config *cmd, | ||
62 | uint16_t action, uint16_t type); | ||
63 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
64 | |||
54 | 65 | ||
55 | 66 | ||
56 | /* Persistent configuration */ | 67 | /* Persistent configuration */ |
@@ -75,4 +86,25 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, | |||
75 | uint32_t stringset, uint8_t *s); | 86 | uint32_t stringset, uint8_t *s); |
76 | 87 | ||
77 | 88 | ||
89 | /* Accessors */ | ||
90 | |||
91 | #define lbs_mesh_open(priv) (priv->mesh_open) | ||
92 | #define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) | ||
93 | |||
94 | #else | ||
95 | |||
96 | #define lbs_init_mesh(priv) | ||
97 | #define lbs_deinit_mesh(priv) | ||
98 | #define lbs_add_mesh(priv) | ||
99 | #define lbs_remove_mesh(priv) | ||
100 | #define lbs_mesh_set_dev(priv, dev, rxpd) (dev) | ||
101 | #define lbs_mesh_set_txpd(priv, dev, txpd) | ||
102 | #define lbs_mesh_config(priv, enable, chan) | ||
103 | #define lbs_mesh_open(priv) (0) | ||
104 | #define lbs_mesh_connected(priv) (0) | ||
105 | |||
106 | #endif | ||
107 | |||
108 | |||
109 | |||
78 | #endif | 110 | #endif |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index c6a6c042b82f..4a0c3e3cd3b1 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -640,7 +640,7 @@ out: | |||
640 | if (!priv->tx_pending_len) | 640 | if (!priv->tx_pending_len) |
641 | netif_wake_queue(priv->dev); | 641 | netif_wake_queue(priv->dev); |
642 | } | 642 | } |
643 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { | 643 | if (priv->mesh_dev && lbs_mesh_connected(priv)) { |
644 | netif_carrier_on(priv->mesh_dev); | 644 | netif_carrier_on(priv->mesh_dev); |
645 | if (!priv->tx_pending_len) | 645 | if (!priv->tx_pending_len) |
646 | netif_wake_queue(priv->mesh_dev); | 646 | netif_wake_queue(priv->mesh_dev); |
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 315d1ce286ca..52d244ea3d97 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -198,7 +198,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) | |||
198 | if (priv->connect_status == LBS_CONNECTED) | 198 | if (priv->connect_status == LBS_CONNECTED) |
199 | netif_wake_queue(priv->dev); | 199 | netif_wake_queue(priv->dev); |
200 | 200 | ||
201 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) | 201 | if (priv->mesh_dev && lbs_mesh_connected(priv)) |
202 | netif_wake_queue(priv->mesh_dev); | 202 | netif_wake_queue(priv->mesh_dev); |
203 | } | 203 | } |
204 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); | 204 | EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 4b1aab593a84..71f88a08e090 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -192,7 +192,7 @@ static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) | |||
192 | lbs_deb_enter(LBS_DEB_WEXT); | 192 | lbs_deb_enter(LBS_DEB_WEXT); |
193 | 193 | ||
194 | if ((priv->connect_status != LBS_CONNECTED) && | 194 | if ((priv->connect_status != LBS_CONNECTED) && |
195 | (priv->mesh_connect_status != LBS_CONNECTED)) | 195 | !lbs_mesh_connected(priv)) |
196 | memcpy(rates, lbs_bg_rates, MAX_RATES); | 196 | memcpy(rates, lbs_bg_rates, MAX_RATES); |
197 | else | 197 | else |
198 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); | 198 | memcpy(rates, priv->curbssparams.rates, MAX_RATES); |
@@ -298,6 +298,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | #ifdef CONFIG_LIBERTAS_MESH | ||
301 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | 302 | static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, |
302 | struct iw_point *dwrq, char *extra) | 303 | struct iw_point *dwrq, char *extra) |
303 | { | 304 | { |
@@ -307,7 +308,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
307 | 308 | ||
308 | /* Use nickname to indicate that mesh is on */ | 309 | /* Use nickname to indicate that mesh is on */ |
309 | 310 | ||
310 | if (priv->mesh_connect_status == LBS_CONNECTED) { | 311 | if (lbs_mesh_connected(priv)) { |
311 | strncpy(extra, "Mesh", 12); | 312 | strncpy(extra, "Mesh", 12); |
312 | extra[12] = '\0'; | 313 | extra[12] = '\0'; |
313 | dwrq->length = strlen(extra); | 314 | dwrq->length = strlen(extra); |
@@ -321,6 +322,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, | |||
321 | lbs_deb_leave(LBS_DEB_WEXT); | 322 | lbs_deb_leave(LBS_DEB_WEXT); |
322 | return 0; | 323 | return 0; |
323 | } | 324 | } |
325 | #endif | ||
324 | 326 | ||
325 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, | 327 | static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, |
326 | struct iw_param *vwrq, char *extra) | 328 | struct iw_param *vwrq, char *extra) |
@@ -422,6 +424,7 @@ static int lbs_get_mode(struct net_device *dev, | |||
422 | return 0; | 424 | return 0; |
423 | } | 425 | } |
424 | 426 | ||
427 | #ifdef CONFIG_LIBERTAS_MESH | ||
425 | static int mesh_wlan_get_mode(struct net_device *dev, | 428 | static int mesh_wlan_get_mode(struct net_device *dev, |
426 | struct iw_request_info *info, u32 * uwrq, | 429 | struct iw_request_info *info, u32 * uwrq, |
427 | char *extra) | 430 | char *extra) |
@@ -433,6 +436,7 @@ static int mesh_wlan_get_mode(struct net_device *dev, | |||
433 | lbs_deb_leave(LBS_DEB_WEXT); | 436 | lbs_deb_leave(LBS_DEB_WEXT); |
434 | return 0; | 437 | return 0; |
435 | } | 438 | } |
439 | #endif | ||
436 | 440 | ||
437 | static int lbs_get_txpow(struct net_device *dev, | 441 | static int lbs_get_txpow(struct net_device *dev, |
438 | struct iw_request_info *info, | 442 | struct iw_request_info *info, |
@@ -863,7 +867,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
863 | 867 | ||
864 | /* If we're not associated, all quality values are meaningless */ | 868 | /* If we're not associated, all quality values are meaningless */ |
865 | if ((priv->connect_status != LBS_CONNECTED) && | 869 | if ((priv->connect_status != LBS_CONNECTED) && |
866 | (priv->mesh_connect_status != LBS_CONNECTED)) | 870 | !lbs_mesh_connected(priv)) |
867 | goto out; | 871 | goto out; |
868 | 872 | ||
869 | /* Quality by RSSI */ | 873 | /* Quality by RSSI */ |
@@ -1010,6 +1014,7 @@ out: | |||
1010 | return ret; | 1014 | return ret; |
1011 | } | 1015 | } |
1012 | 1016 | ||
1017 | #ifdef CONFIG_LIBERTAS_MESH | ||
1013 | static int lbs_mesh_set_freq(struct net_device *dev, | 1018 | static int lbs_mesh_set_freq(struct net_device *dev, |
1014 | struct iw_request_info *info, | 1019 | struct iw_request_info *info, |
1015 | struct iw_freq *fwrq, char *extra) | 1020 | struct iw_freq *fwrq, char *extra) |
@@ -1061,6 +1066,7 @@ out: | |||
1061 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 1066 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
1062 | return ret; | 1067 | return ret; |
1063 | } | 1068 | } |
1069 | #endif | ||
1064 | 1070 | ||
1065 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | 1071 | static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, |
1066 | struct iw_param *vwrq, char *extra) | 1072 | struct iw_param *vwrq, char *extra) |
@@ -2108,6 +2114,7 @@ out: | |||
2108 | return ret; | 2114 | return ret; |
2109 | } | 2115 | } |
2110 | 2116 | ||
2117 | #ifdef CONFIG_LIBERTAS_MESH | ||
2111 | static int lbs_mesh_get_essid(struct net_device *dev, | 2118 | static int lbs_mesh_get_essid(struct net_device *dev, |
2112 | struct iw_request_info *info, | 2119 | struct iw_request_info *info, |
2113 | struct iw_point *dwrq, char *extra) | 2120 | struct iw_point *dwrq, char *extra) |
@@ -2161,6 +2168,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2161 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 2168 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
2162 | return ret; | 2169 | return ret; |
2163 | } | 2170 | } |
2171 | #endif | ||
2164 | 2172 | ||
2165 | /** | 2173 | /** |
2166 | * @brief Connect to the AP or Ad-hoc Network with specific bssid | 2174 | * @brief Connect to the AP or Ad-hoc Network with specific bssid |
@@ -2267,7 +2275,13 @@ static const iw_handler lbs_handler[] = { | |||
2267 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2275 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2268 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2276 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2269 | }; | 2277 | }; |
2278 | struct iw_handler_def lbs_handler_def = { | ||
2279 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2280 | .standard = (iw_handler *) lbs_handler, | ||
2281 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2282 | }; | ||
2270 | 2283 | ||
2284 | #ifdef CONFIG_LIBERTAS_MESH | ||
2271 | static const iw_handler mesh_wlan_handler[] = { | 2285 | static const iw_handler mesh_wlan_handler[] = { |
2272 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ | 2286 | (iw_handler) NULL, /* SIOCSIWCOMMIT */ |
2273 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ | 2287 | (iw_handler) lbs_get_name, /* SIOCGIWNAME */ |
@@ -2325,14 +2339,10 @@ static const iw_handler mesh_wlan_handler[] = { | |||
2325 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ | 2339 | (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ |
2326 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | 2340 | (iw_handler) NULL, /* SIOCSIWPMKSA */ |
2327 | }; | 2341 | }; |
2328 | struct iw_handler_def lbs_handler_def = { | ||
2329 | .num_standard = ARRAY_SIZE(lbs_handler), | ||
2330 | .standard = (iw_handler *) lbs_handler, | ||
2331 | .get_wireless_stats = lbs_get_wireless_stats, | ||
2332 | }; | ||
2333 | 2342 | ||
2334 | struct iw_handler_def mesh_handler_def = { | 2343 | struct iw_handler_def mesh_handler_def = { |
2335 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), | 2344 | .num_standard = ARRAY_SIZE(mesh_wlan_handler), |
2336 | .standard = (iw_handler *) mesh_wlan_handler, | 2345 | .standard = (iw_handler *) mesh_wlan_handler, |
2337 | .get_wireless_stats = lbs_get_wireless_stats, | 2346 | .get_wireless_stats = lbs_get_wireless_stats, |
2338 | }; | 2347 | }; |
2348 | #endif | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 88e41176e7fd..718a5f198c30 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -436,6 +436,38 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, | |||
436 | } | 436 | } |
437 | 437 | ||
438 | 438 | ||
439 | struct mac80211_hwsim_addr_match_data { | ||
440 | bool ret; | ||
441 | const u8 *addr; | ||
442 | }; | ||
443 | |||
444 | static void mac80211_hwsim_addr_iter(void *data, u8 *mac, | ||
445 | struct ieee80211_vif *vif) | ||
446 | { | ||
447 | struct mac80211_hwsim_addr_match_data *md = data; | ||
448 | if (memcmp(mac, md->addr, ETH_ALEN) == 0) | ||
449 | md->ret = true; | ||
450 | } | ||
451 | |||
452 | |||
453 | static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, | ||
454 | const u8 *addr) | ||
455 | { | ||
456 | struct mac80211_hwsim_addr_match_data md; | ||
457 | |||
458 | if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0) | ||
459 | return true; | ||
460 | |||
461 | md.ret = false; | ||
462 | md.addr = addr; | ||
463 | ieee80211_iterate_active_interfaces_atomic(data->hw, | ||
464 | mac80211_hwsim_addr_iter, | ||
465 | &md); | ||
466 | |||
467 | return md.ret; | ||
468 | } | ||
469 | |||
470 | |||
439 | static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 471 | static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
440 | struct sk_buff *skb) | 472 | struct sk_buff *skb) |
441 | { | 473 | { |
@@ -488,8 +520,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | |||
488 | if (nskb == NULL) | 520 | if (nskb == NULL) |
489 | continue; | 521 | continue; |
490 | 522 | ||
491 | if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr, | 523 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
492 | ETH_ALEN) == 0) | ||
493 | ack = true; | 524 | ack = true; |
494 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 525 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
495 | ieee80211_rx_irqsafe(data2->hw, nskb); | 526 | ieee80211_rx_irqsafe(data2->hw, nskb); |
@@ -618,12 +649,26 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
618 | { | 649 | { |
619 | struct mac80211_hwsim_data *data = hw->priv; | 650 | struct mac80211_hwsim_data *data = hw->priv; |
620 | struct ieee80211_conf *conf = &hw->conf; | 651 | struct ieee80211_conf *conf = &hw->conf; |
621 | 652 | static const char *chantypes[4] = { | |
622 | printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n", | 653 | [NL80211_CHAN_NO_HT] = "noht", |
654 | [NL80211_CHAN_HT20] = "ht20", | ||
655 | [NL80211_CHAN_HT40MINUS] = "ht40-", | ||
656 | [NL80211_CHAN_HT40PLUS] = "ht40+", | ||
657 | }; | ||
658 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
659 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
660 | [IEEE80211_SMPS_OFF] = "off", | ||
661 | [IEEE80211_SMPS_STATIC] = "static", | ||
662 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
663 | }; | ||
664 | |||
665 | printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", | ||
623 | wiphy_name(hw->wiphy), __func__, | 666 | wiphy_name(hw->wiphy), __func__, |
624 | conf->channel->center_freq, | 667 | conf->channel->center_freq, |
668 | chantypes[conf->channel_type], | ||
625 | !!(conf->flags & IEEE80211_CONF_IDLE), | 669 | !!(conf->flags & IEEE80211_CONF_IDLE), |
626 | !!(conf->flags & IEEE80211_CONF_PS)); | 670 | !!(conf->flags & IEEE80211_CONF_PS), |
671 | smps_modes[conf->smps_mode]); | ||
627 | 672 | ||
628 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 673 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
629 | 674 | ||
@@ -827,6 +872,31 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, | |||
827 | } | 872 | } |
828 | #endif | 873 | #endif |
829 | 874 | ||
875 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | ||
876 | struct ieee80211_vif *vif, | ||
877 | enum ieee80211_ampdu_mlme_action action, | ||
878 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
879 | { | ||
880 | switch (action) { | ||
881 | case IEEE80211_AMPDU_TX_START: | ||
882 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
883 | break; | ||
884 | case IEEE80211_AMPDU_TX_STOP: | ||
885 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
886 | break; | ||
887 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
888 | break; | ||
889 | case IEEE80211_AMPDU_RX_START: | ||
890 | case IEEE80211_AMPDU_RX_STOP: | ||
891 | break; | ||
892 | default: | ||
893 | return -EOPNOTSUPP; | ||
894 | } | ||
895 | |||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | |||
830 | static const struct ieee80211_ops mac80211_hwsim_ops = | 900 | static const struct ieee80211_ops mac80211_hwsim_ops = |
831 | { | 901 | { |
832 | .tx = mac80211_hwsim_tx, | 902 | .tx = mac80211_hwsim_tx, |
@@ -841,6 +911,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = | |||
841 | .set_tim = mac80211_hwsim_set_tim, | 911 | .set_tim = mac80211_hwsim_set_tim, |
842 | .conf_tx = mac80211_hwsim_conf_tx, | 912 | .conf_tx = mac80211_hwsim_conf_tx, |
843 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 913 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
914 | .ampdu_action = mac80211_hwsim_ampdu_action, | ||
844 | }; | 915 | }; |
845 | 916 | ||
846 | 917 | ||
@@ -1082,7 +1153,9 @@ static int __init init_mac80211_hwsim(void) | |||
1082 | BIT(NL80211_IFTYPE_MESH_POINT); | 1153 | BIT(NL80211_IFTYPE_MESH_POINT); |
1083 | 1154 | ||
1084 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1155 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
1085 | IEEE80211_HW_SIGNAL_DBM; | 1156 | IEEE80211_HW_SIGNAL_DBM | |
1157 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
1158 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; | ||
1086 | 1159 | ||
1087 | /* ask mac80211 to reserve space for magic */ | 1160 | /* ask mac80211 to reserve space for magic */ |
1088 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1161 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2ecbedb26e15..305c106fdc1c 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2594,23 +2594,9 @@ end: | |||
2594 | /* | 2594 | /* |
2595 | * driver/device initialization | 2595 | * driver/device initialization |
2596 | */ | 2596 | */ |
2597 | static int bcm4320a_early_init(struct usbnet *usbdev) | 2597 | static void rndis_copy_module_params(struct usbnet *usbdev) |
2598 | { | ||
2599 | /* bcm4320a doesn't handle configuration parameters well. Try | ||
2600 | * set any and you get partially zeroed mac and broken device. | ||
2601 | */ | ||
2602 | |||
2603 | return 0; | ||
2604 | } | ||
2605 | |||
2606 | static int bcm4320b_early_init(struct usbnet *usbdev) | ||
2607 | { | 2598 | { |
2608 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | 2599 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2609 | char buf[8]; | ||
2610 | |||
2611 | /* Early initialization settings, setting these won't have effect | ||
2612 | * if called after generic_rndis_bind(). | ||
2613 | */ | ||
2614 | 2600 | ||
2615 | priv->param_country[0] = modparam_country[0]; | 2601 | priv->param_country[0] = modparam_country[0]; |
2616 | priv->param_country[1] = modparam_country[1]; | 2602 | priv->param_country[1] = modparam_country[1]; |
@@ -2652,6 +2638,32 @@ static int bcm4320b_early_init(struct usbnet *usbdev) | |||
2652 | priv->param_workaround_interval = 500; | 2638 | priv->param_workaround_interval = 500; |
2653 | else | 2639 | else |
2654 | priv->param_workaround_interval = modparam_workaround_interval; | 2640 | priv->param_workaround_interval = modparam_workaround_interval; |
2641 | } | ||
2642 | |||
2643 | static int bcm4320a_early_init(struct usbnet *usbdev) | ||
2644 | { | ||
2645 | /* copy module parameters for bcm4320a so that iwconfig reports txpower | ||
2646 | * and workaround parameter is copied to private structure correctly. | ||
2647 | */ | ||
2648 | rndis_copy_module_params(usbdev); | ||
2649 | |||
2650 | /* bcm4320a doesn't handle configuration parameters well. Try | ||
2651 | * set any and you get partially zeroed mac and broken device. | ||
2652 | */ | ||
2653 | |||
2654 | return 0; | ||
2655 | } | ||
2656 | |||
2657 | static int bcm4320b_early_init(struct usbnet *usbdev) | ||
2658 | { | ||
2659 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); | ||
2660 | char buf[8]; | ||
2661 | |||
2662 | rndis_copy_module_params(usbdev); | ||
2663 | |||
2664 | /* Early initialization settings, setting these won't have effect | ||
2665 | * if called after generic_rndis_bind(). | ||
2666 | */ | ||
2655 | 2667 | ||
2656 | rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); | 2668 | rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); |
2657 | rndis_set_config_parameter_str(usbdev, "FrameBursting", | 2669 | rndis_set_config_parameter_str(usbdev, "FrameBursting", |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index dfc886fcb44d..458378c4e500 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -835,7 +835,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
835 | struct rxdone_entry_desc *rxdesc) | 835 | struct rxdone_entry_desc *rxdesc) |
836 | { | 836 | { |
837 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 837 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
838 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
839 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 838 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
840 | __le32 *rxd = entry_priv->desc; | 839 | __le32 *rxd = entry_priv->desc; |
841 | __le32 *rxwi = (__le32 *)entry->skb->data; | 840 | __le32 *rxwi = (__le32 *)entry->skb->data; |
@@ -883,10 +882,8 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
883 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) | 882 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) |
884 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 883 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
885 | 884 | ||
886 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { | 885 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) |
887 | rxdesc->dev_flags |= RXDONE_L2PAD; | 886 | rxdesc->dev_flags |= RXDONE_L2PAD; |
888 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
889 | } | ||
890 | 887 | ||
891 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 888 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
892 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 889 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -927,7 +924,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
927 | * Remove TXWI descriptor from start of buffer. | 924 | * Remove TXWI descriptor from start of buffer. |
928 | */ | 925 | */ |
929 | skb_pull(entry->skb, RXWI_DESC_SIZE); | 926 | skb_pull(entry->skb, RXWI_DESC_SIZE); |
930 | skb_trim(entry->skb, rxdesc->size); | ||
931 | } | 927 | } |
932 | 928 | ||
933 | /* | 929 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index af85d18cdbe7..40295b454ff6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -295,9 +295,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
295 | 295 | ||
296 | rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); | 296 | rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); |
297 | rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); | 297 | rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); |
298 | /* Don't use bulk in aggregation when working with USB 1.1 */ | 298 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); |
299 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, | ||
300 | (rt2x00dev->rx->usb_maxpacket == 512)); | ||
301 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); | 299 | rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); |
302 | /* | 300 | /* |
303 | * Total room for RX frames in kilobytes, PBF might still exceed | 301 | * Total room for RX frames in kilobytes, PBF might still exceed |
@@ -573,41 +571,57 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
573 | { | 571 | { |
574 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 572 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
575 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 573 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
576 | __le32 *rxd = (__le32 *)entry->skb->data; | 574 | __le32 *rxi = (__le32 *)entry->skb->data; |
577 | __le32 *rxwi; | 575 | __le32 *rxwi; |
578 | u32 rxd0; | 576 | __le32 *rxd; |
577 | u32 rxi0; | ||
579 | u32 rxwi0; | 578 | u32 rxwi0; |
580 | u32 rxwi1; | 579 | u32 rxwi1; |
581 | u32 rxwi2; | 580 | u32 rxwi2; |
582 | u32 rxwi3; | 581 | u32 rxwi3; |
582 | u32 rxd0; | ||
583 | int rx_pkt_len; | ||
584 | |||
585 | /* | ||
586 | * RX frame format is : | ||
587 | * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad | | ||
588 | * |<------------ rx_pkt_len -------------->| | ||
589 | */ | ||
590 | rt2x00_desc_read(rxi, 0, &rxi0); | ||
591 | rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN); | ||
592 | |||
593 | rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE); | ||
594 | |||
595 | /* | ||
596 | * FIXME : we need to check for rx_pkt_len validity | ||
597 | */ | ||
598 | rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len); | ||
583 | 599 | ||
584 | /* | 600 | /* |
585 | * Copy descriptor to the skbdesc->desc buffer, making it safe from | 601 | * Copy descriptor to the skbdesc->desc buffer, making it safe from |
586 | * moving of frame data in rt2x00usb. | 602 | * moving of frame data in rt2x00usb. |
587 | */ | 603 | */ |
588 | memcpy(skbdesc->desc, rxd, skbdesc->desc_len); | 604 | memcpy(skbdesc->desc, rxi, skbdesc->desc_len); |
589 | rxd = (__le32 *)skbdesc->desc; | ||
590 | rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)]; | ||
591 | 605 | ||
592 | /* | 606 | /* |
593 | * It is now safe to read the descriptor on all architectures. | 607 | * It is now safe to read the descriptor on all architectures. |
594 | */ | 608 | */ |
595 | rt2x00_desc_read(rxd, 0, &rxd0); | ||
596 | rt2x00_desc_read(rxwi, 0, &rxwi0); | 609 | rt2x00_desc_read(rxwi, 0, &rxwi0); |
597 | rt2x00_desc_read(rxwi, 1, &rxwi1); | 610 | rt2x00_desc_read(rxwi, 1, &rxwi1); |
598 | rt2x00_desc_read(rxwi, 2, &rxwi2); | 611 | rt2x00_desc_read(rxwi, 2, &rxwi2); |
599 | rt2x00_desc_read(rxwi, 3, &rxwi3); | 612 | rt2x00_desc_read(rxwi, 3, &rxwi3); |
613 | rt2x00_desc_read(rxd, 0, &rxd0); | ||
600 | 614 | ||
601 | if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR)) | 615 | if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) |
602 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 616 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
603 | 617 | ||
604 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | 618 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { |
605 | rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); | 619 | rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); |
606 | rxdesc->cipher_status = | 620 | rxdesc->cipher_status = |
607 | rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR); | 621 | rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); |
608 | } | 622 | } |
609 | 623 | ||
610 | if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) { | 624 | if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { |
611 | /* | 625 | /* |
612 | * Hardware has stripped IV/EIV data from 802.11 frame during | 626 | * Hardware has stripped IV/EIV data from 802.11 frame during |
613 | * decryption. Unfortunately the descriptor doesn't contain | 627 | * decryption. Unfortunately the descriptor doesn't contain |
@@ -622,13 +636,11 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
622 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | 636 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; |
623 | } | 637 | } |
624 | 638 | ||
625 | if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS)) | 639 | if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) |
626 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 640 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
627 | 641 | ||
628 | if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) { | 642 | if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) |
629 | rxdesc->dev_flags |= RXDONE_L2PAD; | 643 | rxdesc->dev_flags |= RXDONE_L2PAD; |
630 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
631 | } | ||
632 | 644 | ||
633 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 645 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
634 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 646 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -663,7 +675,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
663 | * Remove RXWI descriptor from start of buffer. | 675 | * Remove RXWI descriptor from start of buffer. |
664 | */ | 676 | */ |
665 | skb_pull(entry->skb, skbdesc->desc_len); | 677 | skb_pull(entry->skb, skbdesc->desc_len); |
666 | skb_trim(entry->skb, rxdesc->size); | ||
667 | } | 678 | } |
668 | 679 | ||
669 | /* | 680 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 1e4340a182ef..d1d8ae94b4d4 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h | |||
@@ -79,6 +79,8 @@ | |||
79 | */ | 79 | */ |
80 | #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) | 80 | #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) |
81 | #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) | 81 | #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) |
82 | #define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
83 | #define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) | ||
82 | 84 | ||
83 | /* | 85 | /* |
84 | * TX Info structure | 86 | * TX Info structure |
@@ -101,6 +103,54 @@ | |||
101 | #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) | 103 | #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) |
102 | 104 | ||
103 | /* | 105 | /* |
106 | * RX Info structure | ||
107 | */ | ||
108 | |||
109 | /* | ||
110 | * Word 0 | ||
111 | */ | ||
112 | |||
113 | #define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff) | ||
114 | |||
115 | /* | ||
116 | * RX WI structure | ||
117 | */ | ||
118 | |||
119 | /* | ||
120 | * Word0 | ||
121 | */ | ||
122 | #define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) | ||
123 | #define RXWI_W0_KEY_INDEX FIELD32(0x00000300) | ||
124 | #define RXWI_W0_BSSID FIELD32(0x00001c00) | ||
125 | #define RXWI_W0_UDF FIELD32(0x0000e000) | ||
126 | #define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) | ||
127 | #define RXWI_W0_TID FIELD32(0xf0000000) | ||
128 | |||
129 | /* | ||
130 | * Word1 | ||
131 | */ | ||
132 | #define RXWI_W1_FRAG FIELD32(0x0000000f) | ||
133 | #define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) | ||
134 | #define RXWI_W1_MCS FIELD32(0x007f0000) | ||
135 | #define RXWI_W1_BW FIELD32(0x00800000) | ||
136 | #define RXWI_W1_SHORT_GI FIELD32(0x01000000) | ||
137 | #define RXWI_W1_STBC FIELD32(0x06000000) | ||
138 | #define RXWI_W1_PHYMODE FIELD32(0xc0000000) | ||
139 | |||
140 | /* | ||
141 | * Word2 | ||
142 | */ | ||
143 | #define RXWI_W2_RSSI0 FIELD32(0x000000ff) | ||
144 | #define RXWI_W2_RSSI1 FIELD32(0x0000ff00) | ||
145 | #define RXWI_W2_RSSI2 FIELD32(0x00ff0000) | ||
146 | |||
147 | /* | ||
148 | * Word3 | ||
149 | */ | ||
150 | #define RXWI_W3_SNR0 FIELD32(0x000000ff) | ||
151 | #define RXWI_W3_SNR1 FIELD32(0x0000ff00) | ||
152 | |||
153 | /* | ||
104 | * RX descriptor format for RX Ring. | 154 | * RX descriptor format for RX Ring. |
105 | */ | 155 | */ |
106 | 156 | ||
@@ -115,25 +165,25 @@ | |||
115 | * AMSDU: rx with 802.3 header, not 802.11 header. | 165 | * AMSDU: rx with 802.3 header, not 802.11 header. |
116 | */ | 166 | */ |
117 | 167 | ||
118 | #define RXINFO_W0_BA FIELD32(0x00000001) | 168 | #define RXD_W0_BA FIELD32(0x00000001) |
119 | #define RXINFO_W0_DATA FIELD32(0x00000002) | 169 | #define RXD_W0_DATA FIELD32(0x00000002) |
120 | #define RXINFO_W0_NULLDATA FIELD32(0x00000004) | 170 | #define RXD_W0_NULLDATA FIELD32(0x00000004) |
121 | #define RXINFO_W0_FRAG FIELD32(0x00000008) | 171 | #define RXD_W0_FRAG FIELD32(0x00000008) |
122 | #define RXINFO_W0_UNICAST_TO_ME FIELD32(0x00000010) | 172 | #define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) |
123 | #define RXINFO_W0_MULTICAST FIELD32(0x00000020) | 173 | #define RXD_W0_MULTICAST FIELD32(0x00000020) |
124 | #define RXINFO_W0_BROADCAST FIELD32(0x00000040) | 174 | #define RXD_W0_BROADCAST FIELD32(0x00000040) |
125 | #define RXINFO_W0_MY_BSS FIELD32(0x00000080) | 175 | #define RXD_W0_MY_BSS FIELD32(0x00000080) |
126 | #define RXINFO_W0_CRC_ERROR FIELD32(0x00000100) | 176 | #define RXD_W0_CRC_ERROR FIELD32(0x00000100) |
127 | #define RXINFO_W0_CIPHER_ERROR FIELD32(0x00000600) | 177 | #define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) |
128 | #define RXINFO_W0_AMSDU FIELD32(0x00000800) | 178 | #define RXD_W0_AMSDU FIELD32(0x00000800) |
129 | #define RXINFO_W0_HTC FIELD32(0x00001000) | 179 | #define RXD_W0_HTC FIELD32(0x00001000) |
130 | #define RXINFO_W0_RSSI FIELD32(0x00002000) | 180 | #define RXD_W0_RSSI FIELD32(0x00002000) |
131 | #define RXINFO_W0_L2PAD FIELD32(0x00004000) | 181 | #define RXD_W0_L2PAD FIELD32(0x00004000) |
132 | #define RXINFO_W0_AMPDU FIELD32(0x00008000) | 182 | #define RXD_W0_AMPDU FIELD32(0x00008000) |
133 | #define RXINFO_W0_DECRYPTED FIELD32(0x00010000) | 183 | #define RXD_W0_DECRYPTED FIELD32(0x00010000) |
134 | #define RXINFO_W0_PLCP_RSSI FIELD32(0x00020000) | 184 | #define RXD_W0_PLCP_RSSI FIELD32(0x00020000) |
135 | #define RXINFO_W0_CIPHER_ALG FIELD32(0x00040000) | 185 | #define RXD_W0_CIPHER_ALG FIELD32(0x00040000) |
136 | #define RXINFO_W0_LAST_AMSDU FIELD32(0x00080000) | 186 | #define RXD_W0_LAST_AMSDU FIELD32(0x00080000) |
137 | #define RXINFO_W0_PLCP_SIGNAL FIELD32(0xfff00000) | 187 | #define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) |
138 | 188 | ||
139 | #endif /* RT2800USB_H */ | 189 | #endif /* RT2800USB_H */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4d841c07c970..194dae01d0c3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -104,6 +104,12 @@ | |||
104 | #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) | 104 | #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Determine the number of L2 padding bytes required between the header and | ||
108 | * the payload. | ||
109 | */ | ||
110 | #define L2PAD_SIZE(__hdrlen) (-(__hdrlen) & 3) | ||
111 | |||
112 | /* | ||
107 | * Determine the alignment requirement, | 113 | * Determine the alignment requirement, |
108 | * to make sure the 802.11 payload is padded to a 4-byte boundrary | 114 | * to make sure the 802.11 payload is padded to a 4-byte boundrary |
109 | * we must determine the address of the payload and calculate the | 115 | * we must determine the address of the payload and calculate the |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 06c43ca39bf8..d7711e4d4751 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -385,9 +385,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
385 | memset(&rxdesc, 0, sizeof(rxdesc)); | 385 | memset(&rxdesc, 0, sizeof(rxdesc)); |
386 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | 386 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); |
387 | 387 | ||
388 | /* Trim buffer to correct size */ | ||
389 | skb_trim(entry->skb, rxdesc.size); | ||
390 | |||
391 | /* | 388 | /* |
392 | * The data behind the ieee80211 header must be | 389 | * The data behind the ieee80211 header must be |
393 | * aligned on a 4 byte boundary. | 390 | * aligned on a 4 byte boundary. |
@@ -404,11 +401,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
404 | (rxdesc.flags & RX_FLAG_IV_STRIPPED)) | 401 | (rxdesc.flags & RX_FLAG_IV_STRIPPED)) |
405 | rt2x00crypto_rx_insert_iv(entry->skb, header_length, | 402 | rt2x00crypto_rx_insert_iv(entry->skb, header_length, |
406 | &rxdesc); | 403 | &rxdesc); |
407 | else if (rxdesc.dev_flags & RXDONE_L2PAD) | 404 | else if (header_length && |
405 | (rxdesc.size > header_length) && | ||
406 | (rxdesc.dev_flags & RXDONE_L2PAD)) | ||
408 | rt2x00queue_remove_l2pad(entry->skb, header_length); | 407 | rt2x00queue_remove_l2pad(entry->skb, header_length); |
409 | else | 408 | else |
410 | rt2x00queue_align_payload(entry->skb, header_length); | 409 | rt2x00queue_align_payload(entry->skb, header_length); |
411 | 410 | ||
411 | /* Trim buffer to correct size */ | ||
412 | skb_trim(entry->skb, rxdesc.size); | ||
413 | |||
412 | /* | 414 | /* |
413 | * Check if the frame was received using HT. In that case, | 415 | * Check if the frame was received using HT. In that case, |
414 | * the rate is the MCS index and should be passed to mac80211 | 416 | * the rate is the MCS index and should be passed to mac80211 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0feb4d0e4668..801be436cf1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -41,6 +41,9 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | |||
41 | { | 41 | { |
42 | unsigned int i; | 42 | unsigned int i; |
43 | 43 | ||
44 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) | ||
45 | return 0; | ||
46 | |||
44 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 47 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
45 | rt2x00pci_register_read(rt2x00dev, offset, reg); | 48 | rt2x00pci_register_read(rt2x00dev, offset, reg); |
46 | if (!rt2x00_get_field32(*reg, field)) | 49 | if (!rt2x00_get_field32(*reg, field)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 239afc7a9c0b..3d8fb684b4eb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -177,55 +177,45 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) | |||
177 | 177 | ||
178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) | 178 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) |
179 | { | 179 | { |
180 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 180 | unsigned int payload_length = skb->len - header_length; |
181 | unsigned int frame_length = skb->len; | ||
182 | unsigned int header_align = ALIGN_SIZE(skb, 0); | 181 | unsigned int header_align = ALIGN_SIZE(skb, 0); |
183 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); | 182 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); |
184 | unsigned int l2pad = 4 - (payload_align - header_align); | 183 | unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; |
185 | 184 | ||
186 | if (header_align == payload_align) { | 185 | /* |
187 | /* | 186 | * Adjust the header alignment if the payload needs to be moved more |
188 | * Both header and payload must be moved the same | 187 | * than the header. |
189 | * amount of bytes to align them properly. This means | 188 | */ |
190 | * we don't use the L2 padding but just move the entire | 189 | if (payload_align > header_align) |
191 | * frame. | 190 | header_align += 4; |
192 | */ | 191 | |
193 | rt2x00queue_align_frame(skb); | 192 | /* There is nothing to do if no alignment is needed */ |
194 | } else if (!payload_align) { | 193 | if (!header_align) |
195 | /* | 194 | return; |
196 | * Simple L2 padding, only the header needs to be moved, | 195 | |
197 | * the payload is already properly aligned. | 196 | /* Reserve the amount of space needed in front of the frame */ |
198 | */ | 197 | skb_push(skb, header_align); |
199 | skb_push(skb, header_align); | 198 | |
200 | memmove(skb->data, skb->data + header_align, frame_length); | 199 | /* |
201 | skbdesc->flags |= SKBDESC_L2_PADDED; | 200 | * Move the header. |
202 | } else { | 201 | */ |
203 | /* | 202 | memmove(skb->data, skb->data + header_align, header_length); |
204 | * | ||
205 | * Complicated L2 padding, both header and payload need | ||
206 | * to be moved. By default we only move to the start | ||
207 | * of the buffer, so our header alignment needs to be | ||
208 | * increased if there is not enough room for the header | ||
209 | * to be moved. | ||
210 | */ | ||
211 | if (payload_align > header_align) | ||
212 | header_align += 4; | ||
213 | 203 | ||
214 | skb_push(skb, header_align); | 204 | /* Move the payload, if present and if required */ |
215 | memmove(skb->data, skb->data + header_align, header_length); | 205 | if (payload_length && payload_align) |
216 | memmove(skb->data + header_length + l2pad, | 206 | memmove(skb->data + header_length + l2pad, |
217 | skb->data + header_length + l2pad + payload_align, | 207 | skb->data + header_length + l2pad + payload_align, |
218 | frame_length - header_length); | 208 | payload_length); |
219 | skbdesc->flags |= SKBDESC_L2_PADDED; | 209 | |
220 | } | 210 | /* Trim the skb to the correct size */ |
211 | skb_trim(skb, header_length + l2pad + payload_length); | ||
221 | } | 212 | } |
222 | 213 | ||
223 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) | 214 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) |
224 | { | 215 | { |
225 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | 216 | unsigned int l2pad = L2PAD_SIZE(header_length); |
226 | unsigned int l2pad = 4 - (header_length & 3); | ||
227 | 217 | ||
228 | if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) | 218 | if (!l2pad) |
229 | return; | 219 | return; |
230 | 220 | ||
231 | memmove(skb->data + l2pad, skb->data, header_length); | 221 | memmove(skb->data + l2pad, skb->data, header_length); |
@@ -346,7 +336,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
346 | * Header and alignment information. | 336 | * Header and alignment information. |
347 | */ | 337 | */ |
348 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 338 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
349 | txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); | 339 | if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && |
340 | (entry->skb->len > txdesc->header_length)) | ||
341 | txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); | ||
350 | 342 | ||
351 | /* | 343 | /* |
352 | * Check whether this frame is to be acked. | 344 | * Check whether this frame is to be acked. |
@@ -387,10 +379,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
387 | 379 | ||
388 | /* | 380 | /* |
389 | * Beacons and probe responses require the tsf timestamp | 381 | * Beacons and probe responses require the tsf timestamp |
390 | * to be inserted into the frame. | 382 | * to be inserted into the frame, except for a frame that has been injected |
383 | * through a monitor interface. This latter is needed for testing a | ||
384 | * monitor interface. | ||
391 | */ | 385 | */ |
392 | if (ieee80211_is_beacon(hdr->frame_control) || | 386 | if ((ieee80211_is_beacon(hdr->frame_control) || |
393 | ieee80211_is_probe_resp(hdr->frame_control)) | 387 | ieee80211_is_probe_resp(hdr->frame_control)) && |
388 | (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED))) | ||
394 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); | 389 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); |
395 | 390 | ||
396 | /* | 391 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 70775e5ba1ac..c1e482bb37b3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -92,8 +92,6 @@ enum data_queue_qid { | |||
92 | * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX | 92 | * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX |
93 | * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by | 93 | * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by |
94 | * mac80211 but was stripped for processing by the driver. | 94 | * mac80211 but was stripped for processing by the driver. |
95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, | ||
96 | * the padded bytes are located between header and payload. | ||
97 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, | 95 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, |
98 | * don't try to pass it back. | 96 | * don't try to pass it back. |
99 | */ | 97 | */ |
@@ -101,8 +99,7 @@ enum skb_frame_desc_flags { | |||
101 | SKBDESC_DMA_MAPPED_RX = 1 << 0, | 99 | SKBDESC_DMA_MAPPED_RX = 1 << 0, |
102 | SKBDESC_DMA_MAPPED_TX = 1 << 1, | 100 | SKBDESC_DMA_MAPPED_TX = 1 << 1, |
103 | SKBDESC_IV_STRIPPED = 1 << 2, | 101 | SKBDESC_IV_STRIPPED = 1 << 2, |
104 | SKBDESC_L2_PADDED = 1 << 3, | 102 | SKBDESC_NOT_MAC80211 = 1 << 3, |
105 | SKBDESC_NOT_MAC80211 = 1 << 4, | ||
106 | }; | 103 | }; |
107 | 104 | ||
108 | /** | 105 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ced3b6ab5e16..6ce88d3c3b65 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2354,6 +2354,7 @@ static struct usb_device_id rt73usb_device_table[] = { | |||
2354 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, | 2354 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, |
2355 | /* Buffalo */ | 2355 | /* Buffalo */ |
2356 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, | 2356 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, |
2357 | { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, | ||
2357 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, | 2358 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, |
2358 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, | 2359 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, |
2359 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, | 2360 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index a1a3dd15c664..8a40a1439984 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -132,7 +132,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
132 | 132 | ||
133 | rx_status.antenna = (flags2 >> 15) & 1; | 133 | rx_status.antenna = (flags2 >> 15) & 1; |
134 | /* TODO: improve signal/rssi reporting */ | 134 | /* TODO: improve signal/rssi reporting */ |
135 | rx_status.qual = flags2 & 0xFF; | ||
136 | rx_status.signal = (flags2 >> 8) & 0x7F; | 135 | rx_status.signal = (flags2 >> 8) & 0x7F; |
137 | /* XXX: is this correct? */ | 136 | /* XXX: is this correct? */ |
138 | rx_status.rate_idx = (flags >> 20) & 0xF; | 137 | rx_status.rate_idx = (flags >> 20) & 0xF; |
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 054533f7a124..6301578d1565 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -247,6 +247,7 @@ struct wl1251_debugfs { | |||
247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; | 247 | struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; |
248 | 248 | ||
249 | struct dentry *tx_queue_len; | 249 | struct dentry *tx_queue_len; |
250 | struct dentry *tx_queue_status; | ||
250 | 251 | ||
251 | struct dentry *retry_count; | 252 | struct dentry *retry_count; |
252 | struct dentry *excessive_retries; | 253 | struct dentry *excessive_retries; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index acfa086dbfc5..beff084040b5 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -976,3 +976,72 @@ out: | |||
976 | kfree(acx); | 976 | kfree(acx); |
977 | return ret; | 977 | return ret; |
978 | } | 978 | } |
979 | |||
980 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
981 | u8 aifs, u16 txop) | ||
982 | { | ||
983 | struct wl1251_acx_ac_cfg *acx; | ||
984 | int ret = 0; | ||
985 | |||
986 | wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " | ||
987 | "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); | ||
988 | |||
989 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
990 | |||
991 | if (!acx) { | ||
992 | ret = -ENOMEM; | ||
993 | goto out; | ||
994 | } | ||
995 | |||
996 | acx->ac = ac; | ||
997 | acx->cw_min = cw_min; | ||
998 | acx->cw_max = cw_max; | ||
999 | acx->aifsn = aifs; | ||
1000 | acx->txop_limit = txop; | ||
1001 | |||
1002 | ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | ||
1003 | if (ret < 0) { | ||
1004 | wl1251_warning("acx ac cfg failed: %d", ret); | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | out: | ||
1009 | kfree(acx); | ||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1014 | enum wl1251_acx_channel_type type, | ||
1015 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1016 | enum wl1251_acx_ack_policy ack_policy) | ||
1017 | { | ||
1018 | struct wl1251_acx_tid_cfg *acx; | ||
1019 | int ret = 0; | ||
1020 | |||
1021 | wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d " | ||
1022 | "ps_scheme %d ack_policy %d", queue, type, tsid, | ||
1023 | ps_scheme, ack_policy); | ||
1024 | |||
1025 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1026 | |||
1027 | if (!acx) { | ||
1028 | ret = -ENOMEM; | ||
1029 | goto out; | ||
1030 | } | ||
1031 | |||
1032 | acx->queue = queue; | ||
1033 | acx->type = type; | ||
1034 | acx->tsid = tsid; | ||
1035 | acx->ps_scheme = ps_scheme; | ||
1036 | acx->ack_policy = ack_policy; | ||
1037 | |||
1038 | ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | ||
1039 | if (ret < 0) { | ||
1040 | wl1251_warning("acx tid cfg failed: %d", ret); | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | out: | ||
1045 | kfree(acx); | ||
1046 | return ret; | ||
1047 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 652371432cd8..26160c45784c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -1166,6 +1166,87 @@ struct wl1251_acx_wr_tbtt_and_dtim { | |||
1166 | u8 padding; | 1166 | u8 padding; |
1167 | } __attribute__ ((packed)); | 1167 | } __attribute__ ((packed)); |
1168 | 1168 | ||
1169 | struct wl1251_acx_ac_cfg { | ||
1170 | struct acx_header header; | ||
1171 | |||
1172 | /* | ||
1173 | * Access Category - The TX queue's access category | ||
1174 | * (refer to AccessCategory_enum) | ||
1175 | */ | ||
1176 | u8 ac; | ||
1177 | |||
1178 | /* | ||
1179 | * The contention window minimum size (in slots) for | ||
1180 | * the access class. | ||
1181 | */ | ||
1182 | u8 cw_min; | ||
1183 | |||
1184 | /* | ||
1185 | * The contention window maximum size (in slots) for | ||
1186 | * the access class. | ||
1187 | */ | ||
1188 | u16 cw_max; | ||
1189 | |||
1190 | /* The AIF value (in slots) for the access class. */ | ||
1191 | u8 aifsn; | ||
1192 | |||
1193 | u8 reserved; | ||
1194 | |||
1195 | /* The TX Op Limit (in microseconds) for the access class. */ | ||
1196 | u16 txop_limit; | ||
1197 | } __attribute__ ((packed)); | ||
1198 | |||
1199 | |||
1200 | enum wl1251_acx_channel_type { | ||
1201 | CHANNEL_TYPE_DCF = 0, | ||
1202 | CHANNEL_TYPE_EDCF = 1, | ||
1203 | CHANNEL_TYPE_HCCA = 2, | ||
1204 | }; | ||
1205 | |||
1206 | enum wl1251_acx_ps_scheme { | ||
1207 | /* regular ps: simple sending of packets */ | ||
1208 | WL1251_ACX_PS_SCHEME_LEGACY = 0, | ||
1209 | |||
1210 | /* sending a packet triggers a unscheduled apsd downstream */ | ||
1211 | WL1251_ACX_PS_SCHEME_UPSD_TRIGGER = 1, | ||
1212 | |||
1213 | /* a pspoll packet will be sent before every data packet */ | ||
1214 | WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, | ||
1215 | |||
1216 | /* scheduled apsd mode */ | ||
1217 | WL1251_ACX_PS_SCHEME_SAPSD = 3, | ||
1218 | }; | ||
1219 | |||
1220 | enum wl1251_acx_ack_policy { | ||
1221 | WL1251_ACX_ACK_POLICY_LEGACY = 0, | ||
1222 | WL1251_ACX_ACK_POLICY_NO_ACK = 1, | ||
1223 | WL1251_ACX_ACK_POLICY_BLOCK = 2, | ||
1224 | }; | ||
1225 | |||
1226 | struct wl1251_acx_tid_cfg { | ||
1227 | struct acx_header header; | ||
1228 | |||
1229 | /* tx queue id number (0-7) */ | ||
1230 | u8 queue; | ||
1231 | |||
1232 | /* channel access type for the queue, enum wl1251_acx_channel_type */ | ||
1233 | u8 type; | ||
1234 | |||
1235 | /* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */ | ||
1236 | u8 tsid; | ||
1237 | |||
1238 | /* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */ | ||
1239 | u8 ps_scheme; | ||
1240 | |||
1241 | /* the tx queue ack policy, enum wl1251_acx_ack_policy */ | ||
1242 | u8 ack_policy; | ||
1243 | |||
1244 | u8 padding[3]; | ||
1245 | |||
1246 | /* not supported */ | ||
1247 | u32 apsdconf[2]; | ||
1248 | } __attribute__ ((packed)); | ||
1249 | |||
1169 | /************************************************************************* | 1250 | /************************************************************************* |
1170 | 1251 | ||
1171 | Host Interrupt Register (WiLink -> Host) | 1252 | Host Interrupt Register (WiLink -> Host) |
@@ -1322,5 +1403,11 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | |||
1322 | int wl1251_acx_rate_policies(struct wl1251 *wl); | 1403 | int wl1251_acx_rate_policies(struct wl1251 *wl); |
1323 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | 1404 | int wl1251_acx_mem_cfg(struct wl1251 *wl); |
1324 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | 1405 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); |
1406 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | ||
1407 | u8 aifs, u16 txop); | ||
1408 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | ||
1409 | enum wl1251_acx_channel_type type, | ||
1410 | u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, | ||
1411 | enum wl1251_acx_ack_policy ack_policy); | ||
1325 | 1412 | ||
1326 | #endif /* __WL1251_ACX_H__ */ | 1413 | #endif /* __WL1251_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c index a00723059f83..0ccba57fb9fb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c | |||
@@ -237,6 +237,27 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1251_open_file_generic, | 237 | .open = wl1251_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1251 *wl = file->private_data; | ||
244 | char buf[3], status; | ||
245 | int len; | ||
246 | |||
247 | if (wl->tx_queue_stopped) | ||
248 | status = 's'; | ||
249 | else | ||
250 | status = 'r'; | ||
251 | |||
252 | len = scnprintf(buf, sizeof(buf), "%c\n", status); | ||
253 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | ||
254 | } | ||
255 | |||
256 | static const struct file_operations tx_queue_status_ops = { | ||
257 | .read = tx_queue_status_read, | ||
258 | .open = wl1251_open_file_generic, | ||
259 | }; | ||
260 | |||
240 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) | 261 | static void wl1251_debugfs_delete_files(struct wl1251 *wl) |
241 | { | 262 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 263 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -331,6 +352,7 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl) | |||
331 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); | 352 | DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); |
332 | 353 | ||
333 | DEBUGFS_DEL(tx_queue_len); | 354 | DEBUGFS_DEL(tx_queue_len); |
355 | DEBUGFS_DEL(tx_queue_status); | ||
334 | DEBUGFS_DEL(retry_count); | 356 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 357 | DEBUGFS_DEL(excessive_retries); |
336 | } | 358 | } |
@@ -431,6 +453,7 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl) | |||
431 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); | 453 | DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); |
432 | 454 | ||
433 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); | 455 | DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); |
456 | DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); | ||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 457 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 458 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 459 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index 5cb573383eeb..5aad56ea7153 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c | |||
@@ -294,6 +294,11 @@ static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) | |||
294 | goto out; | 294 | goto out; |
295 | } | 295 | } |
296 | 296 | ||
297 | wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); | ||
298 | wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); | ||
299 | wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); | ||
300 | wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); | ||
301 | |||
297 | out: | 302 | out: |
298 | kfree(config); | 303 | kfree(config); |
299 | return ret; | 304 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h index b3b25ec885ea..269cefb3e7d4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ b/drivers/net/wireless/wl12xx/wl1251_init.h | |||
@@ -26,6 +26,53 @@ | |||
26 | 26 | ||
27 | #include "wl1251.h" | 27 | #include "wl1251.h" |
28 | 28 | ||
29 | enum { | ||
30 | /* best effort/legacy */ | ||
31 | AC_BE = 0, | ||
32 | |||
33 | /* background */ | ||
34 | AC_BK = 1, | ||
35 | |||
36 | /* video */ | ||
37 | AC_VI = 2, | ||
38 | |||
39 | /* voice */ | ||
40 | AC_VO = 3, | ||
41 | |||
42 | /* broadcast dummy access category */ | ||
43 | AC_BCAST = 4, | ||
44 | |||
45 | NUM_ACCESS_CATEGORIES = 4 | ||
46 | }; | ||
47 | |||
48 | /* following are defult values for the IE fields*/ | ||
49 | #define CWMIN_BK 15 | ||
50 | #define CWMIN_BE 15 | ||
51 | #define CWMIN_VI 7 | ||
52 | #define CWMIN_VO 3 | ||
53 | #define CWMAX_BK 1023 | ||
54 | #define CWMAX_BE 63 | ||
55 | #define CWMAX_VI 15 | ||
56 | #define CWMAX_VO 7 | ||
57 | |||
58 | /* slot number setting to start transmission at PIFS interval */ | ||
59 | #define AIFS_PIFS 1 | ||
60 | |||
61 | /* | ||
62 | * slot number setting to start transmission at DIFS interval - normal DCF | ||
63 | * access | ||
64 | */ | ||
65 | #define AIFS_DIFS 2 | ||
66 | |||
67 | #define AIFSN_BK 7 | ||
68 | #define AIFSN_BE 3 | ||
69 | #define AIFSN_VI AIFS_PIFS | ||
70 | #define AIFSN_VO AIFS_PIFS | ||
71 | #define TXOP_BK 0 | ||
72 | #define TXOP_BE 0 | ||
73 | #define TXOP_VI 3008 | ||
74 | #define TXOP_VO 1504 | ||
75 | |||
29 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); | 76 | int wl1251_hw_init_hwenc_config(struct wl1251 *wl); |
30 | int wl1251_hw_init_templates_config(struct wl1251 *wl); | 77 | int wl1251_hw_init_templates_config(struct wl1251 *wl); |
31 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); | 78 | int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 2f50a256efa5..6aeffbe9e401 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -395,6 +395,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
395 | * the queue here, otherwise the queue will get too long. | 395 | * the queue here, otherwise the queue will get too long. |
396 | */ | 396 | */ |
397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { | 397 | if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { |
398 | wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); | ||
398 | ieee80211_stop_queues(wl->hw); | 399 | ieee80211_stop_queues(wl->hw); |
399 | 400 | ||
400 | /* | 401 | /* |
@@ -640,20 +641,25 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
640 | * through the bss_info_changed() hook. | 641 | * through the bss_info_changed() hook. |
641 | */ | 642 | */ |
642 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 643 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); |
644 | if (ret < 0) | ||
645 | goto out_sleep; | ||
643 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 646 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
644 | wl->psm_requested) { | 647 | wl->psm_requested) { |
645 | wl1251_debug(DEBUG_PSM, "psm disabled"); | 648 | wl1251_debug(DEBUG_PSM, "psm disabled"); |
646 | 649 | ||
647 | wl->psm_requested = false; | 650 | wl->psm_requested = false; |
648 | 651 | ||
649 | if (wl->psm) | 652 | if (wl->psm) { |
650 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | 653 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); |
654 | if (ret < 0) | ||
655 | goto out_sleep; | ||
656 | } | ||
651 | } | 657 | } |
652 | 658 | ||
653 | if (conf->power_level != wl->power_level) { | 659 | if (conf->power_level != wl->power_level) { |
654 | ret = wl1251_acx_tx_power(wl, conf->power_level); | 660 | ret = wl1251_acx_tx_power(wl, conf->power_level); |
655 | if (ret < 0) | 661 | if (ret < 0) |
656 | goto out; | 662 | goto out_sleep; |
657 | 663 | ||
658 | wl->power_level = conf->power_level; | 664 | wl->power_level = conf->power_level; |
659 | } | 665 | } |
@@ -1273,6 +1279,43 @@ static struct ieee80211_channel wl1251_channels[] = { | |||
1273 | { .hw_value = 13, .center_freq = 2472}, | 1279 | { .hw_value = 13, .center_freq = 2472}, |
1274 | }; | 1280 | }; |
1275 | 1281 | ||
1282 | static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1283 | const struct ieee80211_tx_queue_params *params) | ||
1284 | { | ||
1285 | struct wl1251 *wl = hw->priv; | ||
1286 | int ret; | ||
1287 | |||
1288 | mutex_lock(&wl->mutex); | ||
1289 | |||
1290 | wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1291 | |||
1292 | ret = wl1251_ps_elp_wakeup(wl); | ||
1293 | if (ret < 0) | ||
1294 | goto out; | ||
1295 | |||
1296 | ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), | ||
1297 | params->cw_min, params->cw_max, | ||
1298 | params->aifs, params->txop); | ||
1299 | if (ret < 0) | ||
1300 | goto out_sleep; | ||
1301 | |||
1302 | ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), | ||
1303 | CHANNEL_TYPE_EDCF, | ||
1304 | wl1251_tx_get_queue(queue), | ||
1305 | WL1251_ACX_PS_SCHEME_LEGACY, | ||
1306 | WL1251_ACX_ACK_POLICY_LEGACY); | ||
1307 | if (ret < 0) | ||
1308 | goto out_sleep; | ||
1309 | |||
1310 | out_sleep: | ||
1311 | wl1251_ps_elp_sleep(wl); | ||
1312 | |||
1313 | out: | ||
1314 | mutex_unlock(&wl->mutex); | ||
1315 | |||
1316 | return ret; | ||
1317 | } | ||
1318 | |||
1276 | /* can't be const, mac80211 writes to this */ | 1319 | /* can't be const, mac80211 writes to this */ |
1277 | static struct ieee80211_supported_band wl1251_band_2ghz = { | 1320 | static struct ieee80211_supported_band wl1251_band_2ghz = { |
1278 | .channels = wl1251_channels, | 1321 | .channels = wl1251_channels, |
@@ -1293,6 +1336,7 @@ static const struct ieee80211_ops wl1251_ops = { | |||
1293 | .hw_scan = wl1251_op_hw_scan, | 1336 | .hw_scan = wl1251_op_hw_scan, |
1294 | .bss_info_changed = wl1251_op_bss_info_changed, | 1337 | .bss_info_changed = wl1251_op_bss_info_changed, |
1295 | .set_rts_threshold = wl1251_op_set_rts_threshold, | 1338 | .set_rts_threshold = wl1251_op_set_rts_threshold, |
1339 | .conf_tx = wl1251_op_conf_tx, | ||
1296 | }; | 1340 | }; |
1297 | 1341 | ||
1298 | static int wl1251_register_hw(struct wl1251 *wl) | 1342 | static int wl1251_register_hw(struct wl1251 *wl) |
@@ -1338,6 +1382,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1338 | wl->hw->wiphy->max_scan_ssids = 1; | 1382 | wl->hw->wiphy->max_scan_ssids = 1; |
1339 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; | 1383 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; |
1340 | 1384 | ||
1385 | wl->hw->queues = 4; | ||
1386 | |||
1341 | ret = wl1251_register_hw(wl); | 1387 | ret = wl1251_register_hw(wl); |
1342 | if (ret) | 1388 | if (ret) |
1343 | goto out; | 1389 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 9931b197ff77..851dfb65e474 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -26,7 +26,8 @@ | |||
26 | #include "wl1251_cmd.h" | 26 | #include "wl1251_cmd.h" |
27 | #include "wl1251_io.h" | 27 | #include "wl1251_io.h" |
28 | 28 | ||
29 | #define WL1251_WAKEUP_TIMEOUT 2000 | 29 | /* in ms */ |
30 | #define WL1251_WAKEUP_TIMEOUT 100 | ||
30 | 31 | ||
31 | void wl1251_elp_work(struct work_struct *work) | 32 | void wl1251_elp_work(struct work_struct *work) |
32 | { | 33 | { |
@@ -67,7 +68,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) | |||
67 | 68 | ||
68 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | 69 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) |
69 | { | 70 | { |
70 | unsigned long timeout; | 71 | unsigned long timeout, start; |
71 | u32 elp_reg; | 72 | u32 elp_reg; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!wl->elp) |
@@ -75,6 +76,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
75 | 76 | ||
76 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1251_debug(DEBUG_PSM, "waking up chip from elp"); |
77 | 78 | ||
79 | start = jiffies; | ||
78 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); |
79 | 81 | ||
80 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 82 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
@@ -95,8 +97,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
95 | } | 97 | } |
96 | 98 | ||
97 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", | 99 | wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", |
98 | jiffies_to_msecs(jiffies) - | 100 | jiffies_to_msecs(jiffies - start)); |
99 | (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); | ||
100 | 101 | ||
101 | wl->elp = false; | 102 | wl->elp = false; |
102 | 103 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index f84cc89cbffc..b56732226cc0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -126,7 +126,7 @@ static void wl1251_rx_body(struct wl1251 *wl, | |||
126 | if (wl->rx_current_buffer) | 126 | if (wl->rx_current_buffer) |
127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; | 127 | rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; |
128 | 128 | ||
129 | skb = dev_alloc_skb(length); | 129 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
130 | if (!skb) { | 130 | if (!skb) { |
131 | wl1251_error("Couldn't allocate RX frame"); | 131 | wl1251_error("Couldn't allocate RX frame"); |
132 | return; | 132 | return; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index f85970615849..c8223185efd2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c | |||
@@ -167,8 +167,7 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, | |||
167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); | 167 | tx_hdr->expiry_time = cpu_to_le32(1 << 16); |
168 | tx_hdr->id = id; | 168 | tx_hdr->id = id; |
169 | 169 | ||
170 | /* FIXME: how to get the correct queue id? */ | 170 | tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb)); |
171 | tx_hdr->xmit_queue = 0; | ||
172 | 171 | ||
173 | wl1251_tx_control(tx_hdr, control, fc); | 172 | wl1251_tx_control(tx_hdr, control, fc); |
174 | wl1251_tx_frag_block_num(tx_hdr); | 173 | wl1251_tx_frag_block_num(tx_hdr); |
@@ -220,6 +219,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
220 | /* align the buffer on a 4-byte boundary */ | 219 | /* align the buffer on a 4-byte boundary */ |
221 | skb_reserve(skb, offset); | 220 | skb_reserve(skb, offset); |
222 | memmove(skb->data, src, skb->len); | 221 | memmove(skb->data, src, skb->len); |
222 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | ||
223 | } else { | 223 | } else { |
224 | wl1251_info("No handler, fixme!"); | 224 | wl1251_info("No handler, fixme!"); |
225 | return -EINVAL; | 225 | return -EINVAL; |
@@ -237,8 +237,9 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
237 | 237 | ||
238 | wl1251_mem_write(wl, addr, skb->data, len); | 238 | wl1251_mem_write(wl, addr, skb->data, len); |
239 | 239 | ||
240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", | 240 | wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x " |
241 | tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); | 241 | "queue %d", tx_hdr->id, skb, tx_hdr->length, |
242 | tx_hdr->rate, tx_hdr->xmit_queue); | ||
242 | 243 | ||
243 | return 0; | 244 | return 0; |
244 | } | 245 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 7c1c1665c810..55856c6bb97a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define __WL1251_TX_H__ | 26 | #define __WL1251_TX_H__ |
27 | 27 | ||
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include "wl1251_acx.h" | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * | 32 | * |
@@ -209,6 +210,22 @@ struct tx_result { | |||
209 | u8 done_2; | 210 | u8 done_2; |
210 | } __attribute__ ((packed)); | 211 | } __attribute__ ((packed)); |
211 | 212 | ||
213 | static inline int wl1251_tx_get_queue(int queue) | ||
214 | { | ||
215 | switch (queue) { | ||
216 | case 0: | ||
217 | return QOS_AC_VO; | ||
218 | case 1: | ||
219 | return QOS_AC_VI; | ||
220 | case 2: | ||
221 | return QOS_AC_BE; | ||
222 | case 3: | ||
223 | return QOS_AC_BK; | ||
224 | default: | ||
225 | return QOS_AC_BE; | ||
226 | } | ||
227 | } | ||
228 | |||
212 | void wl1251_tx_work(struct work_struct *work); | 229 | void wl1251_tx_work(struct work_struct *work); |
213 | void wl1251_tx_complete(struct wl1251 *wl); | 230 | void wl1251_tx_complete(struct wl1251 *wl); |
214 | void wl1251_tx_flush(struct wl1251 *wl); | 231 | void wl1251_tx_flush(struct wl1251 *wl); |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ac19ecd19cfe..4daf1c94ec04 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -1078,11 +1078,15 @@ static int eject_installer(struct usb_interface *intf) | |||
1078 | int r; | 1078 | int r; |
1079 | 1079 | ||
1080 | /* Find bulk out endpoint */ | 1080 | /* Find bulk out endpoint */ |
1081 | endpoint = &iface_desc->endpoint[1].desc; | 1081 | for (r = 1; r >= 0; r--) { |
1082 | if (usb_endpoint_dir_out(endpoint) && | 1082 | endpoint = &iface_desc->endpoint[r].desc; |
1083 | usb_endpoint_xfer_bulk(endpoint)) { | 1083 | if (usb_endpoint_dir_out(endpoint) && |
1084 | bulk_out_ep = endpoint->bEndpointAddress; | 1084 | usb_endpoint_xfer_bulk(endpoint)) { |
1085 | } else { | 1085 | bulk_out_ep = endpoint->bEndpointAddress; |
1086 | break; | ||
1087 | } | ||
1088 | } | ||
1089 | if (r == -1) { | ||
1086 | dev_err(&udev->dev, | 1090 | dev_err(&udev->dev, |
1087 | "zd1211rw: Could not find bulk out endpoint\n"); | 1091 | "zd1211rw: Could not find bulk out endpoint\n"); |
1088 | return -ENODEV; | 1092 | return -ENODEV; |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 163c840437d6..d62edc7df3ae 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -707,6 +707,10 @@ struct ieee80211_mgmt { | |||
707 | u8 action; | 707 | u8 action; |
708 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; | 708 | u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; |
709 | } __attribute__ ((packed)) sa_query; | 709 | } __attribute__ ((packed)) sa_query; |
710 | struct { | ||
711 | u8 action; | ||
712 | u8 smps_control; | ||
713 | } __attribute__ ((packed)) ht_smps; | ||
710 | } u; | 714 | } u; |
711 | } __attribute__ ((packed)) action; | 715 | } __attribute__ ((packed)) action; |
712 | } u; | 716 | } u; |
@@ -771,7 +775,10 @@ struct ieee80211_bar { | |||
771 | /** | 775 | /** |
772 | * struct ieee80211_mcs_info - MCS information | 776 | * struct ieee80211_mcs_info - MCS information |
773 | * @rx_mask: RX mask | 777 | * @rx_mask: RX mask |
774 | * @rx_highest: highest supported RX rate | 778 | * @rx_highest: highest supported RX rate. If set represents |
779 | * the highest supported RX data rate in units of 1 Mbps. | ||
780 | * If this field is 0 this value should not be used to | ||
781 | * consider the highest RX data rate supported. | ||
775 | * @tx_params: TX parameters | 782 | * @tx_params: TX parameters |
776 | */ | 783 | */ |
777 | struct ieee80211_mcs_info { | 784 | struct ieee80211_mcs_info { |
@@ -824,6 +831,7 @@ struct ieee80211_ht_cap { | |||
824 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 | 831 | #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 |
825 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 | 832 | #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 |
826 | #define IEEE80211_HT_CAP_SM_PS 0x000C | 833 | #define IEEE80211_HT_CAP_SM_PS 0x000C |
834 | #define IEEE80211_HT_CAP_SM_PS_SHIFT 2 | ||
827 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 | 835 | #define IEEE80211_HT_CAP_GRN_FLD 0x0010 |
828 | #define IEEE80211_HT_CAP_SGI_20 0x0020 | 836 | #define IEEE80211_HT_CAP_SGI_20 0x0020 |
829 | #define IEEE80211_HT_CAP_SGI_40 0x0040 | 837 | #define IEEE80211_HT_CAP_SGI_40 0x0040 |
@@ -839,6 +847,7 @@ struct ieee80211_ht_cap { | |||
839 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ | 847 | /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ |
840 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 | 848 | #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 |
841 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C | 849 | #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C |
850 | #define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 | ||
842 | 851 | ||
843 | /* | 852 | /* |
844 | * Maximum length of AMPDU that the STA can receive. | 853 | * Maximum length of AMPDU that the STA can receive. |
@@ -922,12 +931,17 @@ struct ieee80211_ht_info { | |||
922 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | 931 | #define IEEE80211_MAX_AMPDU_BUF 0x40 |
923 | 932 | ||
924 | 933 | ||
925 | /* Spatial Multiplexing Power Save Modes */ | 934 | /* Spatial Multiplexing Power Save Modes (for capability) */ |
926 | #define WLAN_HT_CAP_SM_PS_STATIC 0 | 935 | #define WLAN_HT_CAP_SM_PS_STATIC 0 |
927 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 | 936 | #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 |
928 | #define WLAN_HT_CAP_SM_PS_INVALID 2 | 937 | #define WLAN_HT_CAP_SM_PS_INVALID 2 |
929 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 | 938 | #define WLAN_HT_CAP_SM_PS_DISABLED 3 |
930 | 939 | ||
940 | /* for SM power control field lower two bits */ | ||
941 | #define WLAN_HT_SMPS_CONTROL_DISABLED 0 | ||
942 | #define WLAN_HT_SMPS_CONTROL_STATIC 1 | ||
943 | #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 | ||
944 | |||
931 | /* Authentication algorithms */ | 945 | /* Authentication algorithms */ |
932 | #define WLAN_AUTH_OPEN 0 | 946 | #define WLAN_AUTH_OPEN 0 |
933 | #define WLAN_AUTH_SHARED_KEY 1 | 947 | #define WLAN_AUTH_SHARED_KEY 1 |
@@ -1150,6 +1164,18 @@ enum ieee80211_spectrum_mgmt_actioncode { | |||
1150 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, | 1164 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, |
1151 | }; | 1165 | }; |
1152 | 1166 | ||
1167 | /* HT action codes */ | ||
1168 | enum ieee80211_ht_actioncode { | ||
1169 | WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, | ||
1170 | WLAN_HT_ACTION_SMPS = 1, | ||
1171 | WLAN_HT_ACTION_PSMP = 2, | ||
1172 | WLAN_HT_ACTION_PCO_PHASE = 3, | ||
1173 | WLAN_HT_ACTION_CSI = 4, | ||
1174 | WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, | ||
1175 | WLAN_HT_ACTION_COMPRESSED_BF = 6, | ||
1176 | WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, | ||
1177 | }; | ||
1178 | |||
1153 | /* Security key length */ | 1179 | /* Security key length */ |
1154 | enum ieee80211_key_len { | 1180 | enum ieee80211_key_len { |
1155 | WLAN_KEY_LEN_WEP40 = 5, | 1181 | WLAN_KEY_LEN_WEP40 = 5, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0884b9a0f778..542a477a94da 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1578,7 +1578,7 @@ unsigned int ieee80211_hdrlen(__le16 fc); | |||
1578 | * @addr: the device MAC address | 1578 | * @addr: the device MAC address |
1579 | * @iftype: the virtual interface type | 1579 | * @iftype: the virtual interface type |
1580 | */ | 1580 | */ |
1581 | int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, | 1581 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
1582 | enum nl80211_iftype iftype); | 1582 | enum nl80211_iftype iftype); |
1583 | 1583 | ||
1584 | /** | 1584 | /** |
@@ -1589,10 +1589,28 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, | |||
1589 | * @bssid: the network bssid (used only for iftype STATION and ADHOC) | 1589 | * @bssid: the network bssid (used only for iftype STATION and ADHOC) |
1590 | * @qos: build 802.11 QoS data frame | 1590 | * @qos: build 802.11 QoS data frame |
1591 | */ | 1591 | */ |
1592 | int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, | 1592 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
1593 | enum nl80211_iftype iftype, u8 *bssid, bool qos); | 1593 | enum nl80211_iftype iftype, u8 *bssid, bool qos); |
1594 | 1594 | ||
1595 | /** | 1595 | /** |
1596 | * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame | ||
1597 | * | ||
1598 | * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of | ||
1599 | * 802.3 frames. The @list will be empty if the decode fails. The | ||
1600 | * @skb is consumed after the function returns. | ||
1601 | * | ||
1602 | * @skb: The input IEEE 802.11n A-MSDU frame. | ||
1603 | * @list: The output list of 802.3 frames. It must be allocated and | ||
1604 | * initialized by by the caller. | ||
1605 | * @addr: The device MAC address. | ||
1606 | * @iftype: The device interface type. | ||
1607 | * @extra_headroom: The hardware extra headroom for SKBs in the @list. | ||
1608 | */ | ||
1609 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | ||
1610 | const u8 *addr, enum nl80211_iftype iftype, | ||
1611 | const unsigned int extra_headroom); | ||
1612 | |||
1613 | /** | ||
1596 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame | 1614 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame |
1597 | * @skb: the data frame | 1615 | * @skb: the data frame |
1598 | */ | 1616 | */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 538d6b761887..494ac69ff477 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -597,8 +597,10 @@ enum ieee80211_conf_flags { | |||
597 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed | 597 | * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed |
598 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed | 598 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed |
599 | * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed | 599 | * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed |
600 | * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed | ||
600 | */ | 601 | */ |
601 | enum ieee80211_conf_changed { | 602 | enum ieee80211_conf_changed { |
603 | IEEE80211_CONF_CHANGE_SMPS = BIT(1), | ||
602 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), | 604 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), |
603 | IEEE80211_CONF_CHANGE_MONITOR = BIT(3), | 605 | IEEE80211_CONF_CHANGE_MONITOR = BIT(3), |
604 | IEEE80211_CONF_CHANGE_PS = BIT(4), | 606 | IEEE80211_CONF_CHANGE_PS = BIT(4), |
@@ -609,6 +611,21 @@ enum ieee80211_conf_changed { | |||
609 | }; | 611 | }; |
610 | 612 | ||
611 | /** | 613 | /** |
614 | * enum ieee80211_smps_mode - spatial multiplexing power save mode | ||
615 | * | ||
616 | * @ | ||
617 | */ | ||
618 | enum ieee80211_smps_mode { | ||
619 | IEEE80211_SMPS_AUTOMATIC, | ||
620 | IEEE80211_SMPS_OFF, | ||
621 | IEEE80211_SMPS_STATIC, | ||
622 | IEEE80211_SMPS_DYNAMIC, | ||
623 | |||
624 | /* keep last */ | ||
625 | IEEE80211_SMPS_NUM_MODES, | ||
626 | }; | ||
627 | |||
628 | /** | ||
612 | * struct ieee80211_conf - configuration of the device | 629 | * struct ieee80211_conf - configuration of the device |
613 | * | 630 | * |
614 | * This struct indicates how the driver shall configure the hardware. | 631 | * This struct indicates how the driver shall configure the hardware. |
@@ -636,6 +653,10 @@ enum ieee80211_conf_changed { | |||
636 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" | 653 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" |
637 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the | 654 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the |
638 | * number of transmissions not the number of retries | 655 | * number of transmissions not the number of retries |
656 | * | ||
657 | * @smps_mode: spatial multiplexing powersave mode; note that | ||
658 | * %IEEE80211_SMPS_STATIC is used when the device is not | ||
659 | * configured for an HT channel | ||
639 | */ | 660 | */ |
640 | struct ieee80211_conf { | 661 | struct ieee80211_conf { |
641 | u32 flags; | 662 | u32 flags; |
@@ -648,6 +669,7 @@ struct ieee80211_conf { | |||
648 | 669 | ||
649 | struct ieee80211_channel *channel; | 670 | struct ieee80211_channel *channel; |
650 | enum nl80211_channel_type channel_type; | 671 | enum nl80211_channel_type channel_type; |
672 | enum ieee80211_smps_mode smps_mode; | ||
651 | }; | 673 | }; |
652 | 674 | ||
653 | /** | 675 | /** |
@@ -659,12 +681,14 @@ struct ieee80211_conf { | |||
659 | * @type: type of this virtual interface | 681 | * @type: type of this virtual interface |
660 | * @bss_conf: BSS configuration for this interface, either our own | 682 | * @bss_conf: BSS configuration for this interface, either our own |
661 | * or the BSS we're associated to | 683 | * or the BSS we're associated to |
684 | * @addr: address of this interface | ||
662 | * @drv_priv: data area for driver use, will always be aligned to | 685 | * @drv_priv: data area for driver use, will always be aligned to |
663 | * sizeof(void *). | 686 | * sizeof(void *). |
664 | */ | 687 | */ |
665 | struct ieee80211_vif { | 688 | struct ieee80211_vif { |
666 | enum nl80211_iftype type; | 689 | enum nl80211_iftype type; |
667 | struct ieee80211_bss_conf bss_conf; | 690 | struct ieee80211_bss_conf bss_conf; |
691 | u8 addr[ETH_ALEN]; | ||
668 | /* must be last */ | 692 | /* must be last */ |
669 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 693 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
670 | }; | 694 | }; |
@@ -928,6 +952,16 @@ enum ieee80211_tkip_key_type { | |||
928 | * @IEEE80211_HW_BEACON_FILTER: | 952 | * @IEEE80211_HW_BEACON_FILTER: |
929 | * Hardware supports dropping of irrelevant beacon frames to | 953 | * Hardware supports dropping of irrelevant beacon frames to |
930 | * avoid waking up cpu. | 954 | * avoid waking up cpu. |
955 | * | ||
956 | * @IEEE80211_HW_SUPPORTS_STATIC_SMPS: | ||
957 | * Hardware supports static spatial multiplexing powersave, | ||
958 | * ie. can turn off all but one chain even on HT connections | ||
959 | * that should be using more chains. | ||
960 | * | ||
961 | * @IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS: | ||
962 | * Hardware supports dynamic spatial multiplexing powersave, | ||
963 | * ie. can turn off all but one chain and then wake the rest | ||
964 | * up as required after, for example, rts/cts handshake. | ||
931 | */ | 965 | */ |
932 | enum ieee80211_hw_flags { | 966 | enum ieee80211_hw_flags { |
933 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 967 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -945,6 +979,8 @@ enum ieee80211_hw_flags { | |||
945 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, | 979 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, |
946 | IEEE80211_HW_MFP_CAPABLE = 1<<13, | 980 | IEEE80211_HW_MFP_CAPABLE = 1<<13, |
947 | IEEE80211_HW_BEACON_FILTER = 1<<14, | 981 | IEEE80211_HW_BEACON_FILTER = 1<<14, |
982 | IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, | ||
983 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, | ||
948 | }; | 984 | }; |
949 | 985 | ||
950 | /** | 986 | /** |
@@ -1213,6 +1249,31 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | |||
1213 | */ | 1249 | */ |
1214 | 1250 | ||
1215 | /** | 1251 | /** |
1252 | * DOC: Spatial multiplexing power save | ||
1253 | * | ||
1254 | * SMPS (Spatial multiplexing power save) is a mechanism to conserve | ||
1255 | * power in an 802.11n implementation. For details on the mechanism | ||
1256 | * and rationale, please refer to 802.11 (as amended by 802.11n-2009) | ||
1257 | * "11.2.3 SM power save". | ||
1258 | * | ||
1259 | * The mac80211 implementation is capable of sending action frames | ||
1260 | * to update the AP about the station's SMPS mode, and will instruct | ||
1261 | * the driver to enter the specific mode. It will also announce the | ||
1262 | * requested SMPS mode during the association handshake. Hardware | ||
1263 | * support for this feature is required, and can be indicated by | ||
1264 | * hardware flags. | ||
1265 | * | ||
1266 | * The default mode will be "automatic", which nl80211/cfg80211 | ||
1267 | * defines to be dynamic SMPS in (regular) powersave, and SMPS | ||
1268 | * turned off otherwise. | ||
1269 | * | ||
1270 | * To support this feature, the driver must set the appropriate | ||
1271 | * hardware support flags, and handle the SMPS flag to the config() | ||
1272 | * operation. It will then with this mechanism be instructed to | ||
1273 | * enter the requested SMPS mode while associated to an HT AP. | ||
1274 | */ | ||
1275 | |||
1276 | /** | ||
1216 | * DOC: Frame filtering | 1277 | * DOC: Frame filtering |
1217 | * | 1278 | * |
1218 | * mac80211 requires to see many management frames for proper | 1279 | * mac80211 requires to see many management frames for proper |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a10d508b07e1..a952b7f8c648 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -96,18 +96,6 @@ menuconfig MAC80211_DEBUG_MENU | |||
96 | ---help--- | 96 | ---help--- |
97 | This option collects various mac80211 debug settings. | 97 | This option collects various mac80211 debug settings. |
98 | 98 | ||
99 | config MAC80211_DEBUG_PACKET_ALIGNMENT | ||
100 | bool "Enable packet alignment debugging" | ||
101 | depends on MAC80211_DEBUG_MENU | ||
102 | ---help--- | ||
103 | This option is recommended for driver authors and strongly | ||
104 | discouraged for everybody else, it will trigger a warning | ||
105 | when a driver hands mac80211 a buffer that is aligned in | ||
106 | a way that will cause problems with the IP stack on some | ||
107 | architectures. | ||
108 | |||
109 | Say N unless you're writing a mac80211 based driver. | ||
110 | |||
111 | config MAC80211_NOINLINE | 99 | config MAC80211_NOINLINE |
112 | bool "Do not inline TX/RX handlers" | 100 | bool "Do not inline TX/RX handlers" |
113 | depends on MAC80211_DEBUG_MENU | 101 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 51c7dc3c4c3b..a978e666ed6f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -41,8 +41,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
41 | sta->sta.addr, tid); | 41 | sta->sta.addr, tid); |
42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
43 | 43 | ||
44 | if (drv_ampdu_action(local, &sta->sdata->vif, | 44 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
45 | IEEE80211_AMPDU_RX_STOP, | ||
46 | &sta->sta, tid, NULL)) | 45 | &sta->sta, tid, NULL)) |
47 | printk(KERN_DEBUG "HW problem - can not stop rx " | 46 | printk(KERN_DEBUG "HW problem - can not stop rx " |
48 | "aggregation for tid %d\n", tid); | 47 | "aggregation for tid %d\n", tid); |
@@ -83,12 +82,11 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | 82 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, |
84 | u16 initiator, u16 reason) | 83 | u16 initiator, u16 reason) |
85 | { | 84 | { |
86 | struct ieee80211_local *local = sdata->local; | ||
87 | struct sta_info *sta; | 85 | struct sta_info *sta; |
88 | 86 | ||
89 | rcu_read_lock(); | 87 | rcu_read_lock(); |
90 | 88 | ||
91 | sta = sta_info_get(local, ra); | 89 | sta = sta_info_get(sdata, ra); |
92 | if (!sta) { | 90 | if (!sta) { |
93 | rcu_read_unlock(); | 91 | rcu_read_unlock(); |
94 | return; | 92 | return; |
@@ -136,7 +134,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
136 | 134 | ||
137 | if (!skb) { | 135 | if (!skb) { |
138 | printk(KERN_DEBUG "%s: failed to allocate buffer " | 136 | printk(KERN_DEBUG "%s: failed to allocate buffer " |
139 | "for addba resp frame\n", sdata->dev->name); | 137 | "for addba resp frame\n", sdata->name); |
140 | return; | 138 | return; |
141 | } | 139 | } |
142 | 140 | ||
@@ -144,10 +142,10 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
144 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 142 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
145 | memset(mgmt, 0, 24); | 143 | memset(mgmt, 0, 24); |
146 | memcpy(mgmt->da, da, ETH_ALEN); | 144 | memcpy(mgmt->da, da, ETH_ALEN); |
147 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 145 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
148 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 146 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
149 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 147 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
150 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 148 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
151 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 149 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
152 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 150 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
153 | 151 | ||
@@ -281,8 +279,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
281 | goto end; | 279 | goto end; |
282 | } | 280 | } |
283 | 281 | ||
284 | ret = drv_ampdu_action(local, &sta->sdata->vif, | 282 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
285 | IEEE80211_AMPDU_RX_START, | ||
286 | &sta->sta, tid, &start_seq_num); | 283 | &sta->sta, tid, &start_seq_num); |
287 | #ifdef CONFIG_MAC80211_HT_DEBUG | 284 | #ifdef CONFIG_MAC80211_HT_DEBUG |
288 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 285 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5e3a7eccef5a..ceda36618d3c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -58,17 +58,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
58 | 58 | ||
59 | if (!skb) { | 59 | if (!skb) { |
60 | printk(KERN_ERR "%s: failed to allocate buffer " | 60 | printk(KERN_ERR "%s: failed to allocate buffer " |
61 | "for addba request frame\n", sdata->dev->name); | 61 | "for addba request frame\n", sdata->name); |
62 | return; | 62 | return; |
63 | } | 63 | } |
64 | skb_reserve(skb, local->hw.extra_tx_headroom); | 64 | skb_reserve(skb, local->hw.extra_tx_headroom); |
65 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 65 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
66 | memset(mgmt, 0, 24); | 66 | memset(mgmt, 0, 24); |
67 | memcpy(mgmt->da, da, ETH_ALEN); | 67 | memcpy(mgmt->da, da, ETH_ALEN); |
68 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 68 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
69 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 69 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
70 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 70 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
71 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 71 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
72 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 72 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
73 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 73 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
74 | 74 | ||
@@ -104,7 +104,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
104 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 104 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); |
105 | if (!skb) { | 105 | if (!skb) { |
106 | printk(KERN_ERR "%s: failed to allocate buffer for " | 106 | printk(KERN_ERR "%s: failed to allocate buffer for " |
107 | "bar frame\n", sdata->dev->name); | 107 | "bar frame\n", sdata->name); |
108 | return; | 108 | return; |
109 | } | 109 | } |
110 | skb_reserve(skb, local->hw.extra_tx_headroom); | 110 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -113,7 +113,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
113 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | 113 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | |
114 | IEEE80211_STYPE_BACK_REQ); | 114 | IEEE80211_STYPE_BACK_REQ); |
115 | memcpy(bar->ra, ra, ETH_ALEN); | 115 | memcpy(bar->ra, ra, ETH_ALEN); |
116 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | 116 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); |
117 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | 117 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; |
118 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | 118 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; |
119 | bar_control |= (u16)(tid << 12); | 119 | bar_control |= (u16)(tid << 12); |
@@ -144,7 +144,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
144 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 144 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
145 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 145 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
146 | 146 | ||
147 | ret = drv_ampdu_action(local, &sta->sdata->vif, | 147 | ret = drv_ampdu_action(local, sta->sdata, |
148 | IEEE80211_AMPDU_TX_STOP, | 148 | IEEE80211_AMPDU_TX_STOP, |
149 | &sta->sta, tid, NULL); | 149 | &sta->sta, tid, NULL); |
150 | 150 | ||
@@ -303,8 +303,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
303 | 303 | ||
304 | start_seq_num = sta->tid_seq[tid]; | 304 | start_seq_num = sta->tid_seq[tid]; |
305 | 305 | ||
306 | ret = drv_ampdu_action(local, &sdata->vif, | 306 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
307 | IEEE80211_AMPDU_TX_START, | ||
308 | pubsta, tid, &start_seq_num); | 307 | pubsta, tid, &start_seq_num); |
309 | 308 | ||
310 | if (ret) { | 309 | if (ret) { |
@@ -420,7 +419,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
420 | ieee80211_agg_splice_finish(local, sta, tid); | 419 | ieee80211_agg_splice_finish(local, sta, tid); |
421 | spin_unlock(&local->ampdu_lock); | 420 | spin_unlock(&local->ampdu_lock); |
422 | 421 | ||
423 | drv_ampdu_action(local, &sta->sdata->vif, | 422 | drv_ampdu_action(local, sta->sdata, |
424 | IEEE80211_AMPDU_TX_OPERATIONAL, | 423 | IEEE80211_AMPDU_TX_OPERATIONAL, |
425 | &sta->sta, tid, NULL); | 424 | &sta->sta, tid, NULL); |
426 | } | 425 | } |
@@ -441,7 +440,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
441 | } | 440 | } |
442 | 441 | ||
443 | rcu_read_lock(); | 442 | rcu_read_lock(); |
444 | sta = sta_info_get(local, ra); | 443 | sta = sta_info_get(sdata, ra); |
445 | if (!sta) { | 444 | if (!sta) { |
446 | rcu_read_unlock(); | 445 | rcu_read_unlock(); |
447 | #ifdef CONFIG_MAC80211_HT_DEBUG | 446 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -489,7 +488,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
489 | #ifdef CONFIG_MAC80211_HT_DEBUG | 488 | #ifdef CONFIG_MAC80211_HT_DEBUG |
490 | if (net_ratelimit()) | 489 | if (net_ratelimit()) |
491 | printk(KERN_WARNING "%s: Not enough memory, " | 490 | printk(KERN_WARNING "%s: Not enough memory, " |
492 | "dropping start BA session", skb->dev->name); | 491 | "dropping start BA session", sdata->name); |
493 | #endif | 492 | #endif |
494 | return; | 493 | return; |
495 | } | 494 | } |
@@ -564,7 +563,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
564 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 563 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
565 | 564 | ||
566 | rcu_read_lock(); | 565 | rcu_read_lock(); |
567 | sta = sta_info_get(local, ra); | 566 | sta = sta_info_get(sdata, ra); |
568 | if (!sta) { | 567 | if (!sta) { |
569 | #ifdef CONFIG_MAC80211_HT_DEBUG | 568 | #ifdef CONFIG_MAC80211_HT_DEBUG |
570 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); | 569 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
@@ -621,7 +620,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
621 | #ifdef CONFIG_MAC80211_HT_DEBUG | 620 | #ifdef CONFIG_MAC80211_HT_DEBUG |
622 | if (net_ratelimit()) | 621 | if (net_ratelimit()) |
623 | printk(KERN_WARNING "%s: Not enough memory, " | 622 | printk(KERN_WARNING "%s: Not enough memory, " |
624 | "dropping stop BA session", skb->dev->name); | 623 | "dropping stop BA session", sdata->name); |
625 | #endif | 624 | #endif |
626 | return; | 625 | return; |
627 | } | 626 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6dc3579c0ac5..63843e3e576a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -150,7 +150,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
150 | rcu_read_lock(); | 150 | rcu_read_lock(); |
151 | 151 | ||
152 | if (mac_addr) { | 152 | if (mac_addr) { |
153 | sta = sta_info_get(sdata->local, mac_addr); | 153 | sta = sta_info_get(sdata, mac_addr); |
154 | if (!sta) { | 154 | if (!sta) { |
155 | ieee80211_key_free(key); | 155 | ieee80211_key_free(key); |
156 | err = -ENOENT; | 156 | err = -ENOENT; |
@@ -181,7 +181,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
181 | if (mac_addr) { | 181 | if (mac_addr) { |
182 | ret = -ENOENT; | 182 | ret = -ENOENT; |
183 | 183 | ||
184 | sta = sta_info_get(sdata->local, mac_addr); | 184 | sta = sta_info_get(sdata, mac_addr); |
185 | if (!sta) | 185 | if (!sta) |
186 | goto out_unlock; | 186 | goto out_unlock; |
187 | 187 | ||
@@ -228,7 +228,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
228 | rcu_read_lock(); | 228 | rcu_read_lock(); |
229 | 229 | ||
230 | if (mac_addr) { | 230 | if (mac_addr) { |
231 | sta = sta_info_get(sdata->local, mac_addr); | 231 | sta = sta_info_get(sdata, mac_addr); |
232 | if (!sta) | 232 | if (!sta) |
233 | goto out; | 233 | goto out; |
234 | 234 | ||
@@ -415,15 +415,13 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
415 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | 415 | static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, |
416 | u8 *mac, struct station_info *sinfo) | 416 | u8 *mac, struct station_info *sinfo) |
417 | { | 417 | { |
418 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 418 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
419 | struct sta_info *sta; | 419 | struct sta_info *sta; |
420 | int ret = -ENOENT; | 420 | int ret = -ENOENT; |
421 | 421 | ||
422 | rcu_read_lock(); | 422 | rcu_read_lock(); |
423 | 423 | ||
424 | /* XXX: verify sta->dev == dev */ | 424 | sta = sta_info_get(sdata, mac); |
425 | |||
426 | sta = sta_info_get(local, mac); | ||
427 | if (sta) { | 425 | if (sta) { |
428 | ret = 0; | 426 | ret = 0; |
429 | sta_set_sinfo(sta, sinfo); | 427 | sta_set_sinfo(sta, sinfo); |
@@ -732,7 +730,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
732 | } else | 730 | } else |
733 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 731 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
734 | 732 | ||
735 | if (compare_ether_addr(mac, dev->dev_addr) == 0) | 733 | if (compare_ether_addr(mac, sdata->vif.addr) == 0) |
736 | return -EINVAL; | 734 | return -EINVAL; |
737 | 735 | ||
738 | if (is_multicast_ether_addr(mac)) | 736 | if (is_multicast_ether_addr(mac)) |
@@ -779,8 +777,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
779 | if (mac) { | 777 | if (mac) { |
780 | rcu_read_lock(); | 778 | rcu_read_lock(); |
781 | 779 | ||
782 | /* XXX: get sta belonging to dev */ | 780 | sta = sta_info_get(sdata, mac); |
783 | sta = sta_info_get(local, mac); | ||
784 | if (!sta) { | 781 | if (!sta) { |
785 | rcu_read_unlock(); | 782 | rcu_read_unlock(); |
786 | return -ENOENT; | 783 | return -ENOENT; |
@@ -801,14 +798,14 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
801 | u8 *mac, | 798 | u8 *mac, |
802 | struct station_parameters *params) | 799 | struct station_parameters *params) |
803 | { | 800 | { |
801 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
804 | struct ieee80211_local *local = wiphy_priv(wiphy); | 802 | struct ieee80211_local *local = wiphy_priv(wiphy); |
805 | struct sta_info *sta; | 803 | struct sta_info *sta; |
806 | struct ieee80211_sub_if_data *vlansdata; | 804 | struct ieee80211_sub_if_data *vlansdata; |
807 | 805 | ||
808 | rcu_read_lock(); | 806 | rcu_read_lock(); |
809 | 807 | ||
810 | /* XXX: get sta belonging to dev */ | 808 | sta = sta_info_get(sdata, mac); |
811 | sta = sta_info_get(local, mac); | ||
812 | if (!sta) { | 809 | if (!sta) { |
813 | rcu_read_unlock(); | 810 | rcu_read_unlock(); |
814 | return -ENOENT; | 811 | return -ENOENT; |
@@ -847,7 +844,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
847 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | 844 | static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, |
848 | u8 *dst, u8 *next_hop) | 845 | u8 *dst, u8 *next_hop) |
849 | { | 846 | { |
850 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
851 | struct ieee80211_sub_if_data *sdata; | 847 | struct ieee80211_sub_if_data *sdata; |
852 | struct mesh_path *mpath; | 848 | struct mesh_path *mpath; |
853 | struct sta_info *sta; | 849 | struct sta_info *sta; |
@@ -856,7 +852,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
856 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 852 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
857 | 853 | ||
858 | rcu_read_lock(); | 854 | rcu_read_lock(); |
859 | sta = sta_info_get(local, next_hop); | 855 | sta = sta_info_get(sdata, next_hop); |
860 | if (!sta) { | 856 | if (!sta) { |
861 | rcu_read_unlock(); | 857 | rcu_read_unlock(); |
862 | return -ENOENT; | 858 | return -ENOENT; |
@@ -895,7 +891,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
895 | struct net_device *dev, | 891 | struct net_device *dev, |
896 | u8 *dst, u8 *next_hop) | 892 | u8 *dst, u8 *next_hop) |
897 | { | 893 | { |
898 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
899 | struct ieee80211_sub_if_data *sdata; | 894 | struct ieee80211_sub_if_data *sdata; |
900 | struct mesh_path *mpath; | 895 | struct mesh_path *mpath; |
901 | struct sta_info *sta; | 896 | struct sta_info *sta; |
@@ -904,7 +899,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
904 | 899 | ||
905 | rcu_read_lock(); | 900 | rcu_read_lock(); |
906 | 901 | ||
907 | sta = sta_info_get(local, next_hop); | 902 | sta = sta_info_get(sdata, next_hop); |
908 | if (!sta) { | 903 | if (!sta) { |
909 | rcu_read_unlock(); | 904 | rcu_read_unlock(); |
910 | return -ENOENT; | 905 | return -ENOENT; |
@@ -1324,6 +1319,50 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) | |||
1324 | } | 1319 | } |
1325 | #endif | 1320 | #endif |
1326 | 1321 | ||
1322 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | ||
1323 | enum ieee80211_smps_mode smps_mode) | ||
1324 | { | ||
1325 | const u8 *ap; | ||
1326 | enum ieee80211_smps_mode old_req; | ||
1327 | int err; | ||
1328 | |||
1329 | old_req = sdata->u.mgd.req_smps; | ||
1330 | sdata->u.mgd.req_smps = smps_mode; | ||
1331 | |||
1332 | if (old_req == smps_mode && | ||
1333 | smps_mode != IEEE80211_SMPS_AUTOMATIC) | ||
1334 | return 0; | ||
1335 | |||
1336 | /* | ||
1337 | * If not associated, or current association is not an HT | ||
1338 | * association, there's no need to send an action frame. | ||
1339 | */ | ||
1340 | if (!sdata->u.mgd.associated || | ||
1341 | sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { | ||
1342 | mutex_lock(&sdata->local->iflist_mtx); | ||
1343 | ieee80211_recalc_smps(sdata->local, sdata); | ||
1344 | mutex_unlock(&sdata->local->iflist_mtx); | ||
1345 | return 0; | ||
1346 | } | ||
1347 | |||
1348 | ap = sdata->u.mgd.associated->cbss.bssid; | ||
1349 | |||
1350 | if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { | ||
1351 | if (sdata->u.mgd.powersave) | ||
1352 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
1353 | else | ||
1354 | smps_mode = IEEE80211_SMPS_OFF; | ||
1355 | } | ||
1356 | |||
1357 | /* send SM PS frame to AP */ | ||
1358 | err = ieee80211_send_smps_action(sdata, smps_mode, | ||
1359 | ap, ap); | ||
1360 | if (err) | ||
1361 | sdata->u.mgd.req_smps = old_req; | ||
1362 | |||
1363 | return err; | ||
1364 | } | ||
1365 | |||
1327 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | 1366 | static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, |
1328 | bool enabled, int timeout) | 1367 | bool enabled, int timeout) |
1329 | { | 1368 | { |
@@ -1341,6 +1380,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1341 | sdata->u.mgd.powersave = enabled; | 1380 | sdata->u.mgd.powersave = enabled; |
1342 | conf->dynamic_ps_timeout = timeout; | 1381 | conf->dynamic_ps_timeout = timeout; |
1343 | 1382 | ||
1383 | /* no change, but if automatic follow powersave */ | ||
1384 | mutex_lock(&sdata->u.mgd.mtx); | ||
1385 | __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); | ||
1386 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1387 | |||
1344 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) | 1388 | if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) |
1345 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 1389 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
1346 | 1390 | ||
@@ -1356,15 +1400,25 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1356 | { | 1400 | { |
1357 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1401 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1358 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1402 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1359 | int i, err = -EINVAL; | 1403 | int i; |
1360 | u32 target_rate; | 1404 | u32 target_rate; |
1361 | struct ieee80211_supported_band *sband; | 1405 | struct ieee80211_supported_band *sband; |
1362 | 1406 | ||
1407 | /* | ||
1408 | * This _could_ be supported by providing a hook for | ||
1409 | * drivers for this function, but at this point it | ||
1410 | * doesn't seem worth bothering. | ||
1411 | */ | ||
1412 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
1413 | return -EOPNOTSUPP; | ||
1414 | |||
1363 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1415 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1364 | 1416 | ||
1365 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | 1417 | /* |
1418 | * target_rate = -1, rate->fixed = 0 means auto only, so use all rates | ||
1366 | * target_rate = X, rate->fixed = 1 means only rate X | 1419 | * target_rate = X, rate->fixed = 1 means only rate X |
1367 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | 1420 | * target_rate = X, rate->fixed = 0 means all rates <= X |
1421 | */ | ||
1368 | sdata->max_ratectrl_rateidx = -1; | 1422 | sdata->max_ratectrl_rateidx = -1; |
1369 | sdata->force_unicast_rateidx = -1; | 1423 | sdata->force_unicast_rateidx = -1; |
1370 | 1424 | ||
@@ -1375,20 +1429,18 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1375 | else | 1429 | else |
1376 | return 0; | 1430 | return 0; |
1377 | 1431 | ||
1378 | for (i=0; i< sband->n_bitrates; i++) { | 1432 | for (i = 0; i< sband->n_bitrates; i++) { |
1379 | struct ieee80211_rate *brate = &sband->bitrates[i]; | 1433 | if (target_rate != sband->bitrates[i].bitrate) |
1380 | int this_rate = brate->bitrate; | 1434 | continue; |
1381 | 1435 | ||
1382 | if (target_rate == this_rate) { | 1436 | /* requested bitrate found */ |
1383 | sdata->max_ratectrl_rateidx = i; | 1437 | sdata->max_ratectrl_rateidx = i; |
1384 | if (mask->fixed) | 1438 | if (mask->fixed) |
1385 | sdata->force_unicast_rateidx = i; | 1439 | sdata->force_unicast_rateidx = i; |
1386 | err = 0; | 1440 | return 0; |
1387 | break; | ||
1388 | } | ||
1389 | } | 1441 | } |
1390 | 1442 | ||
1391 | return err; | 1443 | return -EINVAL; |
1392 | } | 1444 | } |
1393 | 1445 | ||
1394 | struct cfg80211_ops mac80211_config_ops = { | 1446 | struct cfg80211_ops mac80211_config_ops = { |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index e0f5224630da..d12e743cb4e1 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -56,7 +56,7 @@ KEY_CONF_FILE(keyidx, D); | |||
56 | KEY_CONF_FILE(hw_key_idx, D); | 56 | KEY_CONF_FILE(hw_key_idx, D); |
57 | KEY_FILE(flags, X); | 57 | KEY_FILE(flags, X); |
58 | KEY_FILE(tx_rx_count, D); | 58 | KEY_FILE(tx_rx_count, D); |
59 | KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); | 59 | KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n"); |
60 | KEY_OPS(ifindex); | 60 | KEY_OPS(ifindex); |
61 | 61 | ||
62 | static ssize_t key_algorithm_read(struct file *file, | 62 | static ssize_t key_algorithm_read(struct file *file, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 472b2039906c..355983503885 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -41,6 +41,30 @@ static ssize_t ieee80211_if_read( | |||
41 | return ret; | 41 | return ret; |
42 | } | 42 | } |
43 | 43 | ||
44 | static ssize_t ieee80211_if_write( | ||
45 | struct ieee80211_sub_if_data *sdata, | ||
46 | const char __user *userbuf, | ||
47 | size_t count, loff_t *ppos, | ||
48 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | ||
49 | { | ||
50 | u8 *buf; | ||
51 | ssize_t ret = -ENODEV; | ||
52 | |||
53 | buf = kzalloc(count, GFP_KERNEL); | ||
54 | if (!buf) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | if (copy_from_user(buf, userbuf, count)) | ||
58 | return -EFAULT; | ||
59 | |||
60 | rtnl_lock(); | ||
61 | if (sdata->dev->reg_state == NETREG_REGISTERED) | ||
62 | ret = (*write)(sdata, buf, count); | ||
63 | rtnl_unlock(); | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
44 | #define IEEE80211_IF_FMT(name, field, format_string) \ | 68 | #define IEEE80211_IF_FMT(name, field, format_string) \ |
45 | static ssize_t ieee80211_if_fmt_##name( \ | 69 | static ssize_t ieee80211_if_fmt_##name( \ |
46 | const struct ieee80211_sub_if_data *sdata, char *buf, \ | 70 | const struct ieee80211_sub_if_data *sdata, char *buf, \ |
@@ -71,7 +95,7 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
71 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 95 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
72 | } | 96 | } |
73 | 97 | ||
74 | #define __IEEE80211_IF_FILE(name) \ | 98 | #define __IEEE80211_IF_FILE(name, _write) \ |
75 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 99 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
76 | char __user *userbuf, \ | 100 | char __user *userbuf, \ |
77 | size_t count, loff_t *ppos) \ | 101 | size_t count, loff_t *ppos) \ |
@@ -82,12 +106,24 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ | |||
82 | } \ | 106 | } \ |
83 | static const struct file_operations name##_ops = { \ | 107 | static const struct file_operations name##_ops = { \ |
84 | .read = ieee80211_if_read_##name, \ | 108 | .read = ieee80211_if_read_##name, \ |
109 | .write = (_write), \ | ||
85 | .open = mac80211_open_file_generic, \ | 110 | .open = mac80211_open_file_generic, \ |
86 | } | 111 | } |
87 | 112 | ||
113 | #define __IEEE80211_IF_FILE_W(name) \ | ||
114 | static ssize_t ieee80211_if_write_##name(struct file *file, \ | ||
115 | const char __user *userbuf, \ | ||
116 | size_t count, loff_t *ppos) \ | ||
117 | { \ | ||
118 | return ieee80211_if_write(file->private_data, userbuf, count, \ | ||
119 | ppos, ieee80211_if_parse_##name); \ | ||
120 | } \ | ||
121 | __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) | ||
122 | |||
123 | |||
88 | #define IEEE80211_IF_FILE(name, field, format) \ | 124 | #define IEEE80211_IF_FILE(name, field, format) \ |
89 | IEEE80211_IF_FMT_##format(name, field) \ | 125 | IEEE80211_IF_FMT_##format(name, field) \ |
90 | __IEEE80211_IF_FILE(name) | 126 | __IEEE80211_IF_FILE(name, NULL) |
91 | 127 | ||
92 | /* common attributes */ | 128 | /* common attributes */ |
93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 129 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
@@ -99,6 +135,70 @@ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | |||
99 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 135 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
100 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | 136 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); |
101 | 137 | ||
138 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | ||
139 | enum ieee80211_smps_mode smps_mode) | ||
140 | { | ||
141 | struct ieee80211_local *local = sdata->local; | ||
142 | int err; | ||
143 | |||
144 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && | ||
145 | smps_mode == IEEE80211_SMPS_STATIC) | ||
146 | return -EINVAL; | ||
147 | |||
148 | /* auto should be dynamic if in PS mode */ | ||
149 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && | ||
150 | (smps_mode == IEEE80211_SMPS_DYNAMIC || | ||
151 | smps_mode == IEEE80211_SMPS_AUTOMATIC)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | /* supported only on managed interfaces for now */ | ||
155 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
156 | return -EOPNOTSUPP; | ||
157 | |||
158 | mutex_lock(&local->iflist_mtx); | ||
159 | err = __ieee80211_request_smps(sdata, smps_mode); | ||
160 | mutex_unlock(&local->iflist_mtx); | ||
161 | |||
162 | return err; | ||
163 | } | ||
164 | |||
165 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | ||
166 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | ||
167 | [IEEE80211_SMPS_OFF] = "off", | ||
168 | [IEEE80211_SMPS_STATIC] = "static", | ||
169 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | ||
170 | }; | ||
171 | |||
172 | static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, | ||
173 | char *buf, int buflen) | ||
174 | { | ||
175 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
176 | return -EOPNOTSUPP; | ||
177 | |||
178 | return snprintf(buf, buflen, "request: %s\nused: %s\n", | ||
179 | smps_modes[sdata->u.mgd.req_smps], | ||
180 | smps_modes[sdata->u.mgd.ap_smps]); | ||
181 | } | ||
182 | |||
183 | static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | ||
184 | const char *buf, int buflen) | ||
185 | { | ||
186 | enum ieee80211_smps_mode mode; | ||
187 | |||
188 | for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { | ||
189 | if (strncmp(buf, smps_modes[mode], buflen) == 0) { | ||
190 | int err = ieee80211_set_smps(sdata, mode); | ||
191 | if (!err) | ||
192 | return buflen; | ||
193 | return err; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | __IEEE80211_IF_FILE_W(smps); | ||
201 | |||
102 | /* AP attributes */ | 202 | /* AP attributes */ |
103 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 203 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
104 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 204 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
@@ -109,7 +209,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( | |||
109 | return scnprintf(buf, buflen, "%u\n", | 209 | return scnprintf(buf, buflen, "%u\n", |
110 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); | 210 | skb_queue_len(&sdata->u.ap.ps_bc_buf)); |
111 | } | 211 | } |
112 | __IEEE80211_IF_FILE(num_buffered_multicast); | 212 | __IEEE80211_IF_FILE(num_buffered_multicast, NULL); |
113 | 213 | ||
114 | /* WDS attributes */ | 214 | /* WDS attributes */ |
115 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | 215 | IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); |
@@ -158,6 +258,10 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, | |||
158 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ | 258 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ |
159 | sdata, &name##_ops); | 259 | sdata, &name##_ops); |
160 | 260 | ||
261 | #define DEBUGFS_ADD_MODE(name, mode) \ | ||
262 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | ||
263 | sdata, &name##_ops); | ||
264 | |||
161 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 265 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
162 | { | 266 | { |
163 | DEBUGFS_ADD(drop_unencrypted, sta); | 267 | DEBUGFS_ADD(drop_unencrypted, sta); |
@@ -167,6 +271,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
167 | DEBUGFS_ADD(bssid, sta); | 271 | DEBUGFS_ADD(bssid, sta); |
168 | DEBUGFS_ADD(aid, sta); | 272 | DEBUGFS_ADD(aid, sta); |
169 | DEBUGFS_ADD(capab, sta); | 273 | DEBUGFS_ADD(capab, sta); |
274 | DEBUGFS_ADD_MODE(smps, 0600); | ||
170 | } | 275 | } |
171 | 276 | ||
172 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 277 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -280,16 +385,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
280 | } | 385 | } |
281 | } | 386 | } |
282 | 387 | ||
283 | static int notif_registered; | ||
284 | |||
285 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | 388 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) |
286 | { | 389 | { |
287 | char buf[10+IFNAMSIZ]; | 390 | char buf[10+IFNAMSIZ]; |
288 | 391 | ||
289 | if (!notif_registered) | 392 | sprintf(buf, "netdev:%s", sdata->name); |
290 | return; | ||
291 | |||
292 | sprintf(buf, "netdev:%s", sdata->dev->name); | ||
293 | sdata->debugfs.dir = debugfs_create_dir(buf, | 393 | sdata->debugfs.dir = debugfs_create_dir(buf, |
294 | sdata->local->hw.wiphy->debugfsdir); | 394 | sdata->local->hw.wiphy->debugfsdir); |
295 | add_files(sdata); | 395 | add_files(sdata); |
@@ -304,58 +404,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | |||
304 | sdata->debugfs.dir = NULL; | 404 | sdata->debugfs.dir = NULL; |
305 | } | 405 | } |
306 | 406 | ||
307 | static int netdev_notify(struct notifier_block *nb, | 407 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) |
308 | unsigned long state, | ||
309 | void *ndev) | ||
310 | { | 408 | { |
311 | struct net_device *dev = ndev; | ||
312 | struct dentry *dir; | 409 | struct dentry *dir; |
313 | struct ieee80211_sub_if_data *sdata; | 410 | char buf[10 + IFNAMSIZ]; |
314 | char buf[10+IFNAMSIZ]; | ||
315 | |||
316 | if (state != NETDEV_CHANGENAME) | ||
317 | return 0; | ||
318 | |||
319 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
320 | return 0; | ||
321 | |||
322 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
323 | return 0; | ||
324 | |||
325 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
326 | 411 | ||
327 | dir = sdata->debugfs.dir; | 412 | dir = sdata->debugfs.dir; |
328 | 413 | ||
329 | if (!dir) | 414 | if (!dir) |
330 | return 0; | 415 | return; |
331 | 416 | ||
332 | sprintf(buf, "netdev:%s", dev->name); | 417 | sprintf(buf, "netdev:%s", sdata->name); |
333 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 418 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
334 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " | 419 | printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " |
335 | "dir to %s\n", buf); | 420 | "dir to %s\n", buf); |
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct notifier_block mac80211_debugfs_netdev_notifier = { | ||
341 | .notifier_call = netdev_notify, | ||
342 | }; | ||
343 | |||
344 | void ieee80211_debugfs_netdev_init(void) | ||
345 | { | ||
346 | int err; | ||
347 | |||
348 | err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
349 | if (err) { | ||
350 | printk(KERN_ERR | ||
351 | "mac80211: failed to install netdev notifier," | ||
352 | " disabling per-netdev debugfs!\n"); | ||
353 | } else | ||
354 | notif_registered = 1; | ||
355 | } | ||
356 | |||
357 | void ieee80211_debugfs_netdev_exit(void) | ||
358 | { | ||
359 | unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); | ||
360 | notif_registered = 0; | ||
361 | } | 421 | } |
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h index 7af731f0b731..79025e79f4d6 100644 --- a/net/mac80211/debugfs_netdev.h +++ b/net/mac80211/debugfs_netdev.h | |||
@@ -6,8 +6,7 @@ | |||
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_netdev_init(void); | 9 | void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); |
10 | void ieee80211_debugfs_netdev_exit(void); | ||
11 | #else | 10 | #else |
12 | static inline void ieee80211_debugfs_add_netdev( | 11 | static inline void ieee80211_debugfs_add_netdev( |
13 | struct ieee80211_sub_if_data *sdata) | 12 | struct ieee80211_sub_if_data *sdata) |
@@ -15,10 +14,8 @@ static inline void ieee80211_debugfs_add_netdev( | |||
15 | static inline void ieee80211_debugfs_remove_netdev( | 14 | static inline void ieee80211_debugfs_remove_netdev( |
16 | struct ieee80211_sub_if_data *sdata) | 15 | struct ieee80211_sub_if_data *sdata) |
17 | {} | 16 | {} |
18 | static inline void ieee80211_debugfs_netdev_init(void) | 17 | static inline void ieee80211_debugfs_rename_netdev( |
19 | {} | 18 | struct ieee80211_sub_if_data *sdata) |
20 | |||
21 | static inline void ieee80211_debugfs_netdev_exit(void) | ||
22 | {} | 19 | {} |
23 | #endif | 20 | #endif |
24 | 21 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 3f41608c8081..0d4a759ba72c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -44,7 +44,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
44 | STA_OPS(name) | 44 | STA_OPS(name) |
45 | 45 | ||
46 | STA_FILE(aid, sta.aid, D); | 46 | STA_FILE(aid, sta.aid, D); |
47 | STA_FILE(dev, sdata->dev->name, S); | 47 | STA_FILE(dev, sdata->name, S); |
48 | STA_FILE(rx_packets, rx_packets, LU); | 48 | STA_FILE(rx_packets, rx_packets, LU); |
49 | STA_FILE(tx_packets, tx_packets, LU); | 49 | STA_FILE(tx_packets, tx_packets, LU); |
50 | STA_FILE(rx_bytes, rx_bytes, LU); | 50 | STA_FILE(rx_bytes, rx_bytes, LU); |
@@ -160,7 +160,12 @@ STA_OPS(agg_status); | |||
160 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | 160 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, |
161 | size_t count, loff_t *ppos) | 161 | size_t count, loff_t *ppos) |
162 | { | 162 | { |
163 | char buf[200], *p = buf; | 163 | #define PRINT_HT_CAP(_cond, _str) \ |
164 | do { \ | ||
165 | if (_cond) \ | ||
166 | p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ | ||
167 | } while (0) | ||
168 | char buf[1024], *p = buf; | ||
164 | int i; | 169 | int i; |
165 | struct sta_info *sta = file->private_data; | 170 | struct sta_info *sta = file->private_data; |
166 | struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; | 171 | struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; |
@@ -168,15 +173,64 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
168 | p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", | 173 | p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", |
169 | htc->ht_supported ? "" : "not "); | 174 | htc->ht_supported ? "" : "not "); |
170 | if (htc->ht_supported) { | 175 | if (htc->ht_supported) { |
171 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.2x\n", htc->cap); | 176 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); |
177 | |||
178 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP"); | ||
179 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); | ||
180 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); | ||
181 | |||
182 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save"); | ||
183 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save"); | ||
184 | PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled"); | ||
185 | |||
186 | PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield"); | ||
187 | PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI"); | ||
188 | PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI"); | ||
189 | PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC"); | ||
190 | |||
191 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC"); | ||
192 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream"); | ||
193 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams"); | ||
194 | PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams"); | ||
195 | |||
196 | PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); | ||
197 | |||
198 | PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " | ||
199 | "3839 bytes"); | ||
200 | PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " | ||
201 | "7935 bytes"); | ||
202 | |||
203 | /* | ||
204 | * For beacons and probe response this would mean the BSS | ||
205 | * does or does not allow the usage of DSSS/CCK HT40. | ||
206 | * Otherwise it means the STA does or does not use | ||
207 | * DSSS/CCK HT40. | ||
208 | */ | ||
209 | PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40"); | ||
210 | PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40"); | ||
211 | |||
212 | /* BIT(13) is reserved */ | ||
213 | |||
214 | PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant"); | ||
215 | |||
216 | PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection"); | ||
217 | |||
172 | p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", | 218 | p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", |
173 | htc->ampdu_factor, htc->ampdu_density); | 219 | htc->ampdu_factor, htc->ampdu_density); |
174 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); | 220 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); |
221 | |||
175 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | 222 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) |
176 | p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", | 223 | p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", |
177 | htc->mcs.rx_mask[i]); | 224 | htc->mcs.rx_mask[i]); |
178 | p += scnprintf(p, sizeof(buf)+buf-p, "\nMCS rx highest: %d\n", | 225 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); |
179 | le16_to_cpu(htc->mcs.rx_highest)); | 226 | |
227 | /* If not set this is meaningless */ | ||
228 | if (le16_to_cpu(htc->mcs.rx_highest)) { | ||
229 | p += scnprintf(p, sizeof(buf)+buf-p, | ||
230 | "MCS rx highest: %d Mbps\n", | ||
231 | le16_to_cpu(htc->mcs.rx_highest)); | ||
232 | } | ||
233 | |||
180 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", | 234 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", |
181 | htc->mcs.tx_params); | 235 | htc->mcs.tx_params); |
182 | } | 236 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 921dd9c9ff62..727e4cf7b8a6 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -39,7 +39,7 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
39 | struct ieee80211_if_init_conf *conf) | 39 | struct ieee80211_if_init_conf *conf) |
40 | { | 40 | { |
41 | int ret = local->ops->add_interface(&local->hw, conf); | 41 | int ret = local->ops->add_interface(&local->hw, conf); |
42 | trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret); | 42 | trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); |
43 | return ret; | 43 | return ret; |
44 | } | 44 | } |
45 | 45 | ||
@@ -47,7 +47,7 @@ static inline void drv_remove_interface(struct ieee80211_local *local, | |||
47 | struct ieee80211_if_init_conf *conf) | 47 | struct ieee80211_if_init_conf *conf) |
48 | { | 48 | { |
49 | local->ops->remove_interface(&local->hw, conf); | 49 | local->ops->remove_interface(&local->hw, conf); |
50 | trace_drv_remove_interface(local, conf->mac_addr, conf->vif); | 50 | trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); |
51 | } | 51 | } |
52 | 52 | ||
53 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 53 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
@@ -58,13 +58,13 @@ static inline int drv_config(struct ieee80211_local *local, u32 changed) | |||
58 | } | 58 | } |
59 | 59 | ||
60 | static inline void drv_bss_info_changed(struct ieee80211_local *local, | 60 | static inline void drv_bss_info_changed(struct ieee80211_local *local, |
61 | struct ieee80211_vif *vif, | 61 | struct ieee80211_sub_if_data *sdata, |
62 | struct ieee80211_bss_conf *info, | 62 | struct ieee80211_bss_conf *info, |
63 | u32 changed) | 63 | u32 changed) |
64 | { | 64 | { |
65 | if (local->ops->bss_info_changed) | 65 | if (local->ops->bss_info_changed) |
66 | local->ops->bss_info_changed(&local->hw, vif, info, changed); | 66 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); |
67 | trace_drv_bss_info_changed(local, vif, info, changed); | 67 | trace_drv_bss_info_changed(local, sdata, info, changed); |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | 70 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, |
@@ -106,12 +106,13 @@ static inline int drv_set_tim(struct ieee80211_local *local, | |||
106 | } | 106 | } |
107 | 107 | ||
108 | static inline int drv_set_key(struct ieee80211_local *local, | 108 | static inline int drv_set_key(struct ieee80211_local *local, |
109 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | 109 | enum set_key_cmd cmd, |
110 | struct ieee80211_sub_if_data *sdata, | ||
110 | struct ieee80211_sta *sta, | 111 | struct ieee80211_sta *sta, |
111 | struct ieee80211_key_conf *key) | 112 | struct ieee80211_key_conf *key) |
112 | { | 113 | { |
113 | int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); | 114 | int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); |
114 | trace_drv_set_key(local, cmd, vif, sta, key, ret); | 115 | trace_drv_set_key(local, cmd, sdata, sta, key, ret); |
115 | return ret; | 116 | return ret; |
116 | } | 117 | } |
117 | 118 | ||
@@ -179,13 +180,13 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, | |||
179 | } | 180 | } |
180 | 181 | ||
181 | static inline void drv_sta_notify(struct ieee80211_local *local, | 182 | static inline void drv_sta_notify(struct ieee80211_local *local, |
182 | struct ieee80211_vif *vif, | 183 | struct ieee80211_sub_if_data *sdata, |
183 | enum sta_notify_cmd cmd, | 184 | enum sta_notify_cmd cmd, |
184 | struct ieee80211_sta *sta) | 185 | struct ieee80211_sta *sta) |
185 | { | 186 | { |
186 | if (local->ops->sta_notify) | 187 | if (local->ops->sta_notify) |
187 | local->ops->sta_notify(&local->hw, vif, cmd, sta); | 188 | local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); |
188 | trace_drv_sta_notify(local, vif, cmd, sta); | 189 | trace_drv_sta_notify(local, sdata, cmd, sta); |
189 | } | 190 | } |
190 | 191 | ||
191 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | 192 | static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, |
@@ -239,16 +240,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) | |||
239 | } | 240 | } |
240 | 241 | ||
241 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 242 | static inline int drv_ampdu_action(struct ieee80211_local *local, |
242 | struct ieee80211_vif *vif, | 243 | struct ieee80211_sub_if_data *sdata, |
243 | enum ieee80211_ampdu_mlme_action action, | 244 | enum ieee80211_ampdu_mlme_action action, |
244 | struct ieee80211_sta *sta, u16 tid, | 245 | struct ieee80211_sta *sta, u16 tid, |
245 | u16 *ssn) | 246 | u16 *ssn) |
246 | { | 247 | { |
247 | int ret = -EOPNOTSUPP; | 248 | int ret = -EOPNOTSUPP; |
248 | if (local->ops->ampdu_action) | 249 | if (local->ops->ampdu_action) |
249 | ret = local->ops->ampdu_action(&local->hw, vif, action, | 250 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, |
250 | sta, tid, ssn); | 251 | sta, tid, ssn); |
251 | trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret); | 252 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); |
252 | return ret; | 253 | return ret; |
253 | } | 254 | } |
254 | 255 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index ee94ea0c67e9..7a849b920165 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -25,10 +25,12 @@ static inline void trace_ ## name(proto) {} | |||
25 | #define STA_PR_FMT " sta:%pM" | 25 | #define STA_PR_FMT " sta:%pM" |
26 | #define STA_PR_ARG __entry->sta_addr | 26 | #define STA_PR_ARG __entry->sta_addr |
27 | 27 | ||
28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) | 28 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ |
29 | #define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif | 29 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
30 | #define VIF_PR_FMT " vif:%p(%d)" | 30 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
31 | #define VIF_PR_ARG __entry->vif, __entry->vif_type | 31 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
32 | #define VIF_PR_FMT " vif:%s(%d)" | ||
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | ||
32 | 34 | ||
33 | TRACE_EVENT(drv_start, | 35 | TRACE_EVENT(drv_start, |
34 | TP_PROTO(struct ieee80211_local *local, int ret), | 36 | TP_PROTO(struct ieee80211_local *local, int ret), |
@@ -70,11 +72,10 @@ TRACE_EVENT(drv_stop, | |||
70 | 72 | ||
71 | TRACE_EVENT(drv_add_interface, | 73 | TRACE_EVENT(drv_add_interface, |
72 | TP_PROTO(struct ieee80211_local *local, | 74 | TP_PROTO(struct ieee80211_local *local, |
73 | const u8 *addr, | 75 | struct ieee80211_sub_if_data *sdata, |
74 | struct ieee80211_vif *vif, | ||
75 | int ret), | 76 | int ret), |
76 | 77 | ||
77 | TP_ARGS(local, addr, vif, ret), | 78 | TP_ARGS(local, sdata, ret), |
78 | 79 | ||
79 | TP_STRUCT__entry( | 80 | TP_STRUCT__entry( |
80 | LOCAL_ENTRY | 81 | LOCAL_ENTRY |
@@ -86,7 +87,7 @@ TRACE_EVENT(drv_add_interface, | |||
86 | TP_fast_assign( | 87 | TP_fast_assign( |
87 | LOCAL_ASSIGN; | 88 | LOCAL_ASSIGN; |
88 | VIF_ASSIGN; | 89 | VIF_ASSIGN; |
89 | memcpy(__entry->addr, addr, 6); | 90 | memcpy(__entry->addr, sdata->vif.addr, 6); |
90 | __entry->ret = ret; | 91 | __entry->ret = ret; |
91 | ), | 92 | ), |
92 | 93 | ||
@@ -97,10 +98,9 @@ TRACE_EVENT(drv_add_interface, | |||
97 | ); | 98 | ); |
98 | 99 | ||
99 | TRACE_EVENT(drv_remove_interface, | 100 | TRACE_EVENT(drv_remove_interface, |
100 | TP_PROTO(struct ieee80211_local *local, | 101 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), |
101 | const u8 *addr, struct ieee80211_vif *vif), | ||
102 | 102 | ||
103 | TP_ARGS(local, addr, vif), | 103 | TP_ARGS(local, sdata), |
104 | 104 | ||
105 | TP_STRUCT__entry( | 105 | TP_STRUCT__entry( |
106 | LOCAL_ENTRY | 106 | LOCAL_ENTRY |
@@ -111,7 +111,7 @@ TRACE_EVENT(drv_remove_interface, | |||
111 | TP_fast_assign( | 111 | TP_fast_assign( |
112 | LOCAL_ASSIGN; | 112 | LOCAL_ASSIGN; |
113 | VIF_ASSIGN; | 113 | VIF_ASSIGN; |
114 | memcpy(__entry->addr, addr, 6); | 114 | memcpy(__entry->addr, sdata->vif.addr, 6); |
115 | ), | 115 | ), |
116 | 116 | ||
117 | TP_printk( | 117 | TP_printk( |
@@ -140,6 +140,7 @@ TRACE_EVENT(drv_config, | |||
140 | __field(u8, short_frame_max_tx_count) | 140 | __field(u8, short_frame_max_tx_count) |
141 | __field(int, center_freq) | 141 | __field(int, center_freq) |
142 | __field(int, channel_type) | 142 | __field(int, channel_type) |
143 | __field(int, smps) | ||
143 | ), | 144 | ), |
144 | 145 | ||
145 | TP_fast_assign( | 146 | TP_fast_assign( |
@@ -155,6 +156,7 @@ TRACE_EVENT(drv_config, | |||
155 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; | 156 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; |
156 | __entry->center_freq = local->hw.conf.channel->center_freq; | 157 | __entry->center_freq = local->hw.conf.channel->center_freq; |
157 | __entry->channel_type = local->hw.conf.channel_type; | 158 | __entry->channel_type = local->hw.conf.channel_type; |
159 | __entry->smps = local->hw.conf.smps_mode; | ||
158 | ), | 160 | ), |
159 | 161 | ||
160 | TP_printk( | 162 | TP_printk( |
@@ -165,11 +167,11 @@ TRACE_EVENT(drv_config, | |||
165 | 167 | ||
166 | TRACE_EVENT(drv_bss_info_changed, | 168 | TRACE_EVENT(drv_bss_info_changed, |
167 | TP_PROTO(struct ieee80211_local *local, | 169 | TP_PROTO(struct ieee80211_local *local, |
168 | struct ieee80211_vif *vif, | 170 | struct ieee80211_sub_if_data *sdata, |
169 | struct ieee80211_bss_conf *info, | 171 | struct ieee80211_bss_conf *info, |
170 | u32 changed), | 172 | u32 changed), |
171 | 173 | ||
172 | TP_ARGS(local, vif, info, changed), | 174 | TP_ARGS(local, sdata, info, changed), |
173 | 175 | ||
174 | TP_STRUCT__entry( | 176 | TP_STRUCT__entry( |
175 | LOCAL_ENTRY | 177 | LOCAL_ENTRY |
@@ -293,11 +295,11 @@ TRACE_EVENT(drv_set_tim, | |||
293 | 295 | ||
294 | TRACE_EVENT(drv_set_key, | 296 | TRACE_EVENT(drv_set_key, |
295 | TP_PROTO(struct ieee80211_local *local, | 297 | TP_PROTO(struct ieee80211_local *local, |
296 | enum set_key_cmd cmd, struct ieee80211_vif *vif, | 298 | enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, |
297 | struct ieee80211_sta *sta, | 299 | struct ieee80211_sta *sta, |
298 | struct ieee80211_key_conf *key, int ret), | 300 | struct ieee80211_key_conf *key, int ret), |
299 | 301 | ||
300 | TP_ARGS(local, cmd, vif, sta, key, ret), | 302 | TP_ARGS(local, cmd, sdata, sta, key, ret), |
301 | 303 | ||
302 | TP_STRUCT__entry( | 304 | TP_STRUCT__entry( |
303 | LOCAL_ENTRY | 305 | LOCAL_ENTRY |
@@ -491,11 +493,11 @@ TRACE_EVENT(drv_set_rts_threshold, | |||
491 | 493 | ||
492 | TRACE_EVENT(drv_sta_notify, | 494 | TRACE_EVENT(drv_sta_notify, |
493 | TP_PROTO(struct ieee80211_local *local, | 495 | TP_PROTO(struct ieee80211_local *local, |
494 | struct ieee80211_vif *vif, | 496 | struct ieee80211_sub_if_data *sdata, |
495 | enum sta_notify_cmd cmd, | 497 | enum sta_notify_cmd cmd, |
496 | struct ieee80211_sta *sta), | 498 | struct ieee80211_sta *sta), |
497 | 499 | ||
498 | TP_ARGS(local, vif, cmd, sta), | 500 | TP_ARGS(local, sdata, cmd, sta), |
499 | 501 | ||
500 | TP_STRUCT__entry( | 502 | TP_STRUCT__entry( |
501 | LOCAL_ENTRY | 503 | LOCAL_ENTRY |
@@ -656,12 +658,12 @@ TRACE_EVENT(drv_tx_last_beacon, | |||
656 | 658 | ||
657 | TRACE_EVENT(drv_ampdu_action, | 659 | TRACE_EVENT(drv_ampdu_action, |
658 | TP_PROTO(struct ieee80211_local *local, | 660 | TP_PROTO(struct ieee80211_local *local, |
659 | struct ieee80211_vif *vif, | 661 | struct ieee80211_sub_if_data *sdata, |
660 | enum ieee80211_ampdu_mlme_action action, | 662 | enum ieee80211_ampdu_mlme_action action, |
661 | struct ieee80211_sta *sta, u16 tid, | 663 | struct ieee80211_sta *sta, u16 tid, |
662 | u16 *ssn, int ret), | 664 | u16 *ssn, int ret), |
663 | 665 | ||
664 | TP_ARGS(local, vif, action, sta, tid, ssn, ret), | 666 | TP_ARGS(local, sdata, action, sta, tid, ssn, ret), |
665 | 667 | ||
666 | TP_STRUCT__entry( | 668 | TP_STRUCT__entry( |
667 | LOCAL_ENTRY | 669 | LOCAL_ENTRY |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index d7dcee680728..bb677a73b7c9 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -125,7 +125,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
125 | 125 | ||
126 | if (!skb) { | 126 | if (!skb) { |
127 | printk(KERN_ERR "%s: failed to allocate buffer " | 127 | printk(KERN_ERR "%s: failed to allocate buffer " |
128 | "for delba frame\n", sdata->dev->name); | 128 | "for delba frame\n", sdata->name); |
129 | return; | 129 | return; |
130 | } | 130 | } |
131 | 131 | ||
@@ -133,10 +133,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
133 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 133 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
134 | memset(mgmt, 0, 24); | 134 | memset(mgmt, 0, 24); |
135 | memcpy(mgmt->da, da, ETH_ALEN); | 135 | memcpy(mgmt->da, da, ETH_ALEN); |
136 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 136 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
137 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 137 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
138 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 138 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
139 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 139 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
140 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | 140 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
141 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 141 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
142 | 142 | ||
@@ -185,3 +185,50 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
185 | spin_unlock_bh(&sta->lock); | 185 | spin_unlock_bh(&sta->lock); |
186 | } | 186 | } |
187 | } | 187 | } |
188 | |||
189 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | ||
190 | enum ieee80211_smps_mode smps, const u8 *da, | ||
191 | const u8 *bssid) | ||
192 | { | ||
193 | struct ieee80211_local *local = sdata->local; | ||
194 | struct sk_buff *skb; | ||
195 | struct ieee80211_mgmt *action_frame; | ||
196 | |||
197 | /* 27 = header + category + action + smps mode */ | ||
198 | skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom); | ||
199 | if (!skb) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
203 | action_frame = (void *)skb_put(skb, 27); | ||
204 | memcpy(action_frame->da, da, ETH_ALEN); | ||
205 | memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
206 | memcpy(action_frame->bssid, bssid, ETH_ALEN); | ||
207 | action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
208 | IEEE80211_STYPE_ACTION); | ||
209 | action_frame->u.action.category = WLAN_CATEGORY_HT; | ||
210 | action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; | ||
211 | switch (smps) { | ||
212 | case IEEE80211_SMPS_AUTOMATIC: | ||
213 | case IEEE80211_SMPS_NUM_MODES: | ||
214 | WARN_ON(1); | ||
215 | case IEEE80211_SMPS_OFF: | ||
216 | action_frame->u.action.u.ht_smps.smps_control = | ||
217 | WLAN_HT_SMPS_CONTROL_DISABLED; | ||
218 | break; | ||
219 | case IEEE80211_SMPS_STATIC: | ||
220 | action_frame->u.action.u.ht_smps.smps_control = | ||
221 | WLAN_HT_SMPS_CONTROL_STATIC; | ||
222 | break; | ||
223 | case IEEE80211_SMPS_DYNAMIC: | ||
224 | action_frame->u.action.u.ht_smps.smps_control = | ||
225 | WLAN_HT_SMPS_CONTROL_DYNAMIC; | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | /* we'll do more on status of this frame */ | ||
230 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
231 | ieee80211_tx_skb(sdata, skb); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 10d13856f86c..ef6c6b2401d1 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -117,7 +117,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
117 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 117 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
118 | IEEE80211_STYPE_PROBE_RESP); | 118 | IEEE80211_STYPE_PROBE_RESP); |
119 | memset(mgmt->da, 0xff, ETH_ALEN); | 119 | memset(mgmt->da, 0xff, ETH_ALEN); |
120 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 120 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
121 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | 121 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
122 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); | 122 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); |
123 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); | 123 | mgmt->u.beacon.timestamp = cpu_to_le64(tsf); |
@@ -252,7 +252,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
252 | 252 | ||
253 | rcu_read_lock(); | 253 | rcu_read_lock(); |
254 | 254 | ||
255 | sta = sta_info_get(local, mgmt->sa); | 255 | sta = sta_info_get(sdata, mgmt->sa); |
256 | if (sta) { | 256 | if (sta) { |
257 | u32 prev_rates; | 257 | u32 prev_rates; |
258 | 258 | ||
@@ -266,7 +266,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
266 | printk(KERN_DEBUG "%s: updated supp_rates set " | 266 | printk(KERN_DEBUG "%s: updated supp_rates set " |
267 | "for %pM based on beacon info (0x%llx | " | 267 | "for %pM based on beacon info (0x%llx | " |
268 | "0x%llx -> 0x%llx)\n", | 268 | "0x%llx -> 0x%llx)\n", |
269 | sdata->dev->name, | 269 | sdata->name, |
270 | sta->sta.addr, | 270 | sta->sta.addr, |
271 | (unsigned long long) prev_rates, | 271 | (unsigned long long) prev_rates, |
272 | (unsigned long long) supp_rates, | 272 | (unsigned long long) supp_rates, |
@@ -364,7 +364,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
364 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 364 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
365 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 365 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
366 | "local TSF - IBSS merge with BSSID %pM\n", | 366 | "local TSF - IBSS merge with BSSID %pM\n", |
367 | sdata->dev->name, mgmt->bssid); | 367 | sdata->name, mgmt->bssid); |
368 | #endif | 368 | #endif |
369 | ieee80211_sta_join_ibss(sdata, bss); | 369 | ieee80211_sta_join_ibss(sdata, bss); |
370 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); | 370 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); |
@@ -393,7 +393,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
393 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | 393 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { |
394 | if (net_ratelimit()) | 394 | if (net_ratelimit()) |
395 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", | 395 | printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", |
396 | sdata->dev->name, addr); | 396 | sdata->name, addr); |
397 | return NULL; | 397 | return NULL; |
398 | } | 398 | } |
399 | 399 | ||
@@ -402,7 +402,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
402 | 402 | ||
403 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 403 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
404 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", | 404 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", |
405 | wiphy_name(local->hw.wiphy), addr, sdata->dev->name); | 405 | wiphy_name(local->hw.wiphy), addr, sdata->name); |
406 | #endif | 406 | #endif |
407 | 407 | ||
408 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 408 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
@@ -466,7 +466,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
466 | return; | 466 | return; |
467 | 467 | ||
468 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 468 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
469 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); | 469 | "IBSS networks with same SSID (merge)\n", sdata->name); |
470 | 470 | ||
471 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); | 471 | ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); |
472 | } | 472 | } |
@@ -488,13 +488,13 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
488 | * random number generator get different BSSID. */ | 488 | * random number generator get different BSSID. */ |
489 | get_random_bytes(bssid, ETH_ALEN); | 489 | get_random_bytes(bssid, ETH_ALEN); |
490 | for (i = 0; i < ETH_ALEN; i++) | 490 | for (i = 0; i < ETH_ALEN; i++) |
491 | bssid[i] ^= sdata->dev->dev_addr[i]; | 491 | bssid[i] ^= sdata->vif.addr[i]; |
492 | bssid[0] &= ~0x01; | 492 | bssid[0] &= ~0x01; |
493 | bssid[0] |= 0x02; | 493 | bssid[0] |= 0x02; |
494 | } | 494 | } |
495 | 495 | ||
496 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 496 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", |
497 | sdata->dev->name, bssid); | 497 | sdata->name, bssid); |
498 | 498 | ||
499 | sband = local->hw.wiphy->bands[ifibss->channel->band]; | 499 | sband = local->hw.wiphy->bands[ifibss->channel->band]; |
500 | 500 | ||
@@ -523,7 +523,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
523 | active_ibss = ieee80211_sta_active_ibss(sdata); | 523 | active_ibss = ieee80211_sta_active_ibss(sdata); |
524 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 524 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
525 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 525 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
526 | sdata->dev->name, active_ibss); | 526 | sdata->name, active_ibss); |
527 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 527 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
528 | 528 | ||
529 | if (active_ibss) | 529 | if (active_ibss) |
@@ -552,7 +552,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
552 | 552 | ||
553 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | 553 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" |
554 | " based on configured SSID\n", | 554 | " based on configured SSID\n", |
555 | sdata->dev->name, bss->cbss.bssid); | 555 | sdata->name, bss->cbss.bssid); |
556 | 556 | ||
557 | ieee80211_sta_join_ibss(sdata, bss); | 557 | ieee80211_sta_join_ibss(sdata, bss); |
558 | ieee80211_rx_bss_put(local, bss); | 558 | ieee80211_rx_bss_put(local, bss); |
@@ -571,7 +571,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
571 | } else if (time_after(jiffies, ifibss->last_scan_completed + | 571 | } else if (time_after(jiffies, ifibss->last_scan_completed + |
572 | IEEE80211_SCAN_INTERVAL)) { | 572 | IEEE80211_SCAN_INTERVAL)) { |
573 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 573 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
574 | "join\n", sdata->dev->name); | 574 | "join\n", sdata->name); |
575 | 575 | ||
576 | ieee80211_request_internal_scan(sdata, ifibss->ssid, | 576 | ieee80211_request_internal_scan(sdata, ifibss->ssid, |
577 | ifibss->ssid_len); | 577 | ifibss->ssid_len); |
@@ -585,7 +585,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
585 | return; | 585 | return; |
586 | } | 586 | } |
587 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 587 | printk(KERN_DEBUG "%s: IBSS not allowed on" |
588 | " %d MHz\n", sdata->dev->name, | 588 | " %d MHz\n", sdata->name, |
589 | local->hw.conf.channel->center_freq); | 589 | local->hw.conf.channel->center_freq); |
590 | 590 | ||
591 | /* No IBSS found - decrease scan interval and continue | 591 | /* No IBSS found - decrease scan interval and continue |
@@ -619,7 +619,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
619 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 619 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
620 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" | 620 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" |
621 | " (tx_last_beacon=%d)\n", | 621 | " (tx_last_beacon=%d)\n", |
622 | sdata->dev->name, mgmt->sa, mgmt->da, | 622 | sdata->name, mgmt->sa, mgmt->da, |
623 | mgmt->bssid, tx_last_beacon); | 623 | mgmt->bssid, tx_last_beacon); |
624 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 624 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
625 | 625 | ||
@@ -637,7 +637,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
637 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 637 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
638 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 638 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " |
639 | "from %pM\n", | 639 | "from %pM\n", |
640 | sdata->dev->name, mgmt->sa); | 640 | sdata->name, mgmt->sa); |
641 | #endif | 641 | #endif |
642 | return; | 642 | return; |
643 | } | 643 | } |
@@ -657,7 +657,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
657 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 657 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
658 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 658 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
659 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", | 659 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", |
660 | sdata->dev->name, resp->da); | 660 | sdata->name, resp->da); |
661 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 661 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
662 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 662 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
663 | ieee80211_tx_skb(sdata, skb); | 663 | ieee80211_tx_skb(sdata, skb); |
@@ -671,7 +671,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
671 | size_t baselen; | 671 | size_t baselen; |
672 | struct ieee802_11_elems elems; | 672 | struct ieee802_11_elems elems; |
673 | 673 | ||
674 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 674 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
675 | return; /* ignore ProbeResp to foreign address */ | 675 | return; /* ignore ProbeResp to foreign address */ |
676 | 676 | ||
677 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 677 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 91dc8636d644..88b0ba6c7484 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -140,7 +140,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; | |||
140 | 140 | ||
141 | struct ieee80211_tx_data { | 141 | struct ieee80211_tx_data { |
142 | struct sk_buff *skb; | 142 | struct sk_buff *skb; |
143 | struct net_device *dev; | ||
144 | struct ieee80211_local *local; | 143 | struct ieee80211_local *local; |
145 | struct ieee80211_sub_if_data *sdata; | 144 | struct ieee80211_sub_if_data *sdata; |
146 | struct sta_info *sta; | 145 | struct sta_info *sta; |
@@ -298,6 +297,8 @@ struct ieee80211_if_managed { | |||
298 | 297 | ||
299 | unsigned long timers_running; /* used for quiesce/restart */ | 298 | unsigned long timers_running; /* used for quiesce/restart */ |
300 | bool powersave; /* powersave requested for this iface */ | 299 | bool powersave; /* powersave requested for this iface */ |
300 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | ||
301 | ap_smps; /* smps mode AP thinks we're in */ | ||
301 | 302 | ||
302 | unsigned long request; | 303 | unsigned long request; |
303 | 304 | ||
@@ -433,6 +434,8 @@ struct ieee80211_sub_if_data { | |||
433 | 434 | ||
434 | int drop_unencrypted; | 435 | int drop_unencrypted; |
435 | 436 | ||
437 | char name[IFNAMSIZ]; | ||
438 | |||
436 | /* | 439 | /* |
437 | * keep track of whether the HT opmode (stored in | 440 | * keep track of whether the HT opmode (stored in |
438 | * vif.bss_info.ht_operation_mode) is valid. | 441 | * vif.bss_info.ht_operation_mode) is valid. |
@@ -586,6 +589,9 @@ struct ieee80211_local { | |||
586 | /* used for uploading changed mc list */ | 589 | /* used for uploading changed mc list */ |
587 | struct work_struct reconfig_filter; | 590 | struct work_struct reconfig_filter; |
588 | 591 | ||
592 | /* used to reconfigure hardware SM PS */ | ||
593 | struct work_struct recalc_smps; | ||
594 | |||
589 | /* aggregated multicast list */ | 595 | /* aggregated multicast list */ |
590 | struct dev_addr_list *mc_list; | 596 | struct dev_addr_list *mc_list; |
591 | int mc_count; | 597 | int mc_count; |
@@ -760,6 +766,8 @@ struct ieee80211_local { | |||
760 | int user_power_level; /* in dBm */ | 766 | int user_power_level; /* in dBm */ |
761 | int power_constr_level; /* in dBm */ | 767 | int power_constr_level; /* in dBm */ |
762 | 768 | ||
769 | enum ieee80211_smps_mode smps_mode; | ||
770 | |||
763 | struct work_struct restart_work; | 771 | struct work_struct restart_work; |
764 | 772 | ||
765 | #ifdef CONFIG_MAC80211_DEBUGFS | 773 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -874,6 +882,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
874 | void ieee80211_configure_filter(struct ieee80211_local *local); | 882 | void ieee80211_configure_filter(struct ieee80211_local *local); |
875 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); | 883 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
876 | 884 | ||
885 | extern bool ieee80211_disable_40mhz_24ghz; | ||
886 | |||
877 | /* STA code */ | 887 | /* STA code */ |
878 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); | 888 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
879 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 889 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
@@ -938,6 +948,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, | |||
938 | struct ieee80211_bss *bss); | 948 | struct ieee80211_bss *bss); |
939 | 949 | ||
940 | /* interface handling */ | 950 | /* interface handling */ |
951 | int ieee80211_iface_init(void); | ||
952 | void ieee80211_iface_exit(void); | ||
941 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 953 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
942 | struct net_device **new_dev, enum nl80211_iftype type, | 954 | struct net_device **new_dev, enum nl80211_iftype type, |
943 | struct vif_params *params); | 955 | struct vif_params *params); |
@@ -976,6 +988,9 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
976 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | 988 | void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, |
977 | const u8 *da, u16 tid, | 989 | const u8 *da, u16 tid, |
978 | u16 initiator, u16 reason_code); | 990 | u16 initiator, u16 reason_code); |
991 | int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | ||
992 | enum ieee80211_smps_mode smps, const u8 *da, | ||
993 | const u8 *bssid); | ||
979 | 994 | ||
980 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 995 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, |
981 | u16 tid, u16 initiator, u16 reason); | 996 | u16 tid, u16 initiator, u16 reason); |
@@ -1086,6 +1101,10 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
1086 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1101 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
1087 | struct ieee802_11_elems *elems, | 1102 | struct ieee802_11_elems *elems, |
1088 | enum ieee80211_band band); | 1103 | enum ieee80211_band band); |
1104 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | ||
1105 | enum ieee80211_smps_mode smps_mode); | ||
1106 | void ieee80211_recalc_smps(struct ieee80211_local *local, | ||
1107 | struct ieee80211_sub_if_data *forsdata); | ||
1089 | 1108 | ||
1090 | #ifdef CONFIG_MAC80211_NOINLINE | 1109 | #ifdef CONFIG_MAC80211_NOINLINE |
1091 | #define debug_noinline noinline | 1110 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 80c16f6e2af6..a6e6da3cab70 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -60,6 +60,22 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | static int ieee80211_change_mac(struct net_device *dev, void *addr) | ||
64 | { | ||
65 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
66 | int ret; | ||
67 | |||
68 | if (netif_running(dev)) | ||
69 | return -EBUSY; | ||
70 | |||
71 | ret = eth_mac_addr(dev, addr); | ||
72 | |||
73 | if (ret == 0) | ||
74 | memcpy(sdata->vif.addr, addr, ETH_ALEN); | ||
75 | |||
76 | return ret; | ||
77 | } | ||
78 | |||
63 | static inline int identical_mac_addr_allowed(int type1, int type2) | 79 | static inline int identical_mac_addr_allowed(int type1, int type2) |
64 | { | 80 | { |
65 | return type1 == NL80211_IFTYPE_MONITOR || | 81 | return type1 == NL80211_IFTYPE_MONITOR || |
@@ -234,7 +250,7 @@ static int ieee80211_open(struct net_device *dev) | |||
234 | default: | 250 | default: |
235 | conf.vif = &sdata->vif; | 251 | conf.vif = &sdata->vif; |
236 | conf.type = sdata->vif.type; | 252 | conf.type = sdata->vif.type; |
237 | conf.mac_addr = dev->dev_addr; | 253 | conf.mac_addr = sdata->vif.addr; |
238 | res = drv_add_interface(local, &conf); | 254 | res = drv_add_interface(local, &conf); |
239 | if (res) | 255 | if (res) |
240 | goto err_stop; | 256 | goto err_stop; |
@@ -514,7 +530,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
514 | 530 | ||
515 | conf.vif = &sdata->vif; | 531 | conf.vif = &sdata->vif; |
516 | conf.type = sdata->vif.type; | 532 | conf.type = sdata->vif.type; |
517 | conf.mac_addr = dev->dev_addr; | 533 | conf.mac_addr = sdata->vif.addr; |
518 | /* disable all keys for as long as this netdev is down */ | 534 | /* disable all keys for as long as this netdev is down */ |
519 | ieee80211_disable_keys(sdata); | 535 | ieee80211_disable_keys(sdata); |
520 | drv_remove_interface(local, &conf); | 536 | drv_remove_interface(local, &conf); |
@@ -651,7 +667,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { | |||
651 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 667 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
652 | .ndo_set_multicast_list = ieee80211_set_multicast_list, | 668 | .ndo_set_multicast_list = ieee80211_set_multicast_list, |
653 | .ndo_change_mtu = ieee80211_change_mtu, | 669 | .ndo_change_mtu = ieee80211_change_mtu, |
654 | .ndo_set_mac_address = eth_mac_addr, | 670 | .ndo_set_mac_address = ieee80211_change_mac, |
655 | }; | 671 | }; |
656 | 672 | ||
657 | static const struct net_device_ops ieee80211_monitorif_ops = { | 673 | static const struct net_device_ops ieee80211_monitorif_ops = { |
@@ -794,6 +810,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
794 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 810 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
795 | sdata = netdev_priv(ndev); | 811 | sdata = netdev_priv(ndev); |
796 | ndev->ieee80211_ptr = &sdata->wdev; | 812 | ndev->ieee80211_ptr = &sdata->wdev; |
813 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
814 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
797 | 815 | ||
798 | /* initialise type-independent data */ | 816 | /* initialise type-independent data */ |
799 | sdata->wdev.wiphy = local->hw.wiphy; | 817 | sdata->wdev.wiphy = local->hw.wiphy; |
@@ -945,3 +963,41 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
945 | if (chg) | 963 | if (chg) |
946 | ieee80211_hw_config(local, chg); | 964 | ieee80211_hw_config(local, chg); |
947 | } | 965 | } |
966 | |||
967 | static int netdev_notify(struct notifier_block *nb, | ||
968 | unsigned long state, | ||
969 | void *ndev) | ||
970 | { | ||
971 | struct net_device *dev = ndev; | ||
972 | struct ieee80211_sub_if_data *sdata; | ||
973 | |||
974 | if (state != NETDEV_CHANGENAME) | ||
975 | return 0; | ||
976 | |||
977 | if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) | ||
978 | return 0; | ||
979 | |||
980 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | ||
981 | return 0; | ||
982 | |||
983 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
984 | |||
985 | memcpy(sdata->name, sdata->name, IFNAMSIZ); | ||
986 | |||
987 | ieee80211_debugfs_rename_netdev(sdata); | ||
988 | return 0; | ||
989 | } | ||
990 | |||
991 | static struct notifier_block mac80211_netdev_notifier = { | ||
992 | .notifier_call = netdev_notify, | ||
993 | }; | ||
994 | |||
995 | int ieee80211_iface_init(void) | ||
996 | { | ||
997 | return register_netdevice_notifier(&mac80211_netdev_notifier); | ||
998 | } | ||
999 | |||
1000 | void ieee80211_iface_exit(void) | ||
1001 | { | ||
1002 | unregister_netdevice_notifier(&mac80211_netdev_notifier); | ||
1003 | } | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 659a42d529e3..32ee6d0ee34d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -139,7 +139,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
139 | struct ieee80211_sub_if_data, | 139 | struct ieee80211_sub_if_data, |
140 | u.ap); | 140 | u.ap); |
141 | 141 | ||
142 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); | 142 | ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); |
143 | 143 | ||
144 | if (!ret) { | 144 | if (!ret) { |
145 | spin_lock_bh(&todo_lock); | 145 | spin_lock_bh(&todo_lock); |
@@ -181,7 +181,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
181 | struct ieee80211_sub_if_data, | 181 | struct ieee80211_sub_if_data, |
182 | u.ap); | 182 | u.ap); |
183 | 183 | ||
184 | ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, | 184 | ret = drv_set_key(key->local, DISABLE_KEY, sdata, |
185 | sta, &key->conf); | 185 | sta, &key->conf); |
186 | 186 | ||
187 | if (ret) | 187 | if (ret) |
@@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
421 | */ | 421 | */ |
422 | 422 | ||
423 | /* same here, the AP could be using QoS */ | 423 | /* same here, the AP could be using QoS */ |
424 | ap = sta_info_get(key->local, key->sdata->u.mgd.bssid); | 424 | ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); |
425 | if (ap) { | 425 | if (ap) { |
426 | if (test_sta_flags(ap, WLAN_STA_WME)) | 426 | if (test_sta_flags(ap, WLAN_STA_WME)) |
427 | key->conf.flags |= | 427 | key->conf.flags |= |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index a49f93b79e92..bdc2968c2bbe 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -59,11 +59,17 @@ enum ieee80211_internal_key_flags { | |||
59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), | 59 | KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), |
60 | }; | 60 | }; |
61 | 61 | ||
62 | enum ieee80211_internal_tkip_state { | ||
63 | TKIP_STATE_NOT_INIT, | ||
64 | TKIP_STATE_PHASE1_DONE, | ||
65 | TKIP_STATE_PHASE1_HW_UPLOADED, | ||
66 | }; | ||
67 | |||
62 | struct tkip_ctx { | 68 | struct tkip_ctx { |
63 | u32 iv32; | 69 | u32 iv32; |
64 | u16 iv16; | 70 | u16 iv16; |
65 | u16 p1k[5]; | 71 | u16 p1k[5]; |
66 | int initialized; | 72 | enum ieee80211_internal_tkip_state state; |
67 | }; | 73 | }; |
68 | 74 | ||
69 | struct ieee80211_key { | 75 | struct ieee80211_key { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0d2d94881f1f..d4426748ab10 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -32,7 +32,12 @@ | |||
32 | #include "led.h" | 32 | #include "led.h" |
33 | #include "cfg.h" | 33 | #include "cfg.h" |
34 | #include "debugfs.h" | 34 | #include "debugfs.h" |
35 | #include "debugfs_netdev.h" | 35 | |
36 | |||
37 | bool ieee80211_disable_40mhz_24ghz; | ||
38 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); | ||
39 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, | ||
40 | "Disable 40MHz support in the 2.4GHz band"); | ||
36 | 41 | ||
37 | void ieee80211_configure_filter(struct ieee80211_local *local) | 42 | void ieee80211_configure_filter(struct ieee80211_local *local) |
38 | { | 43 | { |
@@ -114,6 +119,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
114 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 119 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
115 | } | 120 | } |
116 | 121 | ||
122 | if (!conf_is_ht(&local->hw.conf)) { | ||
123 | /* | ||
124 | * mac80211.h documents that this is only valid | ||
125 | * when the channel is set to an HT type, and | ||
126 | * that otherwise STATIC is used. | ||
127 | */ | ||
128 | local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC; | ||
129 | } else if (local->hw.conf.smps_mode != local->smps_mode) { | ||
130 | local->hw.conf.smps_mode = local->smps_mode; | ||
131 | changed |= IEEE80211_CONF_CHANGE_SMPS; | ||
132 | } | ||
133 | |||
117 | if (scan_chan) | 134 | if (scan_chan) |
118 | power = chan->max_power; | 135 | power = chan->max_power; |
119 | else | 136 | else |
@@ -173,7 +190,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
173 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 190 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
174 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 191 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
175 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 192 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
176 | sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; | 193 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
177 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 194 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
178 | sdata->vif.bss_conf.bssid = zero; | 195 | sdata->vif.bss_conf.bssid = zero; |
179 | } else { | 196 | } else { |
@@ -223,8 +240,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
223 | } | 240 | } |
224 | } | 241 | } |
225 | 242 | ||
226 | drv_bss_info_changed(local, &sdata->vif, | 243 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
227 | &sdata->vif.bss_conf, changed); | ||
228 | } | 244 | } |
229 | 245 | ||
230 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | 246 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
@@ -299,6 +315,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
299 | } | 315 | } |
300 | EXPORT_SYMBOL(ieee80211_restart_hw); | 316 | EXPORT_SYMBOL(ieee80211_restart_hw); |
301 | 317 | ||
318 | static void ieee80211_recalc_smps_work(struct work_struct *work) | ||
319 | { | ||
320 | struct ieee80211_local *local = | ||
321 | container_of(work, struct ieee80211_local, recalc_smps); | ||
322 | |||
323 | mutex_lock(&local->iflist_mtx); | ||
324 | ieee80211_recalc_smps(local, NULL); | ||
325 | mutex_unlock(&local->iflist_mtx); | ||
326 | } | ||
327 | |||
302 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 328 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
303 | const struct ieee80211_ops *ops) | 329 | const struct ieee80211_ops *ops) |
304 | { | 330 | { |
@@ -372,6 +398,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
372 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 398 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
373 | 399 | ||
374 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 400 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
401 | INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work); | ||
402 | local->smps_mode = IEEE80211_SMPS_OFF; | ||
375 | 403 | ||
376 | INIT_WORK(&local->dynamic_ps_enable_work, | 404 | INIT_WORK(&local->dynamic_ps_enable_work, |
377 | ieee80211_dynamic_ps_enable_work); | 405 | ieee80211_dynamic_ps_enable_work); |
@@ -674,11 +702,19 @@ static int __init ieee80211_init(void) | |||
674 | 702 | ||
675 | ret = rc80211_pid_init(); | 703 | ret = rc80211_pid_init(); |
676 | if (ret) | 704 | if (ret) |
677 | return ret; | 705 | goto err_pid; |
678 | 706 | ||
679 | ieee80211_debugfs_netdev_init(); | 707 | ret = ieee80211_iface_init(); |
708 | if (ret) | ||
709 | goto err_netdev; | ||
680 | 710 | ||
681 | return 0; | 711 | return 0; |
712 | err_netdev: | ||
713 | rc80211_pid_exit(); | ||
714 | err_pid: | ||
715 | rc80211_minstrel_exit(); | ||
716 | |||
717 | return ret; | ||
682 | } | 718 | } |
683 | 719 | ||
684 | static void __exit ieee80211_exit(void) | 720 | static void __exit ieee80211_exit(void) |
@@ -695,7 +731,7 @@ static void __exit ieee80211_exit(void) | |||
695 | if (mesh_allocated) | 731 | if (mesh_allocated) |
696 | ieee80211s_stop(); | 732 | ieee80211s_stop(); |
697 | 733 | ||
698 | ieee80211_debugfs_netdev_exit(); | 734 | ieee80211_iface_exit(); |
699 | } | 735 | } |
700 | 736 | ||
701 | 737 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6a4331429598..e0bd85e3d4b6 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -457,7 +457,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
457 | 457 | ||
458 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 458 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
459 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | 459 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", |
460 | sdata->dev->name); | 460 | sdata->name); |
461 | #endif | 461 | #endif |
462 | 462 | ||
463 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 463 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
@@ -565,7 +565,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
565 | 565 | ||
566 | /* ignore ProbeResp to foreign address */ | 566 | /* ignore ProbeResp to foreign address */ |
567 | if (stype == IEEE80211_STYPE_PROBE_RESP && | 567 | if (stype == IEEE80211_STYPE_PROBE_RESP && |
568 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | 568 | compare_ether_addr(mgmt->da, sdata->vif.addr)) |
569 | return; | 569 | return; |
570 | 570 | ||
571 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 571 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index d28acb6b1f81..ce84237ebad3 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -128,9 +128,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
128 | IEEE80211_STYPE_ACTION); | 128 | IEEE80211_STYPE_ACTION); |
129 | 129 | ||
130 | memcpy(mgmt->da, da, ETH_ALEN); | 130 | memcpy(mgmt->da, da, ETH_ALEN); |
131 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 131 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
132 | /* BSSID == SA */ | 132 | /* BSSID == SA */ |
133 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 133 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
134 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 134 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
135 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 135 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
136 | 136 | ||
@@ -222,7 +222,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
222 | IEEE80211_STYPE_ACTION); | 222 | IEEE80211_STYPE_ACTION); |
223 | 223 | ||
224 | memcpy(mgmt->da, ra, ETH_ALEN); | 224 | memcpy(mgmt->da, ra, ETH_ALEN); |
225 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 225 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
226 | /* BSSID is left zeroed, wildcard value */ | 226 | /* BSSID is left zeroed, wildcard value */ |
227 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 227 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
228 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 228 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
@@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
335 | bool process = true; | 335 | bool process = true; |
336 | 336 | ||
337 | rcu_read_lock(); | 337 | rcu_read_lock(); |
338 | sta = sta_info_get(local, mgmt->sa); | 338 | sta = sta_info_get(sdata, mgmt->sa); |
339 | if (!sta) { | 339 | if (!sta) { |
340 | rcu_read_unlock(); | 340 | rcu_read_unlock(); |
341 | return 0; | 341 | return 0; |
@@ -374,7 +374,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
374 | new_metric = MAX_METRIC; | 374 | new_metric = MAX_METRIC; |
375 | exp_time = TU_TO_EXP_TIME(orig_lifetime); | 375 | exp_time = TU_TO_EXP_TIME(orig_lifetime); |
376 | 376 | ||
377 | if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { | 377 | if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) { |
378 | /* This MP is the originator, we are not interested in this | 378 | /* This MP is the originator, we are not interested in this |
379 | * frame, except for updating transmitter's path info. | 379 | * frame, except for updating transmitter's path info. |
380 | */ | 380 | */ |
@@ -486,7 +486,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
486 | 486 | ||
487 | mhwmp_dbg("received PREQ from %pM\n", orig_addr); | 487 | mhwmp_dbg("received PREQ from %pM\n", orig_addr); |
488 | 488 | ||
489 | if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { | 489 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { |
490 | mhwmp_dbg("PREQ is for us\n"); | 490 | mhwmp_dbg("PREQ is for us\n"); |
491 | forward = false; | 491 | forward = false; |
492 | reply = true; | 492 | reply = true; |
@@ -579,7 +579,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
579 | * replies | 579 | * replies |
580 | */ | 580 | */ |
581 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); | 581 | target_addr = PREP_IE_TARGET_ADDR(prep_elem); |
582 | if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) | 582 | if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) |
583 | /* destination, no forwarding required */ | 583 | /* destination, no forwarding required */ |
584 | return; | 584 | return; |
585 | 585 | ||
@@ -890,7 +890,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
890 | target_flags = MP_F_RF; | 890 | target_flags = MP_F_RF; |
891 | 891 | ||
892 | spin_unlock_bh(&mpath->state_lock); | 892 | spin_unlock_bh(&mpath->state_lock); |
893 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, | 893 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, |
894 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, | 894 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, |
895 | cpu_to_le32(mpath->sn), broadcast_addr, 0, | 895 | cpu_to_le32(mpath->sn), broadcast_addr, 0, |
896 | ttl, cpu_to_le32(lifetime), 0, | 896 | ttl, cpu_to_le32(lifetime), 0, |
@@ -939,7 +939,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
939 | if (time_after(jiffies, | 939 | if (time_after(jiffies, |
940 | mpath->exp_time - | 940 | mpath->exp_time - |
941 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && | 941 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && |
942 | !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && | 942 | !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && |
943 | !(mpath->flags & MESH_PATH_RESOLVING) && | 943 | !(mpath->flags & MESH_PATH_RESOLVING) && |
944 | !(mpath->flags & MESH_PATH_FIXED)) { | 944 | !(mpath->flags & MESH_PATH_FIXED)) { |
945 | mesh_queue_preq(mpath, | 945 | mesh_queue_preq(mpath, |
@@ -1010,7 +1010,7 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1010 | { | 1010 | { |
1011 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1011 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1012 | 1012 | ||
1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, | 1013 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, |
1014 | cpu_to_le32(++ifmsh->sn), | 1014 | cpu_to_le32(++ifmsh->sn), |
1015 | 0, NULL, 0, broadcast_addr, | 1015 | 0, NULL, 0, broadcast_addr, |
1016 | 0, MESH_TTL, 0, 0, 0, sdata); | 1016 | 0, MESH_TTL, 0, 0, 0, sdata); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0192cfdacae4..2312efe04c62 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -260,7 +260,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
260 | int err = 0; | 260 | int err = 0; |
261 | u32 hash_idx; | 261 | u32 hash_idx; |
262 | 262 | ||
263 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 263 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) |
264 | /* never add ourselves as neighbours */ | 264 | /* never add ourselves as neighbours */ |
265 | return -ENOTSUPP; | 265 | return -ENOTSUPP; |
266 | 266 | ||
@@ -377,7 +377,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
377 | int err = 0; | 377 | int err = 0; |
378 | u32 hash_idx; | 378 | u32 hash_idx; |
379 | 379 | ||
380 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 380 | if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) |
381 | /* never add ourselves as neighbours */ | 381 | /* never add ourselves as neighbours */ |
382 | return -ENOTSUPP; | 382 | return -ENOTSUPP; |
383 | 383 | ||
@@ -605,7 +605,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
605 | struct mesh_path *mpath; | 605 | struct mesh_path *mpath; |
606 | u32 sn = 0; | 606 | u32 sn = 0; |
607 | 607 | ||
608 | if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { | 608 | if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { |
609 | u8 *ra, *da; | 609 | u8 *ra, *da; |
610 | 610 | ||
611 | da = hdr->addr3; | 611 | da = hdr->addr3; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 0f7c6e6a4248..7985e5150898 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -169,7 +169,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
169 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 169 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
170 | IEEE80211_STYPE_ACTION); | 170 | IEEE80211_STYPE_ACTION); |
171 | memcpy(mgmt->da, da, ETH_ALEN); | 171 | memcpy(mgmt->da, da, ETH_ALEN); |
172 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 172 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
173 | /* BSSID is left zeroed, wildcard value */ | 173 | /* BSSID is left zeroed, wildcard value */ |
174 | mgmt->u.action.category = MESH_PLINK_CATEGORY; | 174 | mgmt->u.action.category = MESH_PLINK_CATEGORY; |
175 | mgmt->u.action.u.plink_action.action_code = action; | 175 | mgmt->u.action.u.plink_action.action_code = action; |
@@ -234,7 +234,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
234 | 234 | ||
235 | rcu_read_lock(); | 235 | rcu_read_lock(); |
236 | 236 | ||
237 | sta = sta_info_get(local, hw_addr); | 237 | sta = sta_info_get(sdata, hw_addr); |
238 | if (!sta) { | 238 | if (!sta) { |
239 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 239 | sta = mesh_plink_alloc(sdata, hw_addr, rates); |
240 | if (!sta) { | 240 | if (!sta) { |
@@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
455 | 455 | ||
456 | rcu_read_lock(); | 456 | rcu_read_lock(); |
457 | 457 | ||
458 | sta = sta_info_get(local, mgmt->sa); | 458 | sta = sta_info_get(sdata, mgmt->sa); |
459 | if (!sta && ftype != PLINK_OPEN) { | 459 | if (!sta && ftype != PLINK_OPEN) { |
460 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); | 460 | mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); |
461 | rcu_read_unlock(); | 461 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c79e59f82fd9..2f9ed8b9c3f0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -75,6 +75,9 @@ enum rx_mgmt_action { | |||
75 | /* caller must call cfg80211_send_disassoc() */ | 75 | /* caller must call cfg80211_send_disassoc() */ |
76 | RX_MGMT_CFG80211_DISASSOC, | 76 | RX_MGMT_CFG80211_DISASSOC, |
77 | 77 | ||
78 | /* caller must tell cfg80211 about internal error */ | ||
79 | RX_MGMT_CFG80211_ASSOC_ERROR, | ||
80 | |||
78 | /* caller must call cfg80211_auth_timeout() & free work */ | 81 | /* caller must call cfg80211_auth_timeout() & free work */ |
79 | RX_MGMT_CFG80211_AUTH_TO, | 82 | RX_MGMT_CFG80211_AUTH_TO, |
80 | 83 | ||
@@ -202,7 +205,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
202 | ieee80211_hw_config(local, 0); | 205 | ieee80211_hw_config(local, 0); |
203 | 206 | ||
204 | rcu_read_lock(); | 207 | rcu_read_lock(); |
205 | sta = sta_info_get(local, bssid); | 208 | sta = sta_info_get(sdata, bssid); |
206 | if (sta) | 209 | if (sta) |
207 | rate_control_rate_update(local, sband, sta, | 210 | rate_control_rate_update(local, sband, sta, |
208 | IEEE80211_RC_HT_CHANGED); | 211 | IEEE80211_RC_HT_CHANGED); |
@@ -248,7 +251,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
248 | wk->ssid_len); | 251 | wk->ssid_len); |
249 | if (!skb) { | 252 | if (!skb) { |
250 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 253 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
251 | "frame\n", sdata->dev->name); | 254 | "frame\n", sdata->name); |
252 | return; | 255 | return; |
253 | } | 256 | } |
254 | skb_reserve(skb, local->hw.extra_tx_headroom); | 257 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -282,7 +285,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
282 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 285 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
283 | memset(mgmt, 0, 24); | 286 | memset(mgmt, 0, 24); |
284 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); | 287 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); |
285 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 288 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
286 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); | 289 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); |
287 | 290 | ||
288 | if (!is_zero_ether_addr(wk->prev_bssid)) { | 291 | if (!is_zero_ether_addr(wk->prev_bssid)) { |
@@ -398,6 +401,14 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
398 | __le16 tmp; | 401 | __le16 tmp; |
399 | u32 flags = local->hw.conf.channel->flags; | 402 | u32 flags = local->hw.conf.channel->flags; |
400 | 403 | ||
404 | /* determine capability flags */ | ||
405 | |||
406 | if (ieee80211_disable_40mhz_24ghz && | ||
407 | sband->band == IEEE80211_BAND_2GHZ) { | ||
408 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
409 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
410 | } | ||
411 | |||
401 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 412 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
402 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 413 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
403 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 414 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
@@ -413,17 +424,64 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
413 | break; | 424 | break; |
414 | } | 425 | } |
415 | 426 | ||
416 | tmp = cpu_to_le16(cap); | 427 | /* set SM PS mode properly */ |
417 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); | 428 | cap &= ~IEEE80211_HT_CAP_SM_PS; |
429 | /* new association always uses requested smps mode */ | ||
430 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
431 | if (ifmgd->powersave) | ||
432 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
433 | else | ||
434 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
435 | } else | ||
436 | ifmgd->ap_smps = ifmgd->req_smps; | ||
437 | |||
438 | switch (ifmgd->ap_smps) { | ||
439 | case IEEE80211_SMPS_AUTOMATIC: | ||
440 | case IEEE80211_SMPS_NUM_MODES: | ||
441 | WARN_ON(1); | ||
442 | case IEEE80211_SMPS_OFF: | ||
443 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
444 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
445 | break; | ||
446 | case IEEE80211_SMPS_STATIC: | ||
447 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
448 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
449 | break; | ||
450 | case IEEE80211_SMPS_DYNAMIC: | ||
451 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
452 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | /* reserve and fill IE */ | ||
457 | |||
458 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
418 | *pos++ = WLAN_EID_HT_CAPABILITY; | 459 | *pos++ = WLAN_EID_HT_CAPABILITY; |
419 | *pos++ = sizeof(struct ieee80211_ht_cap); | 460 | *pos++ = sizeof(struct ieee80211_ht_cap); |
420 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 461 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
462 | |||
463 | /* capability flags */ | ||
464 | tmp = cpu_to_le16(cap); | ||
421 | memcpy(pos, &tmp, sizeof(u16)); | 465 | memcpy(pos, &tmp, sizeof(u16)); |
422 | pos += sizeof(u16); | 466 | pos += sizeof(u16); |
423 | /* TODO: needs a define here for << 2 */ | 467 | |
468 | /* AMPDU parameters */ | ||
424 | *pos++ = sband->ht_cap.ampdu_factor | | 469 | *pos++ = sband->ht_cap.ampdu_factor | |
425 | (sband->ht_cap.ampdu_density << 2); | 470 | (sband->ht_cap.ampdu_density << |
471 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
472 | |||
473 | /* MCS set */ | ||
426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 474 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
475 | pos += sizeof(sband->ht_cap.mcs); | ||
476 | |||
477 | /* extended capabilities */ | ||
478 | pos += sizeof(__le16); | ||
479 | |||
480 | /* BF capabilities */ | ||
481 | pos += sizeof(__le32); | ||
482 | |||
483 | /* antenna selection */ | ||
484 | pos += sizeof(u8); | ||
427 | } | 485 | } |
428 | 486 | ||
429 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 487 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
@@ -443,7 +501,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
443 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 501 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
444 | if (!skb) { | 502 | if (!skb) { |
445 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 503 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
446 | "deauth/disassoc frame\n", sdata->dev->name); | 504 | "deauth/disassoc frame\n", sdata->name); |
447 | return; | 505 | return; |
448 | } | 506 | } |
449 | skb_reserve(skb, local->hw.extra_tx_headroom); | 507 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -451,7 +509,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
451 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 509 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
452 | memset(mgmt, 0, 24); | 510 | memset(mgmt, 0, 24); |
453 | memcpy(mgmt->da, bssid, ETH_ALEN); | 511 | memcpy(mgmt->da, bssid, ETH_ALEN); |
454 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 512 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
455 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 513 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
456 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); | 514 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); |
457 | skb_put(skb, 2); | 515 | skb_put(skb, 2); |
@@ -484,7 +542,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
484 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); | 542 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); |
485 | if (!skb) { | 543 | if (!skb) { |
486 | printk(KERN_DEBUG "%s: failed to allocate buffer for " | 544 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
487 | "pspoll frame\n", sdata->dev->name); | 545 | "pspoll frame\n", sdata->name); |
488 | return; | 546 | return; |
489 | } | 547 | } |
490 | skb_reserve(skb, local->hw.extra_tx_headroom); | 548 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -499,7 +557,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
499 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); | 557 | pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); |
500 | 558 | ||
501 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); | 559 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); |
502 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); | 560 | memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN); |
503 | 561 | ||
504 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 562 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
505 | ieee80211_tx_skb(sdata, skb); | 563 | ieee80211_tx_skb(sdata, skb); |
@@ -519,7 +577,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
519 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 577 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); |
520 | if (!skb) { | 578 | if (!skb) { |
521 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | 579 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " |
522 | "frame\n", sdata->dev->name); | 580 | "frame\n", sdata->name); |
523 | return; | 581 | return; |
524 | } | 582 | } |
525 | skb_reserve(skb, local->hw.extra_tx_headroom); | 583 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -532,7 +590,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
532 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | 590 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); |
533 | nullfunc->frame_control = fc; | 591 | nullfunc->frame_control = fc; |
534 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); | 592 | memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); |
535 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 593 | memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); |
536 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); | 594 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); |
537 | 595 | ||
538 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 596 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
@@ -940,6 +998,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
940 | 998 | ||
941 | mutex_lock(&local->iflist_mtx); | 999 | mutex_lock(&local->iflist_mtx); |
942 | ieee80211_recalc_ps(local, -1); | 1000 | ieee80211_recalc_ps(local, -1); |
1001 | ieee80211_recalc_smps(local, sdata); | ||
943 | mutex_unlock(&local->iflist_mtx); | 1002 | mutex_unlock(&local->iflist_mtx); |
944 | 1003 | ||
945 | netif_start_queue(sdata->dev); | 1004 | netif_start_queue(sdata->dev); |
@@ -956,7 +1015,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
956 | wk->tries++; | 1015 | wk->tries++; |
957 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | 1016 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { |
958 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", | 1017 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", |
959 | sdata->dev->name, wk->bss->cbss.bssid); | 1018 | sdata->name, wk->bss->cbss.bssid); |
960 | 1019 | ||
961 | /* | 1020 | /* |
962 | * Most likely AP is not in the range so remove the | 1021 | * Most likely AP is not in the range so remove the |
@@ -974,7 +1033,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
974 | } | 1033 | } |
975 | 1034 | ||
976 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", | 1035 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", |
977 | sdata->dev->name, wk->bss->cbss.bssid, | 1036 | sdata->name, wk->bss->cbss.bssid, |
978 | wk->tries); | 1037 | wk->tries); |
979 | 1038 | ||
980 | /* | 1039 | /* |
@@ -1001,7 +1060,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
1001 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | 1060 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { |
1002 | printk(KERN_DEBUG "%s: authentication with AP %pM" | 1061 | printk(KERN_DEBUG "%s: authentication with AP %pM" |
1003 | " timed out\n", | 1062 | " timed out\n", |
1004 | sdata->dev->name, wk->bss->cbss.bssid); | 1063 | sdata->name, wk->bss->cbss.bssid); |
1005 | 1064 | ||
1006 | /* | 1065 | /* |
1007 | * Most likely AP is not in the range so remove the | 1066 | * Most likely AP is not in the range so remove the |
@@ -1019,7 +1078,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
1019 | } | 1078 | } |
1020 | 1079 | ||
1021 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", | 1080 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", |
1022 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1081 | sdata->name, wk->bss->cbss.bssid, wk->tries); |
1023 | 1082 | ||
1024 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | 1083 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, |
1025 | wk->bss->cbss.bssid, NULL, 0, 0); | 1084 | wk->bss->cbss.bssid, NULL, 0, 0); |
@@ -1078,7 +1137,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1078 | netif_carrier_off(sdata->dev); | 1137 | netif_carrier_off(sdata->dev); |
1079 | 1138 | ||
1080 | rcu_read_lock(); | 1139 | rcu_read_lock(); |
1081 | sta = sta_info_get(local, bssid); | 1140 | sta = sta_info_get(sdata, bssid); |
1082 | if (sta) | 1141 | if (sta) |
1083 | ieee80211_sta_tear_down_BA_sessions(sta); | 1142 | ieee80211_sta_tear_down_BA_sessions(sta); |
1084 | rcu_read_unlock(); | 1143 | rcu_read_unlock(); |
@@ -1115,7 +1174,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1115 | 1174 | ||
1116 | rcu_read_lock(); | 1175 | rcu_read_lock(); |
1117 | 1176 | ||
1118 | sta = sta_info_get(local, bssid); | 1177 | sta = sta_info_get(sdata, bssid); |
1119 | if (!sta) { | 1178 | if (!sta) { |
1120 | rcu_read_unlock(); | 1179 | rcu_read_unlock(); |
1121 | return; | 1180 | return; |
@@ -1139,7 +1198,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1139 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { | 1198 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { |
1140 | printk(KERN_DEBUG "%s: association with AP %pM" | 1199 | printk(KERN_DEBUG "%s: association with AP %pM" |
1141 | " timed out\n", | 1200 | " timed out\n", |
1142 | sdata->dev->name, wk->bss->cbss.bssid); | 1201 | sdata->name, wk->bss->cbss.bssid); |
1143 | 1202 | ||
1144 | /* | 1203 | /* |
1145 | * Most likely AP is not in the range so remove the | 1204 | * Most likely AP is not in the range so remove the |
@@ -1157,7 +1216,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
1157 | } | 1216 | } |
1158 | 1217 | ||
1159 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", | 1218 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", |
1160 | sdata->dev->name, wk->bss->cbss.bssid, wk->tries); | 1219 | sdata->name, wk->bss->cbss.bssid, wk->tries); |
1161 | ieee80211_send_assoc(sdata, wk); | 1220 | ieee80211_send_assoc(sdata, wk); |
1162 | 1221 | ||
1163 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 1222 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
@@ -1218,7 +1277,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1218 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1277 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1219 | if (beacon && net_ratelimit()) | 1278 | if (beacon && net_ratelimit()) |
1220 | printk(KERN_DEBUG "%s: detected beacon loss from AP " | 1279 | printk(KERN_DEBUG "%s: detected beacon loss from AP " |
1221 | "- sending probe request\n", sdata->dev->name); | 1280 | "- sending probe request\n", sdata->name); |
1222 | #endif | 1281 | #endif |
1223 | 1282 | ||
1224 | /* | 1283 | /* |
@@ -1275,7 +1334,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, | |||
1275 | struct ieee80211_mgd_work *wk) | 1334 | struct ieee80211_mgd_work *wk) |
1276 | { | 1335 | { |
1277 | wk->state = IEEE80211_MGD_STATE_IDLE; | 1336 | wk->state = IEEE80211_MGD_STATE_IDLE; |
1278 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); | 1337 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); |
1279 | } | 1338 | } |
1280 | 1339 | ||
1281 | 1340 | ||
@@ -1372,7 +1431,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1372 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1431 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1373 | 1432 | ||
1374 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1433 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1375 | sdata->dev->name, bssid, reason_code); | 1434 | sdata->name, bssid, reason_code); |
1376 | 1435 | ||
1377 | if (!wk) { | 1436 | if (!wk) { |
1378 | ieee80211_set_disassoc(sdata, true); | 1437 | ieee80211_set_disassoc(sdata, true); |
@@ -1407,7 +1466,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1407 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1466 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1408 | 1467 | ||
1409 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1468 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1410 | sdata->dev->name, mgmt->sa, reason_code); | 1469 | sdata->name, mgmt->sa, reason_code); |
1411 | 1470 | ||
1412 | ieee80211_set_disassoc(sdata, false); | 1471 | ieee80211_set_disassoc(sdata, false); |
1413 | ieee80211_recalc_idle(sdata->local); | 1472 | ieee80211_recalc_idle(sdata->local); |
@@ -1431,8 +1490,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1431 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1490 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1432 | u8 *pos; | 1491 | u8 *pos; |
1433 | u32 changed = 0; | 1492 | u32 changed = 0; |
1434 | int i, j; | 1493 | int i, j, err; |
1435 | bool have_higher_than_11mbit = false, newsta = false; | 1494 | bool have_higher_than_11mbit = false; |
1436 | u16 ap_ht_cap_flags; | 1495 | u16 ap_ht_cap_flags; |
1437 | 1496 | ||
1438 | /* | 1497 | /* |
@@ -1452,7 +1511,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1452 | 1511 | ||
1453 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | 1512 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " |
1454 | "status=%d aid=%d)\n", | 1513 | "status=%d aid=%d)\n", |
1455 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, | 1514 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, |
1456 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1515 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
1457 | 1516 | ||
1458 | pos = mgmt->u.assoc_resp.variable; | 1517 | pos = mgmt->u.assoc_resp.variable; |
@@ -1466,7 +1525,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1466 | ms = tu * 1024 / 1000; | 1525 | ms = tu * 1024 / 1000; |
1467 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " | 1526 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " |
1468 | "comeback duration %u TU (%u ms)\n", | 1527 | "comeback duration %u TU (%u ms)\n", |
1469 | sdata->dev->name, tu, ms); | 1528 | sdata->name, tu, ms); |
1470 | wk->timeout = jiffies + msecs_to_jiffies(ms); | 1529 | wk->timeout = jiffies + msecs_to_jiffies(ms); |
1471 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 1530 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
1472 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); | 1531 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); |
@@ -1475,49 +1534,37 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1475 | 1534 | ||
1476 | if (status_code != WLAN_STATUS_SUCCESS) { | 1535 | if (status_code != WLAN_STATUS_SUCCESS) { |
1477 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1536 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
1478 | sdata->dev->name, status_code); | 1537 | sdata->name, status_code); |
1479 | wk->state = IEEE80211_MGD_STATE_IDLE; | 1538 | wk->state = IEEE80211_MGD_STATE_IDLE; |
1480 | return RX_MGMT_CFG80211_ASSOC; | 1539 | return RX_MGMT_CFG80211_ASSOC; |
1481 | } | 1540 | } |
1482 | 1541 | ||
1483 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1542 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
1484 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1543 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
1485 | "set\n", sdata->dev->name, aid); | 1544 | "set\n", sdata->name, aid); |
1486 | aid &= ~(BIT(15) | BIT(14)); | 1545 | aid &= ~(BIT(15) | BIT(14)); |
1487 | 1546 | ||
1488 | if (!elems.supp_rates) { | 1547 | if (!elems.supp_rates) { |
1489 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1548 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
1490 | sdata->dev->name); | 1549 | sdata->name); |
1491 | return RX_MGMT_NONE; | 1550 | return RX_MGMT_NONE; |
1492 | } | 1551 | } |
1493 | 1552 | ||
1494 | printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); | 1553 | printk(KERN_DEBUG "%s: associated\n", sdata->name); |
1495 | ifmgd->aid = aid; | 1554 | ifmgd->aid = aid; |
1496 | 1555 | ||
1497 | rcu_read_lock(); | 1556 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); |
1498 | |||
1499 | /* Add STA entry for the AP */ | ||
1500 | sta = sta_info_get(local, wk->bss->cbss.bssid); | ||
1501 | if (!sta) { | 1557 | if (!sta) { |
1502 | newsta = true; | 1558 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
1503 | 1559 | " the AP\n", sdata->name); | |
1504 | rcu_read_unlock(); | 1560 | return RX_MGMT_CFG80211_ASSOC_ERROR; |
1505 | |||
1506 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); | ||
1507 | if (!sta) { | ||
1508 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | ||
1509 | " the AP\n", sdata->dev->name); | ||
1510 | return RX_MGMT_NONE; | ||
1511 | } | ||
1512 | |||
1513 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1514 | WLAN_STA_ASSOC_AP); | ||
1515 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1516 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1517 | |||
1518 | rcu_read_lock(); | ||
1519 | } | 1561 | } |
1520 | 1562 | ||
1563 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | ||
1564 | WLAN_STA_ASSOC_AP); | ||
1565 | if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | ||
1566 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
1567 | |||
1521 | rates = 0; | 1568 | rates = 0; |
1522 | basic_rates = 0; | 1569 | basic_rates = 0; |
1523 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1570 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
@@ -1580,18 +1627,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1580 | if (elems.wmm_param) | 1627 | if (elems.wmm_param) |
1581 | set_sta_flags(sta, WLAN_STA_WME); | 1628 | set_sta_flags(sta, WLAN_STA_WME); |
1582 | 1629 | ||
1583 | if (newsta) { | 1630 | err = sta_info_insert(sta); |
1584 | int err = sta_info_insert(sta); | 1631 | sta = NULL; |
1585 | if (err) { | 1632 | if (err) { |
1586 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1633 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
1587 | " the AP (error %d)\n", sdata->dev->name, err); | 1634 | " the AP (error %d)\n", sdata->name, err); |
1588 | rcu_read_unlock(); | 1635 | return RX_MGMT_CFG80211_ASSOC_ERROR; |
1589 | return RX_MGMT_NONE; | ||
1590 | } | ||
1591 | } | 1636 | } |
1592 | 1637 | ||
1593 | rcu_read_unlock(); | ||
1594 | |||
1595 | if (elems.wmm_param) | 1638 | if (elems.wmm_param) |
1596 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, | 1639 | ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, |
1597 | elems.wmm_param_len); | 1640 | elems.wmm_param_len); |
@@ -1679,7 +1722,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1679 | 1722 | ||
1680 | ASSERT_MGD_MTX(ifmgd); | 1723 | ASSERT_MGD_MTX(ifmgd); |
1681 | 1724 | ||
1682 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 1725 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
1683 | return; /* ignore ProbeResp to foreign address */ | 1726 | return; /* ignore ProbeResp to foreign address */ |
1684 | 1727 | ||
1685 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1728 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
@@ -1694,7 +1737,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1694 | /* direct probe may be part of the association flow */ | 1737 | /* direct probe may be part of the association flow */ |
1695 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { | 1738 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { |
1696 | printk(KERN_DEBUG "%s: direct probe responded\n", | 1739 | printk(KERN_DEBUG "%s: direct probe responded\n", |
1697 | sdata->dev->name); | 1740 | sdata->name); |
1698 | wk->tries = 0; | 1741 | wk->tries = 0; |
1699 | wk->state = IEEE80211_MGD_STATE_AUTH; | 1742 | wk->state = IEEE80211_MGD_STATE_AUTH; |
1700 | WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); | 1743 | WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); |
@@ -1787,7 +1830,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1787 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1830 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1788 | if (net_ratelimit()) { | 1831 | if (net_ratelimit()) { |
1789 | printk(KERN_DEBUG "%s: cancelling probereq poll due " | 1832 | printk(KERN_DEBUG "%s: cancelling probereq poll due " |
1790 | "to a received beacon\n", sdata->dev->name); | 1833 | "to a received beacon\n", sdata->name); |
1791 | } | 1834 | } |
1792 | #endif | 1835 | #endif |
1793 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 1836 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
@@ -1865,7 +1908,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1865 | 1908 | ||
1866 | rcu_read_lock(); | 1909 | rcu_read_lock(); |
1867 | 1910 | ||
1868 | sta = sta_info_get(local, bssid); | 1911 | sta = sta_info_get(sdata, bssid); |
1869 | if (WARN_ON(!sta)) { | 1912 | if (WARN_ON(!sta)) { |
1870 | rcu_read_unlock(); | 1913 | rcu_read_unlock(); |
1871 | return; | 1914 | return; |
@@ -2036,6 +2079,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2036 | case RX_MGMT_CFG80211_DEAUTH: | 2079 | case RX_MGMT_CFG80211_DEAUTH: |
2037 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 2080 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
2038 | break; | 2081 | break; |
2082 | case RX_MGMT_CFG80211_ASSOC_ERROR: | ||
2083 | /* an internal error -- pretend timeout for now */ | ||
2084 | cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2085 | break; | ||
2039 | default: | 2086 | default: |
2040 | WARN(1, "unexpected: %d", rma); | 2087 | WARN(1, "unexpected: %d", rma); |
2041 | } | 2088 | } |
@@ -2336,6 +2383,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2336 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | 2383 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; |
2337 | 2384 | ||
2338 | mutex_init(&ifmgd->mtx); | 2385 | mutex_init(&ifmgd->mtx); |
2386 | |||
2387 | if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) | ||
2388 | ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; | ||
2389 | else | ||
2390 | ifmgd->req_smps = IEEE80211_SMPS_OFF; | ||
2339 | } | 2391 | } |
2340 | 2392 | ||
2341 | /* scan finished notification */ | 2393 | /* scan finished notification */ |
@@ -2563,7 +2615,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2563 | mutex_unlock(&ifmgd->mtx); | 2615 | mutex_unlock(&ifmgd->mtx); |
2564 | 2616 | ||
2565 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2617 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2566 | sdata->dev->name, bssid, req->reason_code); | 2618 | sdata->name, bssid, req->reason_code); |
2567 | 2619 | ||
2568 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2620 | ieee80211_send_deauth_disassoc(sdata, bssid, |
2569 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2621 | IEEE80211_STYPE_DEAUTH, req->reason_code, |
@@ -2594,7 +2646,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2594 | } | 2646 | } |
2595 | 2647 | ||
2596 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2648 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2597 | sdata->dev->name, req->bss->bssid, req->reason_code); | 2649 | sdata->name, req->bss->bssid, req->reason_code); |
2598 | 2650 | ||
2599 | ieee80211_set_disassoc(sdata, false); | 2651 | ieee80211_set_disassoc(sdata, false); |
2600 | 2652 | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index e535f1c988fe..05e161c3cbc5 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -65,7 +65,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
65 | struct ieee80211_sub_if_data, | 65 | struct ieee80211_sub_if_data, |
66 | u.ap); | 66 | u.ap); |
67 | 67 | ||
68 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, | 68 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, |
69 | &sta->sta); | 69 | &sta->sta); |
70 | } | 70 | } |
71 | 71 | ||
@@ -102,7 +102,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
102 | 102 | ||
103 | conf.vif = &sdata->vif; | 103 | conf.vif = &sdata->vif; |
104 | conf.type = sdata->vif.type; | 104 | conf.type = sdata->vif.type; |
105 | conf.mac_addr = sdata->dev->dev_addr; | 105 | conf.mac_addr = sdata->vif.addr; |
106 | drv_remove_interface(local, &conf); | 106 | drv_remove_interface(local, &conf); |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9f2807aeaf52..6cbf1a7b3157 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -283,15 +283,15 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
283 | skb->protocol = htons(ETH_P_802_2); | 283 | skb->protocol = htons(ETH_P_802_2); |
284 | 284 | ||
285 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 285 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
286 | if (!netif_running(sdata->dev)) | ||
287 | continue; | ||
288 | |||
289 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 286 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
290 | continue; | 287 | continue; |
291 | 288 | ||
292 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 289 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
293 | continue; | 290 | continue; |
294 | 291 | ||
292 | if (!netif_running(sdata->dev)) | ||
293 | continue; | ||
294 | |||
295 | if (prev_dev) { | 295 | if (prev_dev) { |
296 | skb2 = skb_clone(skb, GFP_ATOMIC); | 296 | skb2 = skb_clone(skb, GFP_ATOMIC); |
297 | if (skb2) { | 297 | if (skb2) { |
@@ -361,7 +361,9 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
361 | * boundary. In the case of regular frames, this simply means aligning the | 361 | * boundary. In the case of regular frames, this simply means aligning the |
362 | * payload to a four-byte boundary (because either the IP header is directly | 362 | * payload to a four-byte boundary (because either the IP header is directly |
363 | * contained, or IV/RFC1042 headers that have a length divisible by four are | 363 | * contained, or IV/RFC1042 headers that have a length divisible by four are |
364 | * in front of it). | 364 | * in front of it). If the payload data is not properly aligned and the |
365 | * architecture doesn't support efficient unaligned operations, mac80211 | ||
366 | * will align the data. | ||
365 | * | 367 | * |
366 | * With A-MSDU frames, however, the payload data address must yield two modulo | 368 | * With A-MSDU frames, however, the payload data address must yield two modulo |
367 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that | 369 | * four because there are 14-byte 802.3 headers within the A-MSDU frames that |
@@ -375,25 +377,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
375 | */ | 377 | */ |
376 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) | 378 | static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) |
377 | { | 379 | { |
378 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 380 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
379 | int hdrlen; | 381 | WARN_ONCE((unsigned long)rx->skb->data & 1, |
380 | 382 | "unaligned packet at 0x%p\n", rx->skb->data); | |
381 | #ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | ||
382 | return; | ||
383 | #endif | 383 | #endif |
384 | |||
385 | if (WARN_ONCE((unsigned long)rx->skb->data & 1, | ||
386 | "unaligned packet at 0x%p\n", rx->skb->data)) | ||
387 | return; | ||
388 | |||
389 | if (!ieee80211_is_data_present(hdr->frame_control)) | ||
390 | return; | ||
391 | |||
392 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
393 | if (rx->flags & IEEE80211_RX_AMSDU) | ||
394 | hdrlen += ETH_HLEN; | ||
395 | WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, | ||
396 | "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); | ||
397 | } | 384 | } |
398 | 385 | ||
399 | 386 | ||
@@ -476,7 +463,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
476 | { | 463 | { |
477 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 464 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
478 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 465 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
479 | char *dev_addr = rx->sdata->dev->dev_addr; | 466 | char *dev_addr = rx->sdata->vif.addr; |
480 | 467 | ||
481 | if (ieee80211_is_data(hdr->frame_control)) { | 468 | if (ieee80211_is_data(hdr->frame_control)) { |
482 | if (is_multicast_ether_addr(hdr->addr1)) { | 469 | if (is_multicast_ether_addr(hdr->addr1)) { |
@@ -1021,10 +1008,10 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1021 | 1008 | ||
1022 | atomic_inc(&sdata->bss->num_sta_ps); | 1009 | atomic_inc(&sdata->bss->num_sta_ps); |
1023 | set_sta_flags(sta, WLAN_STA_PS_STA); | 1010 | set_sta_flags(sta, WLAN_STA_PS_STA); |
1024 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); | 1011 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); |
1025 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1012 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1026 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1013 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
1027 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1014 | sdata->name, sta->sta.addr, sta->sta.aid); |
1028 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1015 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1029 | } | 1016 | } |
1030 | 1017 | ||
@@ -1038,13 +1025,13 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1038 | 1025 | ||
1039 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1026 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1040 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", | 1027 | printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", |
1041 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1028 | sdata->name, sta->sta.addr, sta->sta.aid); |
1042 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1029 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1043 | 1030 | ||
1044 | if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { | 1031 | if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { |
1045 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1032 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1046 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", | 1033 | printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", |
1047 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 1034 | sdata->name, sta->sta.addr, sta->sta.aid); |
1048 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1035 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1049 | return; | 1036 | return; |
1050 | } | 1037 | } |
@@ -1156,7 +1143,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
1156 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " | 1143 | printk(KERN_DEBUG "%s: RX reassembly removed oldest " |
1157 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " | 1144 | "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " |
1158 | "addr1=%pM addr2=%pM\n", | 1145 | "addr1=%pM addr2=%pM\n", |
1159 | sdata->dev->name, idx, | 1146 | sdata->name, idx, |
1160 | jiffies - entry->first_frag_time, entry->seq, | 1147 | jiffies - entry->first_frag_time, entry->seq, |
1161 | entry->last_frag, hdr->addr1, hdr->addr2); | 1148 | entry->last_frag, hdr->addr1, hdr->addr2); |
1162 | #endif | 1149 | #endif |
@@ -1424,7 +1411,6 @@ static int | |||
1424 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | 1411 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
1425 | { | 1412 | { |
1426 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1413 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1427 | struct net_device *dev = sdata->dev; | ||
1428 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1414 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1429 | 1415 | ||
1430 | if (ieee80211_has_a4(hdr->frame_control) && | 1416 | if (ieee80211_has_a4(hdr->frame_control) && |
@@ -1436,7 +1422,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1436 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) | 1422 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) |
1437 | return -1; | 1423 | return -1; |
1438 | 1424 | ||
1439 | return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); | 1425 | return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); |
1440 | } | 1426 | } |
1441 | 1427 | ||
1442 | /* | 1428 | /* |
@@ -1453,7 +1439,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
1453 | * of whether the frame was encrypted or not. | 1439 | * of whether the frame was encrypted or not. |
1454 | */ | 1440 | */ |
1455 | if (ehdr->h_proto == htons(ETH_P_PAE) && | 1441 | if (ehdr->h_proto == htons(ETH_P_PAE) && |
1456 | (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 || | 1442 | (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || |
1457 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | 1443 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) |
1458 | return true; | 1444 | return true; |
1459 | 1445 | ||
@@ -1472,7 +1458,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1472 | { | 1458 | { |
1473 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1459 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1474 | struct net_device *dev = sdata->dev; | 1460 | struct net_device *dev = sdata->dev; |
1475 | struct ieee80211_local *local = rx->local; | ||
1476 | struct sk_buff *skb, *xmit_skb; | 1461 | struct sk_buff *skb, *xmit_skb; |
1477 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1462 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1478 | struct sta_info *dsta; | 1463 | struct sta_info *dsta; |
@@ -1495,8 +1480,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1495 | printk(KERN_DEBUG "%s: failed to clone " | 1480 | printk(KERN_DEBUG "%s: failed to clone " |
1496 | "multicast frame\n", dev->name); | 1481 | "multicast frame\n", dev->name); |
1497 | } else { | 1482 | } else { |
1498 | dsta = sta_info_get(local, skb->data); | 1483 | dsta = sta_info_get(sdata, skb->data); |
1499 | if (dsta && dsta->sdata->dev == dev) { | 1484 | if (dsta) { |
1500 | /* | 1485 | /* |
1501 | * The destination station is associated to | 1486 | * The destination station is associated to |
1502 | * this AP (in this VLAN), so send the frame | 1487 | * this AP (in this VLAN), so send the frame |
@@ -1512,7 +1497,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1512 | if (skb) { | 1497 | if (skb) { |
1513 | int align __maybe_unused; | 1498 | int align __maybe_unused; |
1514 | 1499 | ||
1515 | #if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 1500 | #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
1516 | /* | 1501 | /* |
1517 | * 'align' will only take the values 0 or 2 here | 1502 | * 'align' will only take the values 0 or 2 here |
1518 | * since all frames are required to be aligned | 1503 | * since all frames are required to be aligned |
@@ -1556,16 +1541,10 @@ static ieee80211_rx_result debug_noinline | |||
1556 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | 1541 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) |
1557 | { | 1542 | { |
1558 | struct net_device *dev = rx->sdata->dev; | 1543 | struct net_device *dev = rx->sdata->dev; |
1559 | struct ieee80211_local *local = rx->local; | 1544 | struct sk_buff *skb = rx->skb; |
1560 | u16 ethertype; | ||
1561 | u8 *payload; | ||
1562 | struct sk_buff *skb = rx->skb, *frame = NULL; | ||
1563 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1545 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1564 | __le16 fc = hdr->frame_control; | 1546 | __le16 fc = hdr->frame_control; |
1565 | const struct ethhdr *eth; | 1547 | struct sk_buff_head frame_list; |
1566 | int remaining, err; | ||
1567 | u8 dst[ETH_ALEN]; | ||
1568 | u8 src[ETH_ALEN]; | ||
1569 | 1548 | ||
1570 | if (unlikely(!ieee80211_is_data(fc))) | 1549 | if (unlikely(!ieee80211_is_data(fc))) |
1571 | return RX_CONTINUE; | 1550 | return RX_CONTINUE; |
@@ -1576,94 +1555,34 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1576 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1555 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
1577 | return RX_CONTINUE; | 1556 | return RX_CONTINUE; |
1578 | 1557 | ||
1579 | err = __ieee80211_data_to_8023(rx); | 1558 | if (ieee80211_has_a4(hdr->frame_control) && |
1580 | if (unlikely(err)) | 1559 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
1560 | !rx->sdata->u.vlan.sta) | ||
1581 | return RX_DROP_UNUSABLE; | 1561 | return RX_DROP_UNUSABLE; |
1582 | 1562 | ||
1583 | skb->dev = dev; | 1563 | if (is_multicast_ether_addr(hdr->addr1) && |
1584 | 1564 | ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | |
1585 | dev->stats.rx_packets++; | 1565 | rx->sdata->u.vlan.sta) || |
1586 | dev->stats.rx_bytes += skb->len; | 1566 | (rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
1587 | 1567 | rx->sdata->u.mgd.use_4addr))) | |
1588 | /* skip the wrapping header */ | ||
1589 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); | ||
1590 | if (!eth) | ||
1591 | return RX_DROP_UNUSABLE; | 1568 | return RX_DROP_UNUSABLE; |
1592 | 1569 | ||
1593 | while (skb != frame) { | 1570 | skb->dev = dev; |
1594 | u8 padding; | 1571 | __skb_queue_head_init(&frame_list); |
1595 | __be16 len = eth->h_proto; | ||
1596 | unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); | ||
1597 | |||
1598 | remaining = skb->len; | ||
1599 | memcpy(dst, eth->h_dest, ETH_ALEN); | ||
1600 | memcpy(src, eth->h_source, ETH_ALEN); | ||
1601 | |||
1602 | padding = ((4 - subframe_len) & 0x3); | ||
1603 | /* the last MSDU has no padding */ | ||
1604 | if (subframe_len > remaining) | ||
1605 | return RX_DROP_UNUSABLE; | ||
1606 | 1572 | ||
1607 | skb_pull(skb, sizeof(struct ethhdr)); | 1573 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1608 | /* if last subframe reuse skb */ | 1574 | rx->sdata->vif.type, |
1609 | if (remaining <= subframe_len + padding) | 1575 | rx->local->hw.extra_tx_headroom); |
1610 | frame = skb; | ||
1611 | else { | ||
1612 | /* | ||
1613 | * Allocate and reserve two bytes more for payload | ||
1614 | * alignment since sizeof(struct ethhdr) is 14. | ||
1615 | */ | ||
1616 | frame = dev_alloc_skb( | ||
1617 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1618 | subframe_len + 2); | ||
1619 | |||
1620 | if (frame == NULL) | ||
1621 | return RX_DROP_UNUSABLE; | ||
1622 | |||
1623 | skb_reserve(frame, | ||
1624 | ALIGN(local->hw.extra_tx_headroom, 4) + | ||
1625 | sizeof(struct ethhdr) + 2); | ||
1626 | memcpy(skb_put(frame, ntohs(len)), skb->data, | ||
1627 | ntohs(len)); | ||
1628 | |||
1629 | eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + | ||
1630 | padding); | ||
1631 | if (!eth) { | ||
1632 | dev_kfree_skb(frame); | ||
1633 | return RX_DROP_UNUSABLE; | ||
1634 | } | ||
1635 | } | ||
1636 | 1576 | ||
1637 | skb_reset_network_header(frame); | 1577 | while (!skb_queue_empty(&frame_list)) { |
1638 | frame->dev = dev; | 1578 | rx->skb = __skb_dequeue(&frame_list); |
1639 | frame->priority = skb->priority; | ||
1640 | rx->skb = frame; | ||
1641 | |||
1642 | payload = frame->data; | ||
1643 | ethertype = (payload[6] << 8) | payload[7]; | ||
1644 | |||
1645 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | ||
1646 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | ||
1647 | compare_ether_addr(payload, | ||
1648 | bridge_tunnel_header) == 0)) { | ||
1649 | /* remove RFC1042 or Bridge-Tunnel | ||
1650 | * encapsulation and replace EtherType */ | ||
1651 | skb_pull(frame, 6); | ||
1652 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
1653 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
1654 | } else { | ||
1655 | memcpy(skb_push(frame, sizeof(__be16)), | ||
1656 | &len, sizeof(__be16)); | ||
1657 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
1658 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
1659 | } | ||
1660 | 1579 | ||
1661 | if (!ieee80211_frame_allowed(rx, fc)) { | 1580 | if (!ieee80211_frame_allowed(rx, fc)) { |
1662 | if (skb == frame) /* last frame */ | 1581 | dev_kfree_skb(rx->skb); |
1663 | return RX_DROP_UNUSABLE; | ||
1664 | dev_kfree_skb(frame); | ||
1665 | continue; | 1582 | continue; |
1666 | } | 1583 | } |
1584 | dev->stats.rx_packets++; | ||
1585 | dev->stats.rx_bytes += rx->skb->len; | ||
1667 | 1586 | ||
1668 | ieee80211_deliver_skb(rx); | 1587 | ieee80211_deliver_skb(rx); |
1669 | } | 1588 | } |
@@ -1721,7 +1640,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1721 | 1640 | ||
1722 | /* Frame has reached destination. Don't forward */ | 1641 | /* Frame has reached destination. Don't forward */ |
1723 | if (!is_multicast_ether_addr(hdr->addr1) && | 1642 | if (!is_multicast_ether_addr(hdr->addr1) && |
1724 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0) | 1643 | compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) |
1725 | return RX_CONTINUE; | 1644 | return RX_CONTINUE; |
1726 | 1645 | ||
1727 | mesh_hdr->ttl--; | 1646 | mesh_hdr->ttl--; |
@@ -1738,10 +1657,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1738 | 1657 | ||
1739 | if (!fwd_skb && net_ratelimit()) | 1658 | if (!fwd_skb && net_ratelimit()) |
1740 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1659 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1741 | sdata->dev->name); | 1660 | sdata->name); |
1742 | 1661 | ||
1743 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1662 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1744 | memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN); | 1663 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
1745 | info = IEEE80211_SKB_CB(fwd_skb); | 1664 | info = IEEE80211_SKB_CB(fwd_skb); |
1746 | memset(info, 0, sizeof(*info)); | 1665 | memset(info, 0, sizeof(*info)); |
1747 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1666 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
@@ -1870,7 +1789,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1870 | struct sk_buff *skb; | 1789 | struct sk_buff *skb; |
1871 | struct ieee80211_mgmt *resp; | 1790 | struct ieee80211_mgmt *resp; |
1872 | 1791 | ||
1873 | if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { | 1792 | if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) { |
1874 | /* Not to own unicast address */ | 1793 | /* Not to own unicast address */ |
1875 | return; | 1794 | return; |
1876 | } | 1795 | } |
@@ -1894,7 +1813,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1894 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); | 1813 | resp = (struct ieee80211_mgmt *) skb_put(skb, 24); |
1895 | memset(resp, 0, 24); | 1814 | memset(resp, 0, 24); |
1896 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 1815 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
1897 | memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); | 1816 | memcpy(resp->sa, sdata->vif.addr, ETH_ALEN); |
1898 | memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); | 1817 | memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
1899 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1818 | resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1900 | IEEE80211_STYPE_ACTION); | 1819 | IEEE80211_STYPE_ACTION); |
@@ -2274,7 +2193,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2274 | if (!bssid && !sdata->u.mgd.use_4addr) | 2193 | if (!bssid && !sdata->u.mgd.use_4addr) |
2275 | return 0; | 2194 | return 0; |
2276 | if (!multicast && | 2195 | if (!multicast && |
2277 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { | 2196 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { |
2278 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2197 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2279 | return 0; | 2198 | return 0; |
2280 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2199 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
@@ -2291,7 +2210,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2291 | return 0; | 2210 | return 0; |
2292 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2211 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
2293 | } else if (!multicast && | 2212 | } else if (!multicast && |
2294 | compare_ether_addr(sdata->dev->dev_addr, | 2213 | compare_ether_addr(sdata->vif.addr, |
2295 | hdr->addr1) != 0) { | 2214 | hdr->addr1) != 0) { |
2296 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2215 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2297 | return 0; | 2216 | return 0; |
@@ -2308,7 +2227,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2308 | break; | 2227 | break; |
2309 | case NL80211_IFTYPE_MESH_POINT: | 2228 | case NL80211_IFTYPE_MESH_POINT: |
2310 | if (!multicast && | 2229 | if (!multicast && |
2311 | compare_ether_addr(sdata->dev->dev_addr, | 2230 | compare_ether_addr(sdata->vif.addr, |
2312 | hdr->addr1) != 0) { | 2231 | hdr->addr1) != 0) { |
2313 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2232 | if (!(sdata->dev->flags & IFF_PROMISC)) |
2314 | return 0; | 2233 | return 0; |
@@ -2319,11 +2238,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2319 | case NL80211_IFTYPE_AP_VLAN: | 2238 | case NL80211_IFTYPE_AP_VLAN: |
2320 | case NL80211_IFTYPE_AP: | 2239 | case NL80211_IFTYPE_AP: |
2321 | if (!bssid) { | 2240 | if (!bssid) { |
2322 | if (compare_ether_addr(sdata->dev->dev_addr, | 2241 | if (compare_ether_addr(sdata->vif.addr, |
2323 | hdr->addr1)) | 2242 | hdr->addr1)) |
2324 | return 0; | 2243 | return 0; |
2325 | } else if (!ieee80211_bssid_match(bssid, | 2244 | } else if (!ieee80211_bssid_match(bssid, |
2326 | sdata->dev->dev_addr)) { | 2245 | sdata->vif.addr)) { |
2327 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) | 2246 | if (!(rx->flags & IEEE80211_RX_IN_SCAN)) |
2328 | return 0; | 2247 | return 0; |
2329 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2248 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
@@ -2362,6 +2281,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2362 | int prepares; | 2281 | int prepares; |
2363 | struct ieee80211_sub_if_data *prev = NULL; | 2282 | struct ieee80211_sub_if_data *prev = NULL; |
2364 | struct sk_buff *skb_new; | 2283 | struct sk_buff *skb_new; |
2284 | struct sta_info *sta, *tmp; | ||
2285 | bool found_sta = false; | ||
2365 | 2286 | ||
2366 | hdr = (struct ieee80211_hdr *)skb->data; | 2287 | hdr = (struct ieee80211_hdr *)skb->data; |
2367 | memset(&rx, 0, sizeof(rx)); | 2288 | memset(&rx, 0, sizeof(rx)); |
@@ -2378,68 +2299,76 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2378 | ieee80211_parse_qos(&rx); | 2299 | ieee80211_parse_qos(&rx); |
2379 | ieee80211_verify_alignment(&rx); | 2300 | ieee80211_verify_alignment(&rx); |
2380 | 2301 | ||
2381 | rx.sta = sta_info_get(local, hdr->addr2); | 2302 | if (ieee80211_is_data(hdr->frame_control)) { |
2382 | if (rx.sta) | 2303 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2383 | rx.sdata = rx.sta->sdata; | 2304 | rx.sta = sta; |
2384 | 2305 | found_sta = true; | |
2385 | if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { | 2306 | rx.sdata = sta->sdata; |
2386 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2307 | |
2387 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | 2308 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2388 | if (prepares) { | 2309 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); |
2389 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2310 | if (prepares) { |
2390 | if (rx.flags & IEEE80211_RX_RA_MATCH) | 2311 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2391 | ieee80211_rx_michael_mic_report(hdr, &rx); | 2312 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2392 | } else | 2313 | ieee80211_rx_michael_mic_report(hdr, &rx); |
2393 | prev = rx.sdata; | 2314 | } else |
2315 | prev = rx.sdata; | ||
2316 | } | ||
2394 | } | 2317 | } |
2395 | } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2318 | } |
2396 | if (!netif_running(sdata->dev)) | 2319 | if (!found_sta) { |
2397 | continue; | 2320 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2321 | if (!netif_running(sdata->dev)) | ||
2322 | continue; | ||
2398 | 2323 | ||
2399 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 2324 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
2400 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2325 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
2401 | continue; | 2326 | continue; |
2402 | 2327 | ||
2403 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2328 | rx.sta = sta_info_get(sdata, hdr->addr2); |
2404 | prepares = prepare_for_handlers(sdata, &rx, hdr); | ||
2405 | 2329 | ||
2406 | if (!prepares) | 2330 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2407 | continue; | 2331 | prepares = prepare_for_handlers(sdata, &rx, hdr); |
2408 | 2332 | ||
2409 | if (status->flag & RX_FLAG_MMIC_ERROR) { | 2333 | if (!prepares) |
2410 | rx.sdata = sdata; | 2334 | continue; |
2411 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2412 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2413 | continue; | ||
2414 | } | ||
2415 | 2335 | ||
2416 | /* | 2336 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2417 | * frame is destined for this interface, but if it's not | 2337 | rx.sdata = sdata; |
2418 | * also for the previous one we handle that after the | 2338 | if (rx.flags & IEEE80211_RX_RA_MATCH) |
2419 | * loop to avoid copying the SKB once too much | 2339 | ieee80211_rx_michael_mic_report(hdr, |
2420 | */ | 2340 | &rx); |
2341 | continue; | ||
2342 | } | ||
2421 | 2343 | ||
2422 | if (!prev) { | 2344 | /* |
2423 | prev = sdata; | 2345 | * frame is destined for this interface, but if it's |
2424 | continue; | 2346 | * not also for the previous one we handle that after |
2425 | } | 2347 | * the loop to avoid copying the SKB once too much |
2348 | */ | ||
2426 | 2349 | ||
2427 | /* | 2350 | if (!prev) { |
2428 | * frame was destined for the previous interface | 2351 | prev = sdata; |
2429 | * so invoke RX handlers for it | 2352 | continue; |
2430 | */ | 2353 | } |
2431 | 2354 | ||
2432 | skb_new = skb_copy(skb, GFP_ATOMIC); | 2355 | /* |
2433 | if (!skb_new) { | 2356 | * frame was destined for the previous interface |
2434 | if (net_ratelimit()) | 2357 | * so invoke RX handlers for it |
2435 | printk(KERN_DEBUG "%s: failed to copy " | 2358 | */ |
2436 | "multicast frame for %s\n", | 2359 | |
2437 | wiphy_name(local->hw.wiphy), | 2360 | skb_new = skb_copy(skb, GFP_ATOMIC); |
2438 | prev->dev->name); | 2361 | if (!skb_new) { |
2439 | continue; | 2362 | if (net_ratelimit()) |
2363 | printk(KERN_DEBUG "%s: failed to copy " | ||
2364 | "multicast frame for %s\n", | ||
2365 | wiphy_name(local->hw.wiphy), | ||
2366 | prev->name); | ||
2367 | continue; | ||
2368 | } | ||
2369 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2370 | prev = sdata; | ||
2440 | } | 2371 | } |
2441 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); | ||
2442 | prev = sdata; | ||
2443 | } | 2372 | } |
2444 | if (prev) | 2373 | if (prev) |
2445 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); | 2374 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f1a4c7160300..66da0ab1d8fa 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -147,7 +147,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
147 | presp = ieee80211_is_probe_resp(fc); | 147 | presp = ieee80211_is_probe_resp(fc); |
148 | if (presp) { | 148 | if (presp) { |
149 | /* ignore ProbeResp to foreign address */ | 149 | /* ignore ProbeResp to foreign address */ |
150 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 150 | if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) |
151 | return RX_DROP_MONITOR; | 151 | return RX_DROP_MONITOR; |
152 | 152 | ||
153 | presp = true; | 153 | presp = true; |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index aa743a895cf9..7733f66ee2c4 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -35,7 +35,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
35 | 35 | ||
36 | if (!skb) { | 36 | if (!skb) { |
37 | printk(KERN_ERR "%s: failed to allocate buffer for " | 37 | printk(KERN_ERR "%s: failed to allocate buffer for " |
38 | "measurement report frame\n", sdata->dev->name); | 38 | "measurement report frame\n", sdata->name); |
39 | return; | 39 | return; |
40 | } | 40 | } |
41 | 41 | ||
@@ -43,7 +43,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | 43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); |
44 | memset(msr_report, 0, 24); | 44 | memset(msr_report, 0, 24); |
45 | memcpy(msr_report->da, da, ETH_ALEN); | 45 | memcpy(msr_report->da, da, ETH_ALEN); |
46 | memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); | 46 | memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN); |
47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | 47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); |
48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
49 | IEEE80211_STYPE_ACTION); | 49 | IEEE80211_STYPE_ACTION); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 71f370dd24bc..d1a77e79d7a9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -103,13 +103,16 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /* protected by RCU */ | 105 | /* protected by RCU */ |
106 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) | 106 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
107 | const u8 *addr) | ||
107 | { | 108 | { |
109 | struct ieee80211_local *local = sdata->local; | ||
108 | struct sta_info *sta; | 110 | struct sta_info *sta; |
109 | 111 | ||
110 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 112 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
111 | while (sta) { | 113 | while (sta) { |
112 | if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 114 | if (sta->sdata == sdata && |
115 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | ||
113 | break; | 116 | break; |
114 | sta = rcu_dereference(sta->hnext); | 117 | sta = rcu_dereference(sta->hnext); |
115 | } | 118 | } |
@@ -369,7 +372,7 @@ int sta_info_insert(struct sta_info *sta) | |||
369 | goto out_free; | 372 | goto out_free; |
370 | } | 373 | } |
371 | 374 | ||
372 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || | 375 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || |
373 | is_multicast_ether_addr(sta->sta.addr))) { | 376 | is_multicast_ether_addr(sta->sta.addr))) { |
374 | err = -EINVAL; | 377 | err = -EINVAL; |
375 | goto out_free; | 378 | goto out_free; |
@@ -377,7 +380,7 @@ int sta_info_insert(struct sta_info *sta) | |||
377 | 380 | ||
378 | spin_lock_irqsave(&local->sta_lock, flags); | 381 | spin_lock_irqsave(&local->sta_lock, flags); |
379 | /* check if STA exists already */ | 382 | /* check if STA exists already */ |
380 | if (sta_info_get(local, sta->sta.addr)) { | 383 | if (sta_info_get(sdata, sta->sta.addr)) { |
381 | spin_unlock_irqrestore(&local->sta_lock, flags); | 384 | spin_unlock_irqrestore(&local->sta_lock, flags); |
382 | err = -EEXIST; | 385 | err = -EEXIST; |
383 | goto out_free; | 386 | goto out_free; |
@@ -394,7 +397,7 @@ int sta_info_insert(struct sta_info *sta) | |||
394 | struct ieee80211_sub_if_data, | 397 | struct ieee80211_sub_if_data, |
395 | u.ap); | 398 | u.ap); |
396 | 399 | ||
397 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); | 400 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); |
398 | sdata = sta->sdata; | 401 | sdata = sta->sdata; |
399 | } | 402 | } |
400 | 403 | ||
@@ -534,7 +537,7 @@ static void __sta_info_unlink(struct sta_info **sta) | |||
534 | struct ieee80211_sub_if_data, | 537 | struct ieee80211_sub_if_data, |
535 | u.ap); | 538 | u.ap); |
536 | 539 | ||
537 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, | 540 | drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, |
538 | &(*sta)->sta); | 541 | &(*sta)->sta); |
539 | sdata = (*sta)->sdata; | 542 | sdata = (*sta)->sdata; |
540 | } | 543 | } |
@@ -828,7 +831,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
828 | if (time_after(jiffies, sta->last_rx + exp_time)) { | 831 | if (time_after(jiffies, sta->last_rx + exp_time)) { |
829 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 832 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
830 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", | 833 | printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", |
831 | sdata->dev->name, sta->sta.addr); | 834 | sdata->name, sta->sta.addr); |
832 | #endif | 835 | #endif |
833 | __sta_info_unlink(&sta); | 836 | __sta_info_unlink(&sta); |
834 | if (sta) | 837 | if (sta) |
@@ -843,11 +846,12 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
843 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, | 846 | struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, |
844 | const u8 *addr) | 847 | const u8 *addr) |
845 | { | 848 | { |
846 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); | 849 | struct sta_info *sta, *nxt; |
847 | 850 | ||
848 | if (!sta) | 851 | /* Just return a random station ... first in list ... */ |
849 | return NULL; | 852 | for_each_sta_info(hw_to_local(hw), addr, sta, nxt) |
850 | return &sta->sta; | 853 | return &sta->sta; |
854 | return NULL; | ||
851 | } | 855 | } |
852 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); | 856 | EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); |
853 | 857 | ||
@@ -872,7 +876,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
872 | struct ieee80211_local *local = sdata->local; | 876 | struct ieee80211_local *local = sdata->local; |
873 | int sent, buffered; | 877 | int sent, buffered; |
874 | 878 | ||
875 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); | 879 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
876 | 880 | ||
877 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 881 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
878 | sta_info_clear_tim_bit(sta); | 882 | sta_info_clear_tim_bit(sta); |
@@ -885,7 +889,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
885 | 889 | ||
886 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 890 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
887 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " | 891 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
888 | "since STA not sleeping anymore\n", sdata->dev->name, | 892 | "since STA not sleeping anymore\n", sdata->name, |
889 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); | 893 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); |
890 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 894 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
891 | } | 895 | } |
@@ -944,7 +948,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
944 | */ | 948 | */ |
945 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " | 949 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " |
946 | "though there are no buffered frames for it\n", | 950 | "though there are no buffered frames for it\n", |
947 | sdata->dev->name, sta->sta.addr); | 951 | sdata->name, sta->sta.addr); |
948 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 952 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
949 | } | 953 | } |
950 | } | 954 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b4810f6aa94f..c8208236e896 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -403,9 +403,34 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
403 | #define STA_INFO_CLEANUP_INTERVAL (10 * HZ) | 403 | #define STA_INFO_CLEANUP_INTERVAL (10 * HZ) |
404 | 404 | ||
405 | /* | 405 | /* |
406 | * Get a STA info, must have be under RCU read lock. | 406 | * Get a STA info, must be under RCU read lock. |
407 | */ | 407 | */ |
408 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); | 408 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
409 | const u8 *addr); | ||
410 | |||
411 | static inline | ||
412 | void for_each_sta_info_type_check(struct ieee80211_local *local, | ||
413 | const u8 *addr, | ||
414 | struct sta_info *sta, | ||
415 | struct sta_info *nxt) | ||
416 | { | ||
417 | } | ||
418 | |||
419 | #define for_each_sta_info(local, _addr, sta, nxt) \ | ||
420 | for ( /* initialise loop */ \ | ||
421 | sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | ||
422 | nxt = sta ? rcu_dereference(sta->hnext) : NULL; \ | ||
423 | /* typecheck */ \ | ||
424 | for_each_sta_info_type_check(local, (_addr), sta, nxt), \ | ||
425 | /* continue condition */ \ | ||
426 | sta; \ | ||
427 | /* advance loop */ \ | ||
428 | sta = nxt, \ | ||
429 | nxt = sta ? rcu_dereference(sta->hnext) : NULL \ | ||
430 | ) \ | ||
431 | /* compare address and run code only if it matches */ \ | ||
432 | if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0) | ||
433 | |||
409 | /* | 434 | /* |
410 | * Get STA info by index, BROKEN! | 435 | * Get STA info by index, BROKEN! |
411 | */ | 436 | */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index d78f36c64c7b..0c0850d37dda 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -134,6 +134,40 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
134 | dev_kfree_skb(skb); | 134 | dev_kfree_skb(skb); |
135 | } | 135 | } |
136 | 136 | ||
137 | static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) | ||
138 | { | ||
139 | struct ieee80211_mgmt *mgmt = (void *) skb->data; | ||
140 | struct ieee80211_local *local = sta->local; | ||
141 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
142 | |||
143 | if (ieee80211_is_action(mgmt->frame_control) && | ||
144 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
145 | mgmt->u.action.category == WLAN_CATEGORY_HT && | ||
146 | mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { | ||
147 | /* | ||
148 | * This update looks racy, but isn't -- if we come | ||
149 | * here we've definitely got a station that we're | ||
150 | * talking to, and on a managed interface that can | ||
151 | * only be the AP. And the only other place updating | ||
152 | * this variable is before we're associated. | ||
153 | */ | ||
154 | switch (mgmt->u.action.u.ht_smps.smps_control) { | ||
155 | case WLAN_HT_SMPS_CONTROL_DYNAMIC: | ||
156 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
157 | break; | ||
158 | case WLAN_HT_SMPS_CONTROL_STATIC: | ||
159 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; | ||
160 | break; | ||
161 | case WLAN_HT_SMPS_CONTROL_DISABLED: | ||
162 | default: /* shouldn't happen since we don't send that */ | ||
163 | sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | ieee80211_queue_work(&local->hw, &local->recalc_smps); | ||
168 | } | ||
169 | } | ||
170 | |||
137 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 171 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
138 | { | 172 | { |
139 | struct sk_buff *skb2; | 173 | struct sk_buff *skb2; |
@@ -146,7 +180,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
146 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 180 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
147 | struct ieee80211_sub_if_data *sdata; | 181 | struct ieee80211_sub_if_data *sdata; |
148 | struct net_device *prev_dev = NULL; | 182 | struct net_device *prev_dev = NULL; |
149 | struct sta_info *sta; | 183 | struct sta_info *sta, *tmp; |
150 | int retry_count = -1, i; | 184 | int retry_count = -1, i; |
151 | bool injected; | 185 | bool injected; |
152 | 186 | ||
@@ -166,9 +200,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
166 | 200 | ||
167 | sband = local->hw.wiphy->bands[info->band]; | 201 | sband = local->hw.wiphy->bands[info->band]; |
168 | 202 | ||
169 | sta = sta_info_get(local, hdr->addr1); | 203 | for_each_sta_info(local, hdr->addr1, sta, tmp) { |
204 | /* skip wrong virtual interface */ | ||
205 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | ||
206 | continue; | ||
170 | 207 | ||
171 | if (sta) { | ||
172 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 208 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
173 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | 209 | test_sta_flags(sta, WLAN_STA_PS_STA)) { |
174 | /* | 210 | /* |
@@ -208,6 +244,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
208 | rate_control_tx_status(local, sband, sta, skb); | 244 | rate_control_tx_status(local, sband, sta, skb); |
209 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | 245 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) |
210 | ieee80211s_update_metric(local, sta, skb); | 246 | ieee80211s_update_metric(local, sta, skb); |
247 | |||
248 | if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
249 | (info->flags & IEEE80211_TX_STAT_ACK)) | ||
250 | ieee80211_frame_acked(sta, skb); | ||
211 | } | 251 | } |
212 | 252 | ||
213 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 4921d724b6c7..b73454a507f9 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, | |||
100 | p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); | 100 | p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); |
101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; | 101 | p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; |
102 | } | 102 | } |
103 | ctx->initialized = 1; | 103 | ctx->state = TKIP_STATE_PHASE1_DONE; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, | 106 | static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, |
@@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
183 | /* Update the p1k only when the iv16 in the packet wraps around, this | 183 | /* Update the p1k only when the iv16 in the packet wraps around, this |
184 | * might occur after the wrap around of iv16 in the key in case of | 184 | * might occur after the wrap around of iv16 in the key in case of |
185 | * fragmented packets. */ | 185 | * fragmented packets. */ |
186 | if (iv16 == 0 || !ctx->initialized) | 186 | if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) |
187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); | 187 | tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); |
188 | 188 | ||
189 | if (type == IEEE80211_TKIP_P1_KEY) { | 189 | if (type == IEEE80211_TKIP_P1_KEY) { |
@@ -209,7 +209,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
209 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; | 209 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
210 | 210 | ||
211 | /* Calculate per-packet key */ | 211 | /* Calculate per-packet key */ |
212 | if (ctx->iv16 == 0 || !ctx->initialized) | 212 | if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) |
213 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); | 213 | tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); |
214 | 214 | ||
215 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); | 215 | tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); |
@@ -259,7 +259,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
259 | if ((keyid >> 6) != key->conf.keyidx) | 259 | if ((keyid >> 6) != key->conf.keyidx) |
260 | return TKIP_DECRYPT_INVALID_KEYIDX; | 260 | return TKIP_DECRYPT_INVALID_KEYIDX; |
261 | 261 | ||
262 | if (key->u.tkip.rx[queue].initialized && | 262 | if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT && |
263 | (iv32 < key->u.tkip.rx[queue].iv32 || | 263 | (iv32 < key->u.tkip.rx[queue].iv32 || |
264 | (iv32 == key->u.tkip.rx[queue].iv32 && | 264 | (iv32 == key->u.tkip.rx[queue].iv32 && |
265 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 265 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
@@ -275,11 +275,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
275 | 275 | ||
276 | if (only_iv) { | 276 | if (only_iv) { |
277 | res = TKIP_DECRYPT_OK; | 277 | res = TKIP_DECRYPT_OK; |
278 | key->u.tkip.rx[queue].initialized = 1; | 278 | key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; |
279 | goto done; | 279 | goto done; |
280 | } | 280 | } |
281 | 281 | ||
282 | if (!key->u.tkip.rx[queue].initialized || | 282 | if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT || |
283 | key->u.tkip.rx[queue].iv32 != iv32) { | 283 | key->u.tkip.rx[queue].iv32 != iv32) { |
284 | /* IV16 wrapped around - perform TKIP phase 1 */ | 284 | /* IV16 wrapped around - perform TKIP phase 1 */ |
285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); | 285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); |
@@ -299,18 +299,20 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
299 | printk("\n"); | 299 | printk("\n"); |
300 | } | 300 | } |
301 | #endif | 301 | #endif |
302 | if (key->local->ops->update_tkip_key && | 302 | } |
303 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 303 | if (key->local->ops->update_tkip_key && |
304 | static const u8 bcast[ETH_ALEN] = | 304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && |
305 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 305 | key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { |
306 | const u8 *sta_addr = key->sta->sta.addr; | 306 | static const u8 bcast[ETH_ALEN] = |
307 | 307 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
308 | if (is_multicast_ether_addr(ra)) | 308 | const u8 *sta_addr = key->sta->sta.addr; |
309 | sta_addr = bcast; | 309 | |
310 | 310 | if (is_multicast_ether_addr(ra)) | |
311 | drv_update_tkip_key(key->local, &key->conf, sta_addr, | 311 | sta_addr = bcast; |
312 | iv32, key->u.tkip.rx[queue].p1k); | 312 | |
313 | } | 313 | drv_update_tkip_key(key->local, &key->conf, sta_addr, |
314 | iv32, key->u.tkip.rx[queue].p1k); | ||
315 | key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; | ||
314 | } | 316 | } |
315 | 317 | ||
316 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); | 318 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8834cc93c716..ac48c86ae6b3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -223,7 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
223 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 223 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
224 | printk(KERN_DEBUG "%s: dropped data frame to not " | 224 | printk(KERN_DEBUG "%s: dropped data frame to not " |
225 | "associated station %pM\n", | 225 | "associated station %pM\n", |
226 | tx->dev->name, hdr->addr1); | 226 | tx->sdata->name, hdr->addr1); |
227 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 227 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
228 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); | 228 | I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); |
229 | return TX_DROP; | 229 | return TX_DROP; |
@@ -331,7 +331,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
331 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 331 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
332 | if (net_ratelimit()) | 332 | if (net_ratelimit()) |
333 | printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n", | 333 | printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n", |
334 | tx->dev->name); | 334 | tx->sdata->name); |
335 | #endif | 335 | #endif |
336 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); | 336 | dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); |
337 | } else | 337 | } else |
@@ -391,7 +391,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
391 | if (net_ratelimit()) { | 391 | if (net_ratelimit()) { |
392 | printk(KERN_DEBUG "%s: STA %pM TX " | 392 | printk(KERN_DEBUG "%s: STA %pM TX " |
393 | "buffer full - dropping oldest frame\n", | 393 | "buffer full - dropping oldest frame\n", |
394 | tx->dev->name, sta->sta.addr); | 394 | tx->sdata->name, sta->sta.addr); |
395 | } | 395 | } |
396 | #endif | 396 | #endif |
397 | dev_kfree_skb(old); | 397 | dev_kfree_skb(old); |
@@ -416,7 +416,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
416 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 416 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
417 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { | 417 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { |
418 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " | 418 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " |
419 | "set -> send frame\n", tx->dev->name, | 419 | "set -> send frame\n", tx->sdata->name, |
420 | sta->sta.addr); | 420 | sta->sta.addr); |
421 | } | 421 | } |
422 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 422 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
@@ -549,7 +549,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
549 | "%s: Dropped data frame as no usable bitrate found while " | 549 | "%s: Dropped data frame as no usable bitrate found while " |
550 | "scanning and associated. Target station: " | 550 | "scanning and associated. Target station: " |
551 | "%pM on %d GHz band\n", | 551 | "%pM on %d GHz band\n", |
552 | tx->dev->name, hdr->addr1, | 552 | tx->sdata->name, hdr->addr1, |
553 | tx->channel->band ? 5 : 2)) | 553 | tx->channel->band ? 5 : 2)) |
554 | return TX_DROP; | 554 | return TX_DROP; |
555 | 555 | ||
@@ -1021,7 +1021,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1021 | 1021 | ||
1022 | memset(tx, 0, sizeof(*tx)); | 1022 | memset(tx, 0, sizeof(*tx)); |
1023 | tx->skb = skb; | 1023 | tx->skb = skb; |
1024 | tx->dev = sdata->dev; /* use original interface */ | ||
1025 | tx->local = local; | 1024 | tx->local = local; |
1026 | tx->sdata = sdata; | 1025 | tx->sdata = sdata; |
1027 | tx->channel = local->hw.conf.channel; | 1026 | tx->channel = local->hw.conf.channel; |
@@ -1055,7 +1054,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1055 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1054 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1056 | tx->sta = rcu_dereference(sdata->u.vlan.sta); | 1055 | tx->sta = rcu_dereference(sdata->u.vlan.sta); |
1057 | if (!tx->sta) | 1056 | if (!tx->sta) |
1058 | tx->sta = sta_info_get(local, hdr->addr1); | 1057 | tx->sta = sta_info_get(sdata, hdr->addr1); |
1059 | 1058 | ||
1060 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1059 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1061 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1060 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { |
@@ -1474,7 +1473,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1474 | continue; | 1473 | continue; |
1475 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) | 1474 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) |
1476 | continue; | 1475 | continue; |
1477 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, | 1476 | if (compare_ether_addr(tmp_sdata->vif.addr, |
1478 | hdr->addr2) == 0) { | 1477 | hdr->addr2) == 0) { |
1479 | sdata = tmp_sdata; | 1478 | sdata = tmp_sdata; |
1480 | break; | 1479 | break; |
@@ -1638,7 +1637,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1638 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1637 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1639 | /* RA TA DA SA */ | 1638 | /* RA TA DA SA */ |
1640 | memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); | 1639 | memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); |
1641 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1640 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1642 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1641 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1643 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1642 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1644 | hdrlen = 30; | 1643 | hdrlen = 30; |
@@ -1652,7 +1651,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1652 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1651 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1653 | /* DA BSSID SA */ | 1652 | /* DA BSSID SA */ |
1654 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1653 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1655 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1654 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1656 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1655 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1657 | hdrlen = 24; | 1656 | hdrlen = 24; |
1658 | break; | 1657 | break; |
@@ -1660,7 +1659,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1660 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1659 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1661 | /* RA TA DA SA */ | 1660 | /* RA TA DA SA */ |
1662 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1661 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
1663 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1662 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1664 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1663 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1665 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1664 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1666 | hdrlen = 30; | 1665 | hdrlen = 30; |
@@ -1674,8 +1673,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1674 | goto fail; | 1673 | goto fail; |
1675 | } | 1674 | } |
1676 | 1675 | ||
1677 | if (compare_ether_addr(dev->dev_addr, | 1676 | if (compare_ether_addr(sdata->vif.addr, |
1678 | skb->data + ETH_ALEN) == 0) { | 1677 | skb->data + ETH_ALEN) == 0) { |
1679 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1678 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1680 | skb->data, skb->data + ETH_ALEN); | 1679 | skb->data, skb->data + ETH_ALEN); |
1681 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1680 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
@@ -1705,7 +1704,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1705 | } | 1704 | } |
1706 | } | 1705 | } |
1707 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1706 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1708 | mesh_da, dev->dev_addr); | 1707 | mesh_da, sdata->vif.addr); |
1709 | rcu_read_unlock(); | 1708 | rcu_read_unlock(); |
1710 | if (is_mesh_mcast) | 1709 | if (is_mesh_mcast) |
1711 | meshhdrlen = | 1710 | meshhdrlen = |
@@ -1730,7 +1729,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1730 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { | 1729 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { |
1731 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1730 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1732 | /* RA TA DA SA */ | 1731 | /* RA TA DA SA */ |
1733 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1732 | memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); |
1734 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1733 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1735 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1734 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1736 | hdrlen = 30; | 1735 | hdrlen = 30; |
@@ -1761,9 +1760,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1761 | */ | 1760 | */ |
1762 | if (!is_multicast_ether_addr(hdr.addr1)) { | 1761 | if (!is_multicast_ether_addr(hdr.addr1)) { |
1763 | rcu_read_lock(); | 1762 | rcu_read_lock(); |
1764 | sta = sta_info_get(local, hdr.addr1); | 1763 | sta = sta_info_get(sdata, hdr.addr1); |
1765 | /* XXX: in the future, use sdata to look up the sta */ | 1764 | if (sta) |
1766 | if (sta && sta->sdata == sdata) | ||
1767 | sta_flags = get_sta_flags(sta); | 1765 | sta_flags = get_sta_flags(sta); |
1768 | rcu_read_unlock(); | 1766 | rcu_read_unlock(); |
1769 | } | 1767 | } |
@@ -1782,7 +1780,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1782 | unlikely(!is_multicast_ether_addr(hdr.addr1) && | 1780 | unlikely(!is_multicast_ether_addr(hdr.addr1) && |
1783 | !(sta_flags & WLAN_STA_AUTHORIZED) && | 1781 | !(sta_flags & WLAN_STA_AUTHORIZED) && |
1784 | !(ethertype == ETH_P_PAE && | 1782 | !(ethertype == ETH_P_PAE && |
1785 | compare_ether_addr(dev->dev_addr, | 1783 | compare_ether_addr(sdata->vif.addr, |
1786 | skb->data + ETH_ALEN) == 0))) { | 1784 | skb->data + ETH_ALEN) == 0))) { |
1787 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1785 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1788 | if (net_ratelimit()) | 1786 | if (net_ratelimit()) |
@@ -1922,7 +1920,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
1922 | ieee80211_tx(sdata, skb, true); | 1920 | ieee80211_tx(sdata, skb, true); |
1923 | } else { | 1921 | } else { |
1924 | hdr = (struct ieee80211_hdr *)skb->data; | 1922 | hdr = (struct ieee80211_hdr *)skb->data; |
1925 | sta = sta_info_get(local, hdr->addr1); | 1923 | sta = sta_info_get(sdata, hdr->addr1); |
1926 | 1924 | ||
1927 | ret = __ieee80211_tx(local, &skb, sta, true); | 1925 | ret = __ieee80211_tx(local, &skb, sta, true); |
1928 | if (ret != IEEE80211_TX_OK) | 1926 | if (ret != IEEE80211_TX_OK) |
@@ -2146,8 +2144,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2146 | mgmt->frame_control = | 2144 | mgmt->frame_control = |
2147 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 2145 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
2148 | memset(mgmt->da, 0xff, ETH_ALEN); | 2146 | memset(mgmt->da, 0xff, ETH_ALEN); |
2149 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 2147 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
2150 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | 2148 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
2151 | mgmt->u.beacon.beacon_int = | 2149 | mgmt->u.beacon.beacon_int = |
2152 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); | 2150 | cpu_to_le16(sdata->vif.bss_conf.beacon_int); |
2153 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ | 2151 | mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 78a6e924c7e1..b01972579c7c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -469,7 +469,7 @@ void ieee80211_iterate_active_interfaces( | |||
469 | break; | 469 | break; |
470 | } | 470 | } |
471 | if (netif_running(sdata->dev)) | 471 | if (netif_running(sdata->dev)) |
472 | iterator(data, sdata->dev->dev_addr, | 472 | iterator(data, sdata->vif.addr, |
473 | &sdata->vif); | 473 | &sdata->vif); |
474 | } | 474 | } |
475 | 475 | ||
@@ -503,7 +503,7 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
503 | break; | 503 | break; |
504 | } | 504 | } |
505 | if (netif_running(sdata->dev)) | 505 | if (netif_running(sdata->dev)) |
506 | iterator(data, sdata->dev->dev_addr, | 506 | iterator(data, sdata->vif.addr, |
507 | &sdata->vif); | 507 | &sdata->vif); |
508 | } | 508 | } |
509 | 509 | ||
@@ -848,7 +848,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
848 | sizeof(*mgmt) + 6 + extra_len); | 848 | sizeof(*mgmt) + 6 + extra_len); |
849 | if (!skb) { | 849 | if (!skb) { |
850 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 850 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
851 | "frame\n", sdata->dev->name); | 851 | "frame\n", sdata->name); |
852 | return; | 852 | return; |
853 | } | 853 | } |
854 | skb_reserve(skb, local->hw.extra_tx_headroom); | 854 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -858,7 +858,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
858 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 858 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
859 | IEEE80211_STYPE_AUTH); | 859 | IEEE80211_STYPE_AUTH); |
860 | memcpy(mgmt->da, bssid, ETH_ALEN); | 860 | memcpy(mgmt->da, bssid, ETH_ALEN); |
861 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 861 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
862 | memcpy(mgmt->bssid, bssid, ETH_ALEN); | 862 | memcpy(mgmt->bssid, bssid, ETH_ALEN); |
863 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); | 863 | mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); |
864 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); | 864 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); |
@@ -908,16 +908,24 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
908 | } | 908 | } |
909 | 909 | ||
910 | if (sband->ht_cap.ht_supported) { | 910 | if (sband->ht_cap.ht_supported) { |
911 | __le16 tmp = cpu_to_le16(sband->ht_cap.cap); | 911 | u16 cap = sband->ht_cap.cap; |
912 | __le16 tmp; | ||
913 | |||
914 | if (ieee80211_disable_40mhz_24ghz && | ||
915 | sband->band == IEEE80211_BAND_2GHZ) { | ||
916 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
917 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
918 | } | ||
912 | 919 | ||
913 | *pos++ = WLAN_EID_HT_CAPABILITY; | 920 | *pos++ = WLAN_EID_HT_CAPABILITY; |
914 | *pos++ = sizeof(struct ieee80211_ht_cap); | 921 | *pos++ = sizeof(struct ieee80211_ht_cap); |
915 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | 922 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); |
923 | tmp = cpu_to_le16(cap); | ||
916 | memcpy(pos, &tmp, sizeof(u16)); | 924 | memcpy(pos, &tmp, sizeof(u16)); |
917 | pos += sizeof(u16); | 925 | pos += sizeof(u16); |
918 | /* TODO: needs a define here for << 2 */ | ||
919 | *pos++ = sband->ht_cap.ampdu_factor | | 926 | *pos++ = sband->ht_cap.ampdu_factor | |
920 | (sband->ht_cap.ampdu_density << 2); | 927 | (sband->ht_cap.ampdu_density << |
928 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
921 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 929 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
922 | pos += sizeof(sband->ht_cap.mcs); | 930 | pos += sizeof(sband->ht_cap.mcs); |
923 | pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ | 931 | pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ |
@@ -949,7 +957,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
949 | ie_len); | 957 | ie_len); |
950 | if (!skb) { | 958 | if (!skb) { |
951 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | 959 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
952 | "request\n", sdata->dev->name); | 960 | "request\n", sdata->name); |
953 | return; | 961 | return; |
954 | } | 962 | } |
955 | skb_reserve(skb, local->hw.extra_tx_headroom); | 963 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -958,7 +966,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
958 | memset(mgmt, 0, 24); | 966 | memset(mgmt, 0, 24); |
959 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 967 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
960 | IEEE80211_STYPE_PROBE_REQ); | 968 | IEEE80211_STYPE_PROBE_REQ); |
961 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 969 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
962 | if (dst) { | 970 | if (dst) { |
963 | memcpy(mgmt->da, dst, ETH_ALEN); | 971 | memcpy(mgmt->da, dst, ETH_ALEN); |
964 | memcpy(mgmt->bssid, dst, ETH_ALEN); | 972 | memcpy(mgmt->bssid, dst, ETH_ALEN); |
@@ -1051,7 +1059,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1051 | netif_running(sdata->dev)) { | 1059 | netif_running(sdata->dev)) { |
1052 | conf.vif = &sdata->vif; | 1060 | conf.vif = &sdata->vif; |
1053 | conf.type = sdata->vif.type; | 1061 | conf.type = sdata->vif.type; |
1054 | conf.mac_addr = sdata->dev->dev_addr; | 1062 | conf.mac_addr = sdata->vif.addr; |
1055 | res = drv_add_interface(local, &conf); | 1063 | res = drv_add_interface(local, &conf); |
1056 | } | 1064 | } |
1057 | } | 1065 | } |
@@ -1066,7 +1074,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1066 | struct ieee80211_sub_if_data, | 1074 | struct ieee80211_sub_if_data, |
1067 | u.ap); | 1075 | u.ap); |
1068 | 1076 | ||
1069 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, | 1077 | drv_sta_notify(local, sdata, STA_NOTIFY_ADD, |
1070 | &sta->sta); | 1078 | &sta->sta); |
1071 | } | 1079 | } |
1072 | spin_unlock_irqrestore(&local->sta_lock, flags); | 1080 | spin_unlock_irqrestore(&local->sta_lock, flags); |
@@ -1170,3 +1178,77 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1170 | return 0; | 1178 | return 0; |
1171 | } | 1179 | } |
1172 | 1180 | ||
1181 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | ||
1182 | enum ieee80211_smps_mode *smps_mode) | ||
1183 | { | ||
1184 | if (ifmgd->associated) { | ||
1185 | *smps_mode = ifmgd->ap_smps; | ||
1186 | |||
1187 | if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) { | ||
1188 | if (ifmgd->powersave) | ||
1189 | *smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
1190 | else | ||
1191 | *smps_mode = IEEE80211_SMPS_OFF; | ||
1192 | } | ||
1193 | |||
1194 | return 1; | ||
1195 | } | ||
1196 | |||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | /* must hold iflist_mtx */ | ||
1201 | void ieee80211_recalc_smps(struct ieee80211_local *local, | ||
1202 | struct ieee80211_sub_if_data *forsdata) | ||
1203 | { | ||
1204 | struct ieee80211_sub_if_data *sdata; | ||
1205 | enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; | ||
1206 | int count = 0; | ||
1207 | |||
1208 | if (forsdata) | ||
1209 | WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); | ||
1210 | |||
1211 | WARN_ON(!mutex_is_locked(&local->iflist_mtx)); | ||
1212 | |||
1213 | /* | ||
1214 | * This function could be improved to handle multiple | ||
1215 | * interfaces better, but right now it makes any | ||
1216 | * non-station interfaces force SM PS to be turned | ||
1217 | * off. If there are multiple station interfaces it | ||
1218 | * could also use the best possible mode, e.g. if | ||
1219 | * one is in static and the other in dynamic then | ||
1220 | * dynamic is ok. | ||
1221 | */ | ||
1222 | |||
1223 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1224 | if (!netif_running(sdata->dev)) | ||
1225 | continue; | ||
1226 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1227 | goto set; | ||
1228 | if (sdata != forsdata) { | ||
1229 | /* | ||
1230 | * This nested is ok -- we are holding the iflist_mtx | ||
1231 | * so can't get here twice or so. But it's required | ||
1232 | * since normally we acquire it first and then the | ||
1233 | * iflist_mtx. | ||
1234 | */ | ||
1235 | mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); | ||
1236 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1237 | mutex_unlock(&sdata->u.mgd.mtx); | ||
1238 | } else | ||
1239 | count += check_mgd_smps(&sdata->u.mgd, &smps_mode); | ||
1240 | |||
1241 | if (count > 1) { | ||
1242 | smps_mode = IEEE80211_SMPS_OFF; | ||
1243 | break; | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | if (smps_mode == local->smps_mode) | ||
1248 | return; | ||
1249 | |||
1250 | set: | ||
1251 | local->smps_mode = smps_mode; | ||
1252 | /* changed flag is auto-detected for this */ | ||
1253 | ieee80211_hw_config(local, 0); | ||
1254 | } | ||
diff --git a/net/wireless/.gitignore b/net/wireless/.gitignore new file mode 100644 index 000000000000..c33451b896d9 --- /dev/null +++ b/net/wireless/.gitignore | |||
@@ -0,0 +1 @@ | |||
regdb.c | |||
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 90e93a5701aa..8419971f07c5 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -109,6 +109,22 @@ config WIRELESS_OLD_REGULATORY | |||
109 | 109 | ||
110 | Say N and if you say Y, please tell us why. The default is N. | 110 | Say N and if you say Y, please tell us why. The default is N. |
111 | 111 | ||
112 | config CFG80211_INTERNAL_REGDB | ||
113 | bool "use statically compiled regulatory rules database" if EMBEDDED | ||
114 | default n | ||
115 | depends on CFG80211 | ||
116 | ---help--- | ||
117 | This option generates an internal data structure representing | ||
118 | the wireless regulatory rules described in net/wireless/db.txt | ||
119 | and includes code to query that database. This is an alternative | ||
120 | to using CRDA for defining regulatory rules for the kernel. | ||
121 | |||
122 | For details see: | ||
123 | |||
124 | http://wireless.kernel.org/en/developers/Regulatory | ||
125 | |||
126 | Most distributions have a CRDA package. So if unsure, say N. | ||
127 | |||
112 | config CFG80211_WEXT | 128 | config CFG80211_WEXT |
113 | bool "cfg80211 wireless extensions compatibility" | 129 | bool "cfg80211 wireless extensions compatibility" |
114 | depends on CFG80211 | 130 | depends on CFG80211 |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index f07c8dc7aab2..e77e508126fa 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -13,5 +13,11 @@ cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o | |||
13 | cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o | 13 | cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o |
14 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o | 14 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o |
15 | cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o | 15 | cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o |
16 | cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o | ||
16 | 17 | ||
17 | ccflags-y += -D__CHECK_ENDIAN__ | 18 | ccflags-y += -D__CHECK_ENDIAN__ |
19 | |||
20 | $(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk | ||
21 | @$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@ | ||
22 | |||
23 | clean-files := regdb.c | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 4ef3efc94106..35b712127143 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -378,6 +378,8 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev, | |||
378 | struct wireless_dev *for_wdev, | 378 | struct wireless_dev *for_wdev, |
379 | int freq, enum nl80211_channel_type channel_type); | 379 | int freq, enum nl80211_channel_type channel_type); |
380 | 380 | ||
381 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); | ||
382 | |||
381 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 383 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
382 | #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) | 384 | #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) |
383 | #else | 385 | #else |
diff --git a/net/wireless/db.txt b/net/wireless/db.txt new file mode 100644 index 000000000000..a2fc3a09ccdc --- /dev/null +++ b/net/wireless/db.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | # | ||
2 | # This file is a placeholder to prevent accidental build breakage if someone | ||
3 | # enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to | ||
4 | # enable that build option. | ||
5 | # | ||
6 | # You should be using CRDA instead. It is even better if you use the CRDA | ||
7 | # package provided by your distribution, since they will probably keep it | ||
8 | # up-to-date on your behalf. | ||
9 | # | ||
10 | # If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will | ||
11 | # need to replace this file with one containing appropriately formatted | ||
12 | # regulatory rules that cover the regulatory domains you will be using. Your | ||
13 | # best option is to extract the db.txt file from the wireless-regdb git | ||
14 | # repository: | ||
15 | # | ||
16 | # git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git | ||
17 | # | ||
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk new file mode 100644 index 000000000000..8316cf075ce9 --- /dev/null +++ b/net/wireless/genregdb.awk | |||
@@ -0,0 +1,118 @@ | |||
1 | #!/usr/bin/awk -f | ||
2 | # | ||
3 | # genregdb.awk -- generate regdb.c from db.txt | ||
4 | # | ||
5 | # Actually, it reads from stdin (presumed to be db.txt) and writes | ||
6 | # to stdout (presumed to be regdb.c), but close enough... | ||
7 | # | ||
8 | # Copyright 2009 John W. Linville <linville@tuxdriver.com> | ||
9 | # | ||
10 | # This program is free software; you can redistribute it and/or modify | ||
11 | # it under the terms of the GNU General Public License version 2 as | ||
12 | # published by the Free Software Foundation. | ||
13 | # | ||
14 | |||
15 | BEGIN { | ||
16 | active = 0 | ||
17 | rules = 0; | ||
18 | print "/*" | ||
19 | print " * DO NOT EDIT -- file generated from data in db.txt" | ||
20 | print " */" | ||
21 | print "" | ||
22 | print "#include <linux/nl80211.h>" | ||
23 | print "#include <net/cfg80211.h>" | ||
24 | print "" | ||
25 | regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" | ||
26 | } | ||
27 | |||
28 | /^[ \t]*#/ { | ||
29 | /* Ignore */ | ||
30 | } | ||
31 | |||
32 | !active && /^[ \t]*$/ { | ||
33 | /* Ignore */ | ||
34 | } | ||
35 | |||
36 | !active && /country/ { | ||
37 | country=$2 | ||
38 | sub(/:/, "", country) | ||
39 | printf "static const struct ieee80211_regdomain regdom_%s = {\n", country | ||
40 | printf "\t.alpha2 = \"%s\",\n", country | ||
41 | printf "\t.reg_rules = {\n" | ||
42 | active = 1 | ||
43 | regdb = regdb "\t®dom_" country ",\n" | ||
44 | } | ||
45 | |||
46 | active && /^[ \t]*\(/ { | ||
47 | start = $1 | ||
48 | sub(/\(/, "", start) | ||
49 | end = $3 | ||
50 | bw = $5 | ||
51 | sub(/\),/, "", bw) | ||
52 | gain = $6 | ||
53 | sub(/\(/, "", gain) | ||
54 | sub(/,/, "", gain) | ||
55 | power = $7 | ||
56 | sub(/\)/, "", power) | ||
57 | sub(/,/, "", power) | ||
58 | # power might be in mW... | ||
59 | units = $8 | ||
60 | sub(/\)/, "", units) | ||
61 | sub(/,/, "", units) | ||
62 | if (units == "mW") { | ||
63 | if (power == 100) { | ||
64 | power = 20 | ||
65 | } else if (power == 200) { | ||
66 | power = 23 | ||
67 | } else if (power == 500) { | ||
68 | power = 27 | ||
69 | } else if (power == 1000) { | ||
70 | power = 30 | ||
71 | } else { | ||
72 | print "Unknown power value in database!" | ||
73 | } | ||
74 | } | ||
75 | flagstr = "" | ||
76 | for (i=8; i<=NF; i++) | ||
77 | flagstr = flagstr $i | ||
78 | split(flagstr, flagarray, ",") | ||
79 | flags = "" | ||
80 | for (arg in flagarray) { | ||
81 | if (flagarray[arg] == "NO-OFDM") { | ||
82 | flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | " | ||
83 | } else if (flagarray[arg] == "NO-CCK") { | ||
84 | flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | " | ||
85 | } else if (flagarray[arg] == "NO-INDOOR") { | ||
86 | flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | " | ||
87 | } else if (flagarray[arg] == "NO-OUTDOOR") { | ||
88 | flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | " | ||
89 | } else if (flagarray[arg] == "DFS") { | ||
90 | flags = flags "\n\t\t\tNL80211_RRF_DFS | " | ||
91 | } else if (flagarray[arg] == "PTP-ONLY") { | ||
92 | flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | " | ||
93 | } else if (flagarray[arg] == "PTMP-ONLY") { | ||
94 | flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " | ||
95 | } else if (flagarray[arg] == "PASSIVE-SCAN") { | ||
96 | flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " | ||
97 | } else if (flagarray[arg] == "NO-IBSS") { | ||
98 | flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " | ||
99 | } | ||
100 | } | ||
101 | flags = flags "0" | ||
102 | printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags | ||
103 | rules++ | ||
104 | } | ||
105 | |||
106 | active && /^[ \t]*$/ { | ||
107 | active = 0 | ||
108 | printf "\t},\n" | ||
109 | printf "\t.n_reg_rules = %d\n", rules | ||
110 | printf "};\n\n" | ||
111 | rules = 0; | ||
112 | } | ||
113 | |||
114 | END { | ||
115 | print regdb "};" | ||
116 | print "" | ||
117 | print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" | ||
118 | } | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1001db4912f7..acaeaa784d68 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -137,22 +137,23 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
137 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 137 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
138 | const u8 *bssid = mgmt->bssid; | 138 | const u8 *bssid = mgmt->bssid; |
139 | int i; | 139 | int i; |
140 | bool found = false; | ||
140 | 141 | ||
141 | ASSERT_WDEV_LOCK(wdev); | 142 | ASSERT_WDEV_LOCK(wdev); |
142 | 143 | ||
143 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | ||
144 | |||
145 | if (wdev->current_bss && | 144 | if (wdev->current_bss && |
146 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 145 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { |
147 | cfg80211_unhold_bss(wdev->current_bss); | 146 | cfg80211_unhold_bss(wdev->current_bss); |
148 | cfg80211_put_bss(&wdev->current_bss->pub); | 147 | cfg80211_put_bss(&wdev->current_bss->pub); |
149 | wdev->current_bss = NULL; | 148 | wdev->current_bss = NULL; |
149 | found = true; | ||
150 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { | 150 | } else for (i = 0; i < MAX_AUTH_BSSES; i++) { |
151 | if (wdev->auth_bsses[i] && | 151 | if (wdev->auth_bsses[i] && |
152 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { | 152 | memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { |
153 | cfg80211_unhold_bss(wdev->auth_bsses[i]); | 153 | cfg80211_unhold_bss(wdev->auth_bsses[i]); |
154 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); | 154 | cfg80211_put_bss(&wdev->auth_bsses[i]->pub); |
155 | wdev->auth_bsses[i] = NULL; | 155 | wdev->auth_bsses[i] = NULL; |
156 | found = true; | ||
156 | break; | 157 | break; |
157 | } | 158 | } |
158 | if (wdev->authtry_bsses[i] && | 159 | if (wdev->authtry_bsses[i] && |
@@ -160,10 +161,16 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
160 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); | 161 | cfg80211_unhold_bss(wdev->authtry_bsses[i]); |
161 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); | 162 | cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); |
162 | wdev->authtry_bsses[i] = NULL; | 163 | wdev->authtry_bsses[i] = NULL; |
164 | found = true; | ||
163 | break; | 165 | break; |
164 | } | 166 | } |
165 | } | 167 | } |
166 | 168 | ||
169 | if (!found) | ||
170 | return; | ||
171 | |||
172 | nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); | ||
173 | |||
167 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { | 174 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { |
168 | u16 reason_code; | 175 | u16 reason_code; |
169 | bool from_ap; | 176 | bool from_ap; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a6028433e3a0..7cb0d647fc34 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1637,39 +1637,6 @@ static int parse_station_flags(struct genl_info *info, | |||
1637 | return 0; | 1637 | return 0; |
1638 | } | 1638 | } |
1639 | 1639 | ||
1640 | static u16 nl80211_calculate_bitrate(struct rate_info *rate) | ||
1641 | { | ||
1642 | int modulation, streams, bitrate; | ||
1643 | |||
1644 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) | ||
1645 | return rate->legacy; | ||
1646 | |||
1647 | /* the formula below does only work for MCS values smaller than 32 */ | ||
1648 | if (rate->mcs >= 32) | ||
1649 | return 0; | ||
1650 | |||
1651 | modulation = rate->mcs & 7; | ||
1652 | streams = (rate->mcs >> 3) + 1; | ||
1653 | |||
1654 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? | ||
1655 | 13500000 : 6500000; | ||
1656 | |||
1657 | if (modulation < 4) | ||
1658 | bitrate *= (modulation + 1); | ||
1659 | else if (modulation == 4) | ||
1660 | bitrate *= (modulation + 2); | ||
1661 | else | ||
1662 | bitrate *= (modulation + 3); | ||
1663 | |||
1664 | bitrate *= streams; | ||
1665 | |||
1666 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
1667 | bitrate = (bitrate / 9) * 10; | ||
1668 | |||
1669 | /* do NOT round down here */ | ||
1670 | return (bitrate + 50000) / 100000; | ||
1671 | } | ||
1672 | |||
1673 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 1640 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
1674 | int flags, struct net_device *dev, | 1641 | int flags, struct net_device *dev, |
1675 | u8 *mac_addr, struct station_info *sinfo) | 1642 | u8 *mac_addr, struct station_info *sinfo) |
@@ -1716,8 +1683,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
1716 | if (!txrate) | 1683 | if (!txrate) |
1717 | goto nla_put_failure; | 1684 | goto nla_put_failure; |
1718 | 1685 | ||
1719 | /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */ | 1686 | /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ |
1720 | bitrate = nl80211_calculate_bitrate(&sinfo->txrate); | 1687 | bitrate = cfg80211_calculate_bitrate(&sinfo->txrate); |
1721 | if (bitrate > 0) | 1688 | if (bitrate > 0) |
1722 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); | 1689 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); |
1723 | 1690 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index baa898add287..dc13c3ffeca6 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <net/cfg80211.h> | 40 | #include <net/cfg80211.h> |
41 | #include "core.h" | 41 | #include "core.h" |
42 | #include "reg.h" | 42 | #include "reg.h" |
43 | #include "regdb.h" | ||
43 | #include "nl80211.h" | 44 | #include "nl80211.h" |
44 | 45 | ||
45 | /* Receipt of information from last regulatory request */ | 46 | /* Receipt of information from last regulatory request */ |
@@ -335,6 +336,98 @@ static bool country_ie_integrity_changes(u32 checksum) | |||
335 | return false; | 336 | return false; |
336 | } | 337 | } |
337 | 338 | ||
339 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | ||
340 | const struct ieee80211_regdomain *src_regd) | ||
341 | { | ||
342 | struct ieee80211_regdomain *regd; | ||
343 | int size_of_regd = 0; | ||
344 | unsigned int i; | ||
345 | |||
346 | size_of_regd = sizeof(struct ieee80211_regdomain) + | ||
347 | ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); | ||
348 | |||
349 | regd = kzalloc(size_of_regd, GFP_KERNEL); | ||
350 | if (!regd) | ||
351 | return -ENOMEM; | ||
352 | |||
353 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); | ||
354 | |||
355 | for (i = 0; i < src_regd->n_reg_rules; i++) | ||
356 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], | ||
357 | sizeof(struct ieee80211_reg_rule)); | ||
358 | |||
359 | *dst_regd = regd; | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | #ifdef CONFIG_CFG80211_INTERNAL_REGDB | ||
364 | struct reg_regdb_search_request { | ||
365 | char alpha2[2]; | ||
366 | struct list_head list; | ||
367 | }; | ||
368 | |||
369 | static LIST_HEAD(reg_regdb_search_list); | ||
370 | static DEFINE_SPINLOCK(reg_regdb_search_lock); | ||
371 | |||
372 | static void reg_regdb_search(struct work_struct *work) | ||
373 | { | ||
374 | struct reg_regdb_search_request *request; | ||
375 | const struct ieee80211_regdomain *curdom, *regdom; | ||
376 | int i, r; | ||
377 | |||
378 | spin_lock(®_regdb_search_lock); | ||
379 | while (!list_empty(®_regdb_search_list)) { | ||
380 | request = list_first_entry(®_regdb_search_list, | ||
381 | struct reg_regdb_search_request, | ||
382 | list); | ||
383 | list_del(&request->list); | ||
384 | |||
385 | for (i=0; i<reg_regdb_size; i++) { | ||
386 | curdom = reg_regdb[i]; | ||
387 | |||
388 | if (!memcmp(request->alpha2, curdom->alpha2, 2)) { | ||
389 | r = reg_copy_regd(®dom, curdom); | ||
390 | if (r) | ||
391 | break; | ||
392 | spin_unlock(®_regdb_search_lock); | ||
393 | mutex_lock(&cfg80211_mutex); | ||
394 | set_regdom(regdom); | ||
395 | mutex_unlock(&cfg80211_mutex); | ||
396 | spin_lock(®_regdb_search_lock); | ||
397 | break; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | kfree(request); | ||
402 | } | ||
403 | spin_unlock(®_regdb_search_lock); | ||
404 | } | ||
405 | |||
406 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); | ||
407 | |||
408 | static void reg_regdb_query(const char *alpha2) | ||
409 | { | ||
410 | struct reg_regdb_search_request *request; | ||
411 | |||
412 | if (!alpha2) | ||
413 | return; | ||
414 | |||
415 | request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL); | ||
416 | if (!request) | ||
417 | return; | ||
418 | |||
419 | memcpy(request->alpha2, alpha2, 2); | ||
420 | |||
421 | spin_lock(®_regdb_search_lock); | ||
422 | list_add_tail(&request->list, ®_regdb_search_list); | ||
423 | spin_unlock(®_regdb_search_lock); | ||
424 | |||
425 | schedule_work(®_regdb_work); | ||
426 | } | ||
427 | #else | ||
428 | static inline void reg_regdb_query(const char *alpha2) {} | ||
429 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ | ||
430 | |||
338 | /* | 431 | /* |
339 | * This lets us keep regulatory code which is updated on a regulatory | 432 | * This lets us keep regulatory code which is updated on a regulatory |
340 | * basis in userspace. | 433 | * basis in userspace. |
@@ -354,6 +447,9 @@ static int call_crda(const char *alpha2) | |||
354 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " | 447 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " |
355 | "regulatory domain\n"); | 448 | "regulatory domain\n"); |
356 | 449 | ||
450 | /* query internal regulatory database (if it exists) */ | ||
451 | reg_regdb_query(alpha2); | ||
452 | |||
357 | country_env[8] = alpha2[0]; | 453 | country_env[8] = alpha2[0]; |
358 | country_env[9] = alpha2[1]; | 454 | country_env[9] = alpha2[1]; |
359 | 455 | ||
@@ -1342,30 +1438,6 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | |||
1342 | } | 1438 | } |
1343 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); | 1439 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); |
1344 | 1440 | ||
1345 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | ||
1346 | const struct ieee80211_regdomain *src_regd) | ||
1347 | { | ||
1348 | struct ieee80211_regdomain *regd; | ||
1349 | int size_of_regd = 0; | ||
1350 | unsigned int i; | ||
1351 | |||
1352 | size_of_regd = sizeof(struct ieee80211_regdomain) + | ||
1353 | ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); | ||
1354 | |||
1355 | regd = kzalloc(size_of_regd, GFP_KERNEL); | ||
1356 | if (!regd) | ||
1357 | return -ENOMEM; | ||
1358 | |||
1359 | memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); | ||
1360 | |||
1361 | for (i = 0; i < src_regd->n_reg_rules; i++) | ||
1362 | memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], | ||
1363 | sizeof(struct ieee80211_reg_rule)); | ||
1364 | |||
1365 | *dst_regd = regd; | ||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | /* | 1441 | /* |
1370 | * Return value which can be used by ignore_request() to indicate | 1442 | * Return value which can be used by ignore_request() to indicate |
1371 | * it has been determined we should intersect two regulatory domains | 1443 | * it has been determined we should intersect two regulatory domains |
diff --git a/net/wireless/regdb.h b/net/wireless/regdb.h new file mode 100644 index 000000000000..818222c92513 --- /dev/null +++ b/net/wireless/regdb.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __REGDB_H__ | ||
2 | #define __REGDB_H__ | ||
3 | |||
4 | extern const struct ieee80211_regdomain *reg_regdb[]; | ||
5 | extern int reg_regdb_size; | ||
6 | |||
7 | #endif /* __REGDB_H__ */ | ||
diff --git a/net/wireless/util.c b/net/wireless/util.c index 59361fdcb5d0..23557c1d0a9c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -285,7 +285,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | |||
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
288 | int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, | 288 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
289 | enum nl80211_iftype iftype) | 289 | enum nl80211_iftype iftype) |
290 | { | 290 | { |
291 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 291 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -383,7 +383,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, | |||
383 | } | 383 | } |
384 | EXPORT_SYMBOL(ieee80211_data_to_8023); | 384 | EXPORT_SYMBOL(ieee80211_data_to_8023); |
385 | 385 | ||
386 | int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, | 386 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
387 | enum nl80211_iftype iftype, u8 *bssid, bool qos) | 387 | enum nl80211_iftype iftype, u8 *bssid, bool qos) |
388 | { | 388 | { |
389 | struct ieee80211_hdr hdr; | 389 | struct ieee80211_hdr hdr; |
@@ -497,6 +497,101 @@ int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, | |||
497 | } | 497 | } |
498 | EXPORT_SYMBOL(ieee80211_data_from_8023); | 498 | EXPORT_SYMBOL(ieee80211_data_from_8023); |
499 | 499 | ||
500 | |||
501 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | ||
502 | const u8 *addr, enum nl80211_iftype iftype, | ||
503 | const unsigned int extra_headroom) | ||
504 | { | ||
505 | struct sk_buff *frame = NULL; | ||
506 | u16 ethertype; | ||
507 | u8 *payload; | ||
508 | const struct ethhdr *eth; | ||
509 | int remaining, err; | ||
510 | u8 dst[ETH_ALEN], src[ETH_ALEN]; | ||
511 | |||
512 | err = ieee80211_data_to_8023(skb, addr, iftype); | ||
513 | if (err) | ||
514 | goto out; | ||
515 | |||
516 | /* skip the wrapping header */ | ||
517 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); | ||
518 | if (!eth) | ||
519 | goto out; | ||
520 | |||
521 | while (skb != frame) { | ||
522 | u8 padding; | ||
523 | __be16 len = eth->h_proto; | ||
524 | unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); | ||
525 | |||
526 | remaining = skb->len; | ||
527 | memcpy(dst, eth->h_dest, ETH_ALEN); | ||
528 | memcpy(src, eth->h_source, ETH_ALEN); | ||
529 | |||
530 | padding = (4 - subframe_len) & 0x3; | ||
531 | /* the last MSDU has no padding */ | ||
532 | if (subframe_len > remaining) | ||
533 | goto purge; | ||
534 | |||
535 | skb_pull(skb, sizeof(struct ethhdr)); | ||
536 | /* reuse skb for the last subframe */ | ||
537 | if (remaining <= subframe_len + padding) | ||
538 | frame = skb; | ||
539 | else { | ||
540 | unsigned int hlen = ALIGN(extra_headroom, 4); | ||
541 | /* | ||
542 | * Allocate and reserve two bytes more for payload | ||
543 | * alignment since sizeof(struct ethhdr) is 14. | ||
544 | */ | ||
545 | frame = dev_alloc_skb(hlen + subframe_len + 2); | ||
546 | if (!frame) | ||
547 | goto purge; | ||
548 | |||
549 | skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2); | ||
550 | memcpy(skb_put(frame, ntohs(len)), skb->data, | ||
551 | ntohs(len)); | ||
552 | |||
553 | eth = (struct ethhdr *)skb_pull(skb, ntohs(len) + | ||
554 | padding); | ||
555 | if (!eth) { | ||
556 | dev_kfree_skb(frame); | ||
557 | goto purge; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | skb_reset_network_header(frame); | ||
562 | frame->dev = skb->dev; | ||
563 | frame->priority = skb->priority; | ||
564 | |||
565 | payload = frame->data; | ||
566 | ethertype = (payload[6] << 8) | payload[7]; | ||
567 | |||
568 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | ||
569 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | ||
570 | compare_ether_addr(payload, | ||
571 | bridge_tunnel_header) == 0)) { | ||
572 | /* remove RFC1042 or Bridge-Tunnel | ||
573 | * encapsulation and replace EtherType */ | ||
574 | skb_pull(frame, 6); | ||
575 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
576 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
577 | } else { | ||
578 | memcpy(skb_push(frame, sizeof(__be16)), &len, | ||
579 | sizeof(__be16)); | ||
580 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | ||
581 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | ||
582 | } | ||
583 | __skb_queue_tail(list, frame); | ||
584 | } | ||
585 | |||
586 | return; | ||
587 | |||
588 | purge: | ||
589 | __skb_queue_purge(list); | ||
590 | out: | ||
591 | dev_kfree_skb(skb); | ||
592 | } | ||
593 | EXPORT_SYMBOL(ieee80211_amsdu_to_8023s); | ||
594 | |||
500 | /* Given a data frame determine the 802.1p/1d tag to use. */ | 595 | /* Given a data frame determine the 802.1p/1d tag to use. */ |
501 | unsigned int cfg80211_classify8021d(struct sk_buff *skb) | 596 | unsigned int cfg80211_classify8021d(struct sk_buff *skb) |
502 | { | 597 | { |
@@ -720,3 +815,36 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
720 | 815 | ||
721 | return err; | 816 | return err; |
722 | } | 817 | } |
818 | |||
819 | u16 cfg80211_calculate_bitrate(struct rate_info *rate) | ||
820 | { | ||
821 | int modulation, streams, bitrate; | ||
822 | |||
823 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) | ||
824 | return rate->legacy; | ||
825 | |||
826 | /* the formula below does only work for MCS values smaller than 32 */ | ||
827 | if (rate->mcs >= 32) | ||
828 | return 0; | ||
829 | |||
830 | modulation = rate->mcs & 7; | ||
831 | streams = (rate->mcs >> 3) + 1; | ||
832 | |||
833 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? | ||
834 | 13500000 : 6500000; | ||
835 | |||
836 | if (modulation < 4) | ||
837 | bitrate *= (modulation + 1); | ||
838 | else if (modulation == 4) | ||
839 | bitrate *= (modulation + 2); | ||
840 | else | ||
841 | bitrate *= (modulation + 3); | ||
842 | |||
843 | bitrate *= streams; | ||
844 | |||
845 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
846 | bitrate = (bitrate / 9) * 10; | ||
847 | |||
848 | /* do NOT round down here */ | ||
849 | return (bitrate + 50000) / 100000; | ||
850 | } | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 54face3d4424..4198243a3dff 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1257,10 +1257,7 @@ int cfg80211_wext_giwrate(struct net_device *dev, | |||
1257 | if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) | 1257 | if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) |
1258 | return -EOPNOTSUPP; | 1258 | return -EOPNOTSUPP; |
1259 | 1259 | ||
1260 | rate->value = 0; | 1260 | rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); |
1261 | |||
1262 | if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS)) | ||
1263 | rate->value = 100000 * sinfo.txrate.legacy; | ||
1264 | 1261 | ||
1265 | return 0; | 1262 | return 0; |
1266 | } | 1263 | } |