diff options
Diffstat (limited to 'drivers/net')
109 files changed, 3199 insertions, 1892 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 39410016b4ff..e1f04bb437e3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1400,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, | |||
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | static int adm8211_add_interface(struct ieee80211_hw *dev, | 1402 | static int adm8211_add_interface(struct ieee80211_hw *dev, |
1403 | struct ieee80211_if_init_conf *conf) | 1403 | struct ieee80211_vif *vif) |
1404 | { | 1404 | { |
1405 | struct adm8211_priv *priv = dev->priv; | 1405 | struct adm8211_priv *priv = dev->priv; |
1406 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1406 | if (priv->mode != NL80211_IFTYPE_MONITOR) |
1407 | return -EOPNOTSUPP; | 1407 | return -EOPNOTSUPP; |
1408 | 1408 | ||
1409 | switch (conf->type) { | 1409 | switch (vif->type) { |
1410 | case NL80211_IFTYPE_STATION: | 1410 | case NL80211_IFTYPE_STATION: |
1411 | priv->mode = conf->type; | 1411 | priv->mode = vif->type; |
1412 | break; | 1412 | break; |
1413 | default: | 1413 | default: |
1414 | return -EOPNOTSUPP; | 1414 | return -EOPNOTSUPP; |
@@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1416 | 1416 | ||
1417 | ADM8211_IDLE(); | 1417 | ADM8211_IDLE(); |
1418 | 1418 | ||
1419 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); | 1419 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); |
1420 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 1420 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
1421 | 1421 | ||
1422 | adm8211_update_mode(dev); | 1422 | adm8211_update_mode(dev); |
1423 | 1423 | ||
@@ -1427,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1427 | } | 1427 | } |
1428 | 1428 | ||
1429 | static void adm8211_remove_interface(struct ieee80211_hw *dev, | 1429 | static void adm8211_remove_interface(struct ieee80211_hw *dev, |
1430 | struct ieee80211_if_init_conf *conf) | 1430 | struct ieee80211_vif *vif) |
1431 | { | 1431 | { |
1432 | struct adm8211_priv *priv = dev->priv; | 1432 | struct adm8211_priv *priv = dev->priv; |
1433 | priv->mode = NL80211_IFTYPE_MONITOR; | 1433 | priv->mode = NL80211_IFTYPE_MONITOR; |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 2517364d3ebe..0fb419936dff 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) | |||
1789 | } | 1789 | } |
1790 | 1790 | ||
1791 | static int at76_add_interface(struct ieee80211_hw *hw, | 1791 | static int at76_add_interface(struct ieee80211_hw *hw, |
1792 | struct ieee80211_if_init_conf *conf) | 1792 | struct ieee80211_vif *vif) |
1793 | { | 1793 | { |
1794 | struct at76_priv *priv = hw->priv; | 1794 | struct at76_priv *priv = hw->priv; |
1795 | int ret = 0; | 1795 | int ret = 0; |
@@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw, | |||
1798 | 1798 | ||
1799 | mutex_lock(&priv->mtx); | 1799 | mutex_lock(&priv->mtx); |
1800 | 1800 | ||
1801 | switch (conf->type) { | 1801 | switch (vif->type) { |
1802 | case NL80211_IFTYPE_STATION: | 1802 | case NL80211_IFTYPE_STATION: |
1803 | priv->iw_mode = IW_MODE_INFRA; | 1803 | priv->iw_mode = IW_MODE_INFRA; |
1804 | break; | 1804 | break; |
@@ -1814,7 +1814,7 @@ exit: | |||
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | static void at76_remove_interface(struct ieee80211_hw *hw, | 1816 | static void at76_remove_interface(struct ieee80211_hw *hw, |
1817 | struct ieee80211_if_init_conf *conf) | 1817 | struct ieee80211_vif *vif) |
1818 | { | 1818 | { |
1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
1820 | } | 1820 | } |
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..4d27f7f67c76 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++; |
@@ -1950,7 +1939,7 @@ err_free: | |||
1950 | } | 1939 | } |
1951 | 1940 | ||
1952 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | 1941 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, |
1953 | struct ieee80211_if_init_conf *conf) | 1942 | struct ieee80211_vif *vif) |
1954 | { | 1943 | { |
1955 | struct ar9170 *ar = hw->priv; | 1944 | struct ar9170 *ar = hw->priv; |
1956 | struct ath_common *common = &ar->common; | 1945 | struct ath_common *common = &ar->common; |
@@ -1963,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1963 | goto unlock; | 1952 | goto unlock; |
1964 | } | 1953 | } |
1965 | 1954 | ||
1966 | ar->vif = conf->vif; | 1955 | ar->vif = vif; |
1967 | memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); | 1956 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1968 | 1957 | ||
1969 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1958 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1970 | ar->rx_software_decryption = true; | 1959 | ar->rx_software_decryption = true; |
@@ -1984,7 +1973,7 @@ unlock: | |||
1984 | } | 1973 | } |
1985 | 1974 | ||
1986 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | 1975 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, |
1987 | struct ieee80211_if_init_conf *conf) | 1976 | struct ieee80211_vif *vif) |
1988 | { | 1977 | { |
1989 | struct ar9170 *ar = hw->priv; | 1978 | struct ar9170 *ar = hw->priv; |
1990 | 1979 | ||
@@ -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/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index e63b7c40d0ee..fdfaf0f618f1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); | |||
225 | static int ath5k_start(struct ieee80211_hw *hw); | 225 | static int ath5k_start(struct ieee80211_hw *hw); |
226 | static void ath5k_stop(struct ieee80211_hw *hw); | 226 | static void ath5k_stop(struct ieee80211_hw *hw); |
227 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 227 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
228 | struct ieee80211_if_init_conf *conf); | 228 | struct ieee80211_vif *vif); |
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 230 | struct ieee80211_vif *vif); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
233 | int mc_count, struct dev_addr_list *mc_list); | 233 | int mc_count, struct dev_addr_list *mc_list); |
@@ -2773,7 +2773,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) | |||
2773 | } | 2773 | } |
2774 | 2774 | ||
2775 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2775 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
2776 | struct ieee80211_if_init_conf *conf) | 2776 | struct ieee80211_vif *vif) |
2777 | { | 2777 | { |
2778 | struct ath5k_softc *sc = hw->priv; | 2778 | struct ath5k_softc *sc = hw->priv; |
2779 | int ret; | 2779 | int ret; |
@@ -2784,22 +2784,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2784 | goto end; | 2784 | goto end; |
2785 | } | 2785 | } |
2786 | 2786 | ||
2787 | sc->vif = conf->vif; | 2787 | sc->vif = vif; |
2788 | 2788 | ||
2789 | switch (conf->type) { | 2789 | switch (vif->type) { |
2790 | case NL80211_IFTYPE_AP: | 2790 | case NL80211_IFTYPE_AP: |
2791 | case NL80211_IFTYPE_STATION: | 2791 | case NL80211_IFTYPE_STATION: |
2792 | case NL80211_IFTYPE_ADHOC: | 2792 | case NL80211_IFTYPE_ADHOC: |
2793 | case NL80211_IFTYPE_MESH_POINT: | 2793 | case NL80211_IFTYPE_MESH_POINT: |
2794 | case NL80211_IFTYPE_MONITOR: | 2794 | case NL80211_IFTYPE_MONITOR: |
2795 | sc->opmode = conf->type; | 2795 | sc->opmode = vif->type; |
2796 | break; | 2796 | break; |
2797 | default: | 2797 | default: |
2798 | ret = -EOPNOTSUPP; | 2798 | ret = -EOPNOTSUPP; |
2799 | goto end; | 2799 | goto end; |
2800 | } | 2800 | } |
2801 | 2801 | ||
2802 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2802 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2803 | ath5k_mode_setup(sc); | 2803 | ath5k_mode_setup(sc); |
2804 | 2804 | ||
2805 | ret = 0; | 2805 | ret = 0; |
@@ -2810,13 +2810,13 @@ end: | |||
2810 | 2810 | ||
2811 | static void | 2811 | static void |
2812 | ath5k_remove_interface(struct ieee80211_hw *hw, | 2812 | ath5k_remove_interface(struct ieee80211_hw *hw, |
2813 | struct ieee80211_if_init_conf *conf) | 2813 | struct ieee80211_vif *vif) |
2814 | { | 2814 | { |
2815 | struct ath5k_softc *sc = hw->priv; | 2815 | struct ath5k_softc *sc = hw->priv; |
2816 | u8 mac[ETH_ALEN] = {}; | 2816 | u8 mac[ETH_ALEN] = {}; |
2817 | 2817 | ||
2818 | mutex_lock(&sc->lock); | 2818 | mutex_lock(&sc->lock); |
2819 | if (sc->vif != conf->vif) | 2819 | if (sc->vif != vif) |
2820 | goto end; | 2820 | goto end; |
2821 | 2821 | ||
2822 | ath5k_hw_set_lladdr(sc->ah, mac); | 2822 | ath5k_hw_set_lladdr(sc->ah, mac); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1597a42731ed..9efebac5ed0e 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 996eb90263cc..79fbbda15493 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); |
@@ -2550,12 +2540,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2550 | } | 2540 | } |
2551 | 2541 | ||
2552 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 2542 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
2553 | struct ieee80211_if_init_conf *conf) | 2543 | struct ieee80211_vif *vif) |
2554 | { | 2544 | { |
2555 | struct ath_wiphy *aphy = hw->priv; | 2545 | struct ath_wiphy *aphy = hw->priv; |
2556 | struct ath_softc *sc = aphy->sc; | 2546 | struct ath_softc *sc = aphy->sc; |
2557 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2547 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2558 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2548 | struct ath_vif *avp = (void *)vif->drv_priv; |
2559 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 2549 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
2560 | int ret = 0; | 2550 | int ret = 0; |
2561 | 2551 | ||
@@ -2567,7 +2557,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2567 | goto out; | 2557 | goto out; |
2568 | } | 2558 | } |
2569 | 2559 | ||
2570 | switch (conf->type) { | 2560 | switch (vif->type) { |
2571 | case NL80211_IFTYPE_STATION: | 2561 | case NL80211_IFTYPE_STATION: |
2572 | ic_opmode = NL80211_IFTYPE_STATION; | 2562 | ic_opmode = NL80211_IFTYPE_STATION; |
2573 | break; | 2563 | break; |
@@ -2578,11 +2568,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2578 | ret = -ENOBUFS; | 2568 | ret = -ENOBUFS; |
2579 | goto out; | 2569 | goto out; |
2580 | } | 2570 | } |
2581 | ic_opmode = conf->type; | 2571 | ic_opmode = vif->type; |
2582 | break; | 2572 | break; |
2583 | default: | 2573 | default: |
2584 | ath_print(common, ATH_DBG_FATAL, | 2574 | ath_print(common, ATH_DBG_FATAL, |
2585 | "Interface type %d not yet supported\n", conf->type); | 2575 | "Interface type %d not yet supported\n", vif->type); |
2586 | ret = -EOPNOTSUPP; | 2576 | ret = -EOPNOTSUPP; |
2587 | goto out; | 2577 | goto out; |
2588 | } | 2578 | } |
@@ -2614,18 +2604,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2614 | * Enable MIB interrupts when there are hardware phy counters. | 2604 | * Enable MIB interrupts when there are hardware phy counters. |
2615 | * Note we only do this (at the moment) for station mode. | 2605 | * Note we only do this (at the moment) for station mode. |
2616 | */ | 2606 | */ |
2617 | if ((conf->type == NL80211_IFTYPE_STATION) || | 2607 | if ((vif->type == NL80211_IFTYPE_STATION) || |
2618 | (conf->type == NL80211_IFTYPE_ADHOC) || | 2608 | (vif->type == NL80211_IFTYPE_ADHOC) || |
2619 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { | 2609 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
2620 | sc->imask |= ATH9K_INT_MIB; | 2610 | sc->imask |= ATH9K_INT_MIB; |
2621 | sc->imask |= ATH9K_INT_TSFOOR; | 2611 | sc->imask |= ATH9K_INT_TSFOOR; |
2622 | } | 2612 | } |
2623 | 2613 | ||
2624 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 2614 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
2625 | 2615 | ||
2626 | if (conf->type == NL80211_IFTYPE_AP || | 2616 | if (vif->type == NL80211_IFTYPE_AP || |
2627 | conf->type == NL80211_IFTYPE_ADHOC || | 2617 | vif->type == NL80211_IFTYPE_ADHOC || |
2628 | conf->type == NL80211_IFTYPE_MONITOR) | 2618 | vif->type == NL80211_IFTYPE_MONITOR) |
2629 | ath_start_ani(common); | 2619 | ath_start_ani(common); |
2630 | 2620 | ||
2631 | out: | 2621 | out: |
@@ -2634,12 +2624,12 @@ out: | |||
2634 | } | 2624 | } |
2635 | 2625 | ||
2636 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 2626 | static void ath9k_remove_interface(struct ieee80211_hw *hw, |
2637 | struct ieee80211_if_init_conf *conf) | 2627 | struct ieee80211_vif *vif) |
2638 | { | 2628 | { |
2639 | struct ath_wiphy *aphy = hw->priv; | 2629 | struct ath_wiphy *aphy = hw->priv; |
2640 | struct ath_softc *sc = aphy->sc; | 2630 | struct ath_softc *sc = aphy->sc; |
2641 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2631 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2642 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2632 | struct ath_vif *avp = (void *)vif->drv_priv; |
2643 | int i; | 2633 | int i; |
2644 | 2634 | ||
2645 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | 2635 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
@@ -2662,7 +2652,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2662 | sc->sc_flags &= ~SC_OP_BEACONS; | 2652 | sc->sc_flags &= ~SC_OP_BEACONS; |
2663 | 2653 | ||
2664 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 2654 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { |
2665 | if (sc->beacon.bslot[i] == conf->vif) { | 2655 | if (sc->beacon.bslot[i] == vif) { |
2666 | printk(KERN_DEBUG "%s: vif had allocated beacon " | 2656 | printk(KERN_DEBUG "%s: vif had allocated beacon " |
2667 | "slot\n", __func__); | 2657 | "slot\n", __func__); |
2668 | sc->beacon.bslot[i] = NULL; | 2658 | sc->beacon.bslot[i] = NULL; |
@@ -3133,6 +3123,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3133 | { | 3123 | { |
3134 | struct ath_wiphy *aphy = hw->priv; | 3124 | struct ath_wiphy *aphy = hw->priv; |
3135 | struct ath_softc *sc = aphy->sc; | 3125 | struct ath_softc *sc = aphy->sc; |
3126 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3136 | 3127 | ||
3137 | mutex_lock(&sc->mutex); | 3128 | mutex_lock(&sc->mutex); |
3138 | if (ath9k_wiphy_scanning(sc)) { | 3129 | if (ath9k_wiphy_scanning(sc)) { |
@@ -3148,10 +3139,9 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | |||
3148 | 3139 | ||
3149 | aphy->state = ATH_WIPHY_SCAN; | 3140 | aphy->state = ATH_WIPHY_SCAN; |
3150 | ath9k_wiphy_pause_all_forced(sc, aphy); | 3141 | ath9k_wiphy_pause_all_forced(sc, aphy); |
3151 | |||
3152 | spin_lock_bh(&sc->ani_lock); | ||
3153 | sc->sc_flags |= SC_OP_SCANNING; | 3142 | sc->sc_flags |= SC_OP_SCANNING; |
3154 | spin_unlock_bh(&sc->ani_lock); | 3143 | del_timer_sync(&common->ani.timer); |
3144 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
3155 | mutex_unlock(&sc->mutex); | 3145 | mutex_unlock(&sc->mutex); |
3156 | } | 3146 | } |
3157 | 3147 | ||
@@ -3159,13 +3149,14 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3159 | { | 3149 | { |
3160 | struct ath_wiphy *aphy = hw->priv; | 3150 | struct ath_wiphy *aphy = hw->priv; |
3161 | struct ath_softc *sc = aphy->sc; | 3151 | struct ath_softc *sc = aphy->sc; |
3152 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
3162 | 3153 | ||
3163 | mutex_lock(&sc->mutex); | 3154 | mutex_lock(&sc->mutex); |
3164 | spin_lock_bh(&sc->ani_lock); | ||
3165 | aphy->state = ATH_WIPHY_ACTIVE; | 3155 | aphy->state = ATH_WIPHY_ACTIVE; |
3166 | sc->sc_flags &= ~SC_OP_SCANNING; | 3156 | sc->sc_flags &= ~SC_OP_SCANNING; |
3167 | sc->sc_flags |= SC_OP_FULL_RESET; | 3157 | sc->sc_flags |= SC_OP_FULL_RESET; |
3168 | spin_unlock_bh(&sc->ani_lock); | 3158 | ath_start_ani(common); |
3159 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | ||
3169 | ath_beacon_config(sc, NULL); | 3160 | ath_beacon_config(sc, NULL); |
3170 | mutex_unlock(&sc->mutex); | 3161 | mutex_unlock(&sc->mutex); |
3171 | } | 3162 | } |
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/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64c12e1bced3..073be566d05e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -3,6 +3,7 @@ config B43 | |||
3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA | 3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA |
4 | select SSB | 4 | select SSB |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | select SSB_BLOCKIO | ||
6 | ---help--- | 7 | ---help--- |
7 | b43 is a driver for the Broadcom 43xx series wireless devices. | 8 | b43 is a driver for the Broadcom 43xx series wireless devices. |
8 | 9 | ||
@@ -78,14 +79,6 @@ config B43_SDIO | |||
78 | 79 | ||
79 | If unsure, say N. | 80 | If unsure, say N. |
80 | 81 | ||
81 | # Data transfers to the device via PIO | ||
82 | # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. | ||
83 | config B43_PIO | ||
84 | bool | ||
85 | depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) | ||
86 | select SSB_BLOCKIO | ||
87 | default y | ||
88 | |||
89 | config B43_NPHY | 82 | config B43_NPHY |
90 | bool "Pre IEEE 802.11n support (BROKEN)" | 83 | bool "Pre IEEE 802.11n support (BROKEN)" |
91 | depends on B43 && EXPERIMENTAL && BROKEN | 84 | depends on B43 && EXPERIMENTAL && BROKEN |
@@ -137,12 +130,4 @@ config B43_DEBUG | |||
137 | for production use. | 130 | for production use. |
138 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. | 131 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. |
139 | 132 | ||
140 | config B43_FORCE_PIO | ||
141 | bool "Force usage of PIO instead of DMA" | ||
142 | depends on B43 && B43_DEBUG | ||
143 | ---help--- | ||
144 | This will disable DMA and always enable PIO instead. | ||
145 | 133 | ||
146 | Say N! | ||
147 | This is only for debugging the PIO engine code. You do | ||
148 | _NOT_ want to enable this. | ||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 84772a2542dc..5e83b6f0a3a0 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -12,7 +12,7 @@ b43-y += xmit.o | |||
12 | b43-y += lo.o | 12 | b43-y += lo.o |
13 | b43-y += wa.o | 13 | b43-y += wa.o |
14 | b43-y += dma.o | 14 | b43-y += dma.o |
15 | b43-$(CONFIG_B43_PIO) += pio.o | 15 | b43-y += pio.o |
16 | b43-y += rfkill.o | 16 | b43-y += rfkill.o |
17 | b43-$(CONFIG_B43_LEDS) += leds.o | 17 | b43-$(CONFIG_B43_LEDS) += leds.o |
18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fe3bf9491997..2f12a750bc98 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -821,11 +821,9 @@ struct b43_wl { | |||
821 | /* The device LEDs. */ | 821 | /* The device LEDs. */ |
822 | struct b43_leds leds; | 822 | struct b43_leds leds; |
823 | 823 | ||
824 | #ifdef CONFIG_B43_PIO | ||
825 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ | 824 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ |
826 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); | 825 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); |
827 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); | 826 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); |
828 | #endif /* CONFIG_B43_PIO */ | ||
829 | }; | 827 | }; |
830 | 828 | ||
831 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) | 829 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) |
@@ -876,20 +874,9 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) | |||
876 | 874 | ||
877 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) | 875 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) |
878 | { | 876 | { |
879 | #ifdef CONFIG_B43_PIO | ||
880 | return dev->__using_pio_transfers; | 877 | return dev->__using_pio_transfers; |
881 | #else | ||
882 | return 0; | ||
883 | #endif | ||
884 | } | 878 | } |
885 | 879 | ||
886 | #ifdef CONFIG_B43_FORCE_PIO | ||
887 | # define B43_FORCE_PIO 1 | ||
888 | #else | ||
889 | # define B43_FORCE_PIO 0 | ||
890 | #endif | ||
891 | |||
892 | |||
893 | /* Message printing */ | 880 | /* Message printing */ |
894 | void b43info(struct b43_wl *wl, const char *fmt, ...) | 881 | void b43info(struct b43_wl *wl, const char *fmt, ...) |
895 | __attribute__ ((format(printf, 2, 3))); | 882 | __attribute__ ((format(printf, 2, 3))); |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 88d1fd02d40a..615af22c49fd 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1653,7 +1653,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev) | |||
1653 | b43_power_saving_ctl_bits(dev, 0); | 1653 | b43_power_saving_ctl_bits(dev, 0); |
1654 | } | 1654 | } |
1655 | 1655 | ||
1656 | #ifdef CONFIG_B43_PIO | ||
1657 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, | 1656 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, |
1658 | u16 mmio_base, bool enable) | 1657 | u16 mmio_base, bool enable) |
1659 | { | 1658 | { |
@@ -1687,4 +1686,3 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev, | |||
1687 | mmio_base = b43_dmacontroller_base(type, engine_index); | 1686 | mmio_base = b43_dmacontroller_base(type, engine_index); |
1688 | direct_fifo_rx(dev, type, mmio_base, enable); | 1687 | direct_fifo_rx(dev, type, mmio_base, enable); |
1689 | } | 1688 | } |
1690 | #endif /* CONFIG_B43_PIO */ | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 19b4eae47b59..6634a77fc766 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -102,6 +102,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; | |||
102 | module_param_named(verbose, b43_modparam_verbose, int, 0644); | 102 | module_param_named(verbose, b43_modparam_verbose, int, 0644); |
103 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); | 103 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); |
104 | 104 | ||
105 | static int modparam_pio; | ||
106 | module_param_named(pio, modparam_pio, int, 0444); | ||
107 | MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); | ||
105 | 108 | ||
106 | static const struct ssb_device_id b43_ssb_tbl[] = { | 109 | static const struct ssb_device_id b43_ssb_tbl[] = { |
107 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 110 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
@@ -1786,8 +1789,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1786 | dma_reason[4], dma_reason[5]); | 1789 | dma_reason[4], dma_reason[5]); |
1787 | b43err(dev->wl, "This device does not support DMA " | 1790 | b43err(dev->wl, "This device does not support DMA " |
1788 | "on your system. Please use PIO instead.\n"); | 1791 | "on your system. Please use PIO instead.\n"); |
1789 | b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in " | 1792 | b43err(dev->wl, "Unload the b43 module and reload " |
1790 | "your kernel configuration.\n"); | 1793 | "with 'pio=1'\n"); |
1791 | return; | 1794 | return; |
1792 | } | 1795 | } |
1793 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | 1796 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { |
@@ -4353,7 +4356,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4353 | 4356 | ||
4354 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || | 4357 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || |
4355 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || | 4358 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || |
4356 | B43_FORCE_PIO) { | 4359 | modparam_pio) { |
4357 | dev->__using_pio_transfers = 1; | 4360 | dev->__using_pio_transfers = 1; |
4358 | err = b43_pio_init(dev); | 4361 | err = b43_pio_init(dev); |
4359 | } else { | 4362 | } else { |
@@ -4388,7 +4391,7 @@ err_busdown: | |||
4388 | } | 4391 | } |
4389 | 4392 | ||
4390 | static int b43_op_add_interface(struct ieee80211_hw *hw, | 4393 | static int b43_op_add_interface(struct ieee80211_hw *hw, |
4391 | struct ieee80211_if_init_conf *conf) | 4394 | struct ieee80211_vif *vif) |
4392 | { | 4395 | { |
4393 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4396 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4394 | struct b43_wldev *dev; | 4397 | struct b43_wldev *dev; |
@@ -4396,24 +4399,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4396 | 4399 | ||
4397 | /* TODO: allow WDS/AP devices to coexist */ | 4400 | /* TODO: allow WDS/AP devices to coexist */ |
4398 | 4401 | ||
4399 | if (conf->type != NL80211_IFTYPE_AP && | 4402 | if (vif->type != NL80211_IFTYPE_AP && |
4400 | conf->type != NL80211_IFTYPE_MESH_POINT && | 4403 | vif->type != NL80211_IFTYPE_MESH_POINT && |
4401 | conf->type != NL80211_IFTYPE_STATION && | 4404 | vif->type != NL80211_IFTYPE_STATION && |
4402 | conf->type != NL80211_IFTYPE_WDS && | 4405 | vif->type != NL80211_IFTYPE_WDS && |
4403 | conf->type != NL80211_IFTYPE_ADHOC) | 4406 | vif->type != NL80211_IFTYPE_ADHOC) |
4404 | return -EOPNOTSUPP; | 4407 | return -EOPNOTSUPP; |
4405 | 4408 | ||
4406 | mutex_lock(&wl->mutex); | 4409 | mutex_lock(&wl->mutex); |
4407 | if (wl->operating) | 4410 | if (wl->operating) |
4408 | goto out_mutex_unlock; | 4411 | goto out_mutex_unlock; |
4409 | 4412 | ||
4410 | b43dbg(wl, "Adding Interface type %d\n", conf->type); | 4413 | b43dbg(wl, "Adding Interface type %d\n", vif->type); |
4411 | 4414 | ||
4412 | dev = wl->current_dev; | 4415 | dev = wl->current_dev; |
4413 | wl->operating = 1; | 4416 | wl->operating = 1; |
4414 | wl->vif = conf->vif; | 4417 | wl->vif = vif; |
4415 | wl->if_type = conf->type; | 4418 | wl->if_type = vif->type; |
4416 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 4419 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
4417 | 4420 | ||
4418 | b43_adjust_opmode(dev); | 4421 | b43_adjust_opmode(dev); |
4419 | b43_set_pretbtt(dev); | 4422 | b43_set_pretbtt(dev); |
@@ -4428,17 +4431,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4428 | } | 4431 | } |
4429 | 4432 | ||
4430 | static void b43_op_remove_interface(struct ieee80211_hw *hw, | 4433 | static void b43_op_remove_interface(struct ieee80211_hw *hw, |
4431 | struct ieee80211_if_init_conf *conf) | 4434 | struct ieee80211_vif *vif) |
4432 | { | 4435 | { |
4433 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4436 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4434 | struct b43_wldev *dev = wl->current_dev; | 4437 | struct b43_wldev *dev = wl->current_dev; |
4435 | 4438 | ||
4436 | b43dbg(wl, "Removing Interface type %d\n", conf->type); | 4439 | b43dbg(wl, "Removing Interface type %d\n", vif->type); |
4437 | 4440 | ||
4438 | mutex_lock(&wl->mutex); | 4441 | mutex_lock(&wl->mutex); |
4439 | 4442 | ||
4440 | B43_WARN_ON(!wl->operating); | 4443 | B43_WARN_ON(!wl->operating); |
4441 | B43_WARN_ON(wl->vif != conf->vif); | 4444 | B43_WARN_ON(wl->vif != vif); |
4442 | wl->vif = NULL; | 4445 | wl->vif = NULL; |
4443 | 4446 | ||
4444 | wl->operating = 0; | 4447 | wl->operating = 0; |
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index 7dd649c9ddad..7b3c42f93a16 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h | |||
@@ -55,8 +55,6 @@ | |||
55 | #define B43_PIO_MAX_NR_TXPACKETS 32 | 55 | #define B43_PIO_MAX_NR_TXPACKETS 32 |
56 | 56 | ||
57 | 57 | ||
58 | #ifdef CONFIG_B43_PIO | ||
59 | |||
60 | struct b43_pio_txpacket { | 58 | struct b43_pio_txpacket { |
61 | /* Pointer to the TX queue we belong to. */ | 59 | /* Pointer to the TX queue we belong to. */ |
62 | struct b43_pio_txqueue *queue; | 60 | struct b43_pio_txqueue *queue; |
@@ -169,42 +167,4 @@ void b43_pio_rx(struct b43_pio_rxqueue *q); | |||
169 | void b43_pio_tx_suspend(struct b43_wldev *dev); | 167 | void b43_pio_tx_suspend(struct b43_wldev *dev); |
170 | void b43_pio_tx_resume(struct b43_wldev *dev); | 168 | void b43_pio_tx_resume(struct b43_wldev *dev); |
171 | 169 | ||
172 | |||
173 | #else /* CONFIG_B43_PIO */ | ||
174 | |||
175 | |||
176 | static inline int b43_pio_init(struct b43_wldev *dev) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | static inline void b43_pio_free(struct b43_wldev *dev) | ||
181 | { | ||
182 | } | ||
183 | static inline void b43_pio_stop(struct b43_wldev *dev) | ||
184 | { | ||
185 | } | ||
186 | static inline int b43_pio_tx(struct b43_wldev *dev, | ||
187 | struct sk_buff *skb) | ||
188 | { | ||
189 | return 0; | ||
190 | } | ||
191 | static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, | ||
192 | const struct b43_txstatus *status) | ||
193 | { | ||
194 | } | ||
195 | static inline void b43_pio_get_tx_stats(struct b43_wldev *dev, | ||
196 | struct ieee80211_tx_queue_stats *stats) | ||
197 | { | ||
198 | } | ||
199 | static inline void b43_pio_rx(struct b43_pio_rxqueue *q) | ||
200 | { | ||
201 | } | ||
202 | static inline void b43_pio_tx_suspend(struct b43_wldev *dev) | ||
203 | { | ||
204 | } | ||
205 | static inline void b43_pio_tx_resume(struct b43_wldev *dev) | ||
206 | { | ||
207 | } | ||
208 | |||
209 | #endif /* CONFIG_B43_PIO */ | ||
210 | #endif /* B43_PIO_H_ */ | 170 | #endif /* B43_PIO_H_ */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index ab6a18c2e9d9..494017e4fcc9 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3361,7 +3361,7 @@ err_kfree_lo_control: | |||
3361 | } | 3361 | } |
3362 | 3362 | ||
3363 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | 3363 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, |
3364 | struct ieee80211_if_init_conf *conf) | 3364 | struct ieee80211_vif *vif) |
3365 | { | 3365 | { |
3366 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3366 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3367 | struct b43legacy_wldev *dev; | 3367 | struct b43legacy_wldev *dev; |
@@ -3370,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3370 | 3370 | ||
3371 | /* TODO: allow WDS/AP devices to coexist */ | 3371 | /* TODO: allow WDS/AP devices to coexist */ |
3372 | 3372 | ||
3373 | if (conf->type != NL80211_IFTYPE_AP && | 3373 | if (vif->type != NL80211_IFTYPE_AP && |
3374 | conf->type != NL80211_IFTYPE_STATION && | 3374 | vif->type != NL80211_IFTYPE_STATION && |
3375 | conf->type != NL80211_IFTYPE_WDS && | 3375 | vif->type != NL80211_IFTYPE_WDS && |
3376 | conf->type != NL80211_IFTYPE_ADHOC) | 3376 | vif->type != NL80211_IFTYPE_ADHOC) |
3377 | return -EOPNOTSUPP; | 3377 | return -EOPNOTSUPP; |
3378 | 3378 | ||
3379 | mutex_lock(&wl->mutex); | 3379 | mutex_lock(&wl->mutex); |
3380 | if (wl->operating) | 3380 | if (wl->operating) |
3381 | goto out_mutex_unlock; | 3381 | goto out_mutex_unlock; |
3382 | 3382 | ||
3383 | b43legacydbg(wl, "Adding Interface type %d\n", conf->type); | 3383 | b43legacydbg(wl, "Adding Interface type %d\n", vif->type); |
3384 | 3384 | ||
3385 | dev = wl->current_dev; | 3385 | dev = wl->current_dev; |
3386 | wl->operating = 1; | 3386 | wl->operating = 1; |
3387 | wl->vif = conf->vif; | 3387 | wl->vif = vif; |
3388 | wl->if_type = conf->type; | 3388 | wl->if_type = vif->type; |
3389 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 3389 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
3390 | 3390 | ||
3391 | spin_lock_irqsave(&wl->irq_lock, flags); | 3391 | spin_lock_irqsave(&wl->irq_lock, flags); |
3392 | b43legacy_adjust_opmode(dev); | 3392 | b43legacy_adjust_opmode(dev); |
@@ -3403,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3403 | } | 3403 | } |
3404 | 3404 | ||
3405 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, | 3405 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, |
3406 | struct ieee80211_if_init_conf *conf) | 3406 | struct ieee80211_vif *vif) |
3407 | { | 3407 | { |
3408 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3408 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3409 | struct b43legacy_wldev *dev = wl->current_dev; | 3409 | struct b43legacy_wldev *dev = wl->current_dev; |
3410 | unsigned long flags; | 3410 | unsigned long flags; |
3411 | 3411 | ||
3412 | b43legacydbg(wl, "Removing Interface type %d\n", conf->type); | 3412 | b43legacydbg(wl, "Removing Interface type %d\n", vif->type); |
3413 | 3413 | ||
3414 | mutex_lock(&wl->mutex); | 3414 | mutex_lock(&wl->mutex); |
3415 | 3415 | ||
3416 | B43legacy_WARN_ON(!wl->operating); | 3416 | B43legacy_WARN_ON(!wl->operating); |
3417 | B43legacy_WARN_ON(wl->vif != conf->vif); | 3417 | B43legacy_WARN_ON(wl->vif != vif); |
3418 | wl->vif = NULL; | 3418 | wl->vif = NULL; |
3419 | 3419 | ||
3420 | wl->operating = 0; | 3420 | wl->operating = 0; |
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 234891d8cc10..28ffe4c826d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -2804,7 +2804,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | |||
2804 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | 2804 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2805 | }; | 2805 | }; |
2806 | 2806 | ||
2807 | static struct iwl_ops iwl3945_ops = { | 2807 | static const struct iwl_ops iwl3945_ops = { |
2808 | .ucode = &iwl3945_ucode, | 2808 | .ucode = &iwl3945_ucode, |
2809 | .lib = &iwl3945_lib, | 2809 | .lib = &iwl3945_lib, |
2810 | .hcmd = &iwl3945_hcmd, | 2810 | .hcmd = &iwl3945_hcmd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 531fa125f5a6..3ec2fe370b58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -226,7 +226,8 @@ extern void iwl3945_rx_replenish(void *data); | |||
226 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 226 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
227 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 227 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
228 | struct ieee80211_hdr *hdr,int left); | 228 | struct ieee80211_hdr *hdr,int left); |
229 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 229 | extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
230 | char **buf, bool display); | ||
230 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 231 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
231 | 232 | ||
232 | /* | 233 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 761aab127e7c..cee368d4859f 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..14f482960d7f 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); |
@@ -2594,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) | |||
2594 | EXPORT_SYMBOL(iwl_set_mode); | 2584 | EXPORT_SYMBOL(iwl_set_mode); |
2595 | 2585 | ||
2596 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2586 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
2597 | struct ieee80211_if_init_conf *conf) | 2587 | struct ieee80211_vif *vif) |
2598 | { | 2588 | { |
2599 | struct iwl_priv *priv = hw->priv; | 2589 | struct iwl_priv *priv = hw->priv; |
2600 | unsigned long flags; | 2590 | unsigned long flags; |
2601 | 2591 | ||
2602 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); | 2592 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); |
2603 | 2593 | ||
2604 | if (priv->vif) { | 2594 | if (priv->vif) { |
2605 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2595 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
@@ -2607,19 +2597,19 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2607 | } | 2597 | } |
2608 | 2598 | ||
2609 | spin_lock_irqsave(&priv->lock, flags); | 2599 | spin_lock_irqsave(&priv->lock, flags); |
2610 | priv->vif = conf->vif; | 2600 | priv->vif = vif; |
2611 | priv->iw_mode = conf->type; | 2601 | priv->iw_mode = vif->type; |
2612 | 2602 | ||
2613 | spin_unlock_irqrestore(&priv->lock, flags); | 2603 | spin_unlock_irqrestore(&priv->lock, flags); |
2614 | 2604 | ||
2615 | mutex_lock(&priv->mutex); | 2605 | mutex_lock(&priv->mutex); |
2616 | 2606 | ||
2617 | if (conf->mac_addr) { | 2607 | if (vif->addr) { |
2618 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); | 2608 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); |
2619 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 2609 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2620 | } | 2610 | } |
2621 | 2611 | ||
2622 | if (iwl_set_mode(priv, conf->type) == -EAGAIN) | 2612 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) |
2623 | /* we are not ready, will run again when ready */ | 2613 | /* we are not ready, will run again when ready */ |
2624 | set_bit(STATUS_MODE_PENDING, &priv->status); | 2614 | set_bit(STATUS_MODE_PENDING, &priv->status); |
2625 | 2615 | ||
@@ -2631,7 +2621,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2631 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2621 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2632 | 2622 | ||
2633 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2623 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2634 | struct ieee80211_if_init_conf *conf) | 2624 | struct ieee80211_vif *vif) |
2635 | { | 2625 | { |
2636 | struct iwl_priv *priv = hw->priv; | 2626 | struct iwl_priv *priv = hw->priv; |
2637 | 2627 | ||
@@ -2644,7 +2634,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2644 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2634 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2645 | iwlcore_commit_rxon(priv); | 2635 | iwlcore_commit_rxon(priv); |
2646 | } | 2636 | } |
2647 | if (priv->vif == conf->vif) { | 2637 | if (priv->vif == vif) { |
2648 | priv->vif = NULL; | 2638 | priv->vif = NULL; |
2649 | memset(priv->bssid, 0, ETH_ALEN); | 2639 | memset(priv->bssid, 0, ETH_ALEN); |
2650 | } | 2640 | } |
@@ -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 675b7df632fc..8deb83bfe182 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -63,8 +63,6 @@ | |||
63 | #ifndef __iwl_core_h__ | 63 | #ifndef __iwl_core_h__ |
64 | #define __iwl_core_h__ | 64 | #define __iwl_core_h__ |
65 | 65 | ||
66 | #include <linux/utsrelease.h> | ||
67 | |||
68 | /************************ | 66 | /************************ |
69 | * forward declarations * | 67 | * forward declarations * |
70 | ************************/ | 68 | ************************/ |
@@ -72,7 +70,7 @@ struct iwl_host_cmd; | |||
72 | struct iwl_cmd; | 70 | struct iwl_cmd; |
73 | 71 | ||
74 | 72 | ||
75 | #define IWLWIFI_VERSION UTS_RELEASE "-k" | 73 | #define IWLWIFI_VERSION "in-tree:" |
76 | #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" | 74 | #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" |
77 | #define DRV_AUTHOR "<ilw@linux.intel.com>" | 75 | #define DRV_AUTHOR "<ilw@linux.intel.com>" |
78 | 76 | ||
@@ -169,8 +167,10 @@ struct iwl_lib_ops { | |||
169 | int (*is_valid_rtc_data_addr)(u32 addr); | 167 | int (*is_valid_rtc_data_addr)(u32 addr); |
170 | /* 1st ucode load */ | 168 | /* 1st ucode load */ |
171 | int (*load_ucode)(struct iwl_priv *priv); | 169 | int (*load_ucode)(struct iwl_priv *priv); |
172 | void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); | 170 | int (*dump_nic_event_log)(struct iwl_priv *priv, |
171 | bool full_log, char **buf, bool display); | ||
173 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 172 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
173 | void (*dump_csr)(struct iwl_priv *priv); | ||
174 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 174 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); |
175 | /* power management */ | 175 | /* power management */ |
176 | struct iwl_apm_ops apm_ops; | 176 | struct iwl_apm_ops apm_ops; |
@@ -230,7 +230,6 @@ struct iwl_mod_params { | |||
230 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 230 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
231 | * @adv_thermal_throttle: support advance thermal throttle | 231 | * @adv_thermal_throttle: support advance thermal throttle |
232 | * @support_ct_kill_exit: support ct kill exit condition | 232 | * @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 | 233 | * @support_wimax_coexist: support wimax/wifi co-exist |
235 | * | 234 | * |
236 | * We enable the driver to be backward compatible wrt API version. The | 235 | * We enable the driver to be backward compatible wrt API version. The |
@@ -287,7 +286,6 @@ struct iwl_cfg { | |||
287 | const bool supports_idle; | 286 | const bool supports_idle; |
288 | bool adv_thermal_throttle; | 287 | bool adv_thermal_throttle; |
289 | bool support_ct_kill_exit; | 288 | bool support_ct_kill_exit; |
290 | u8 sm_ps_mode; | ||
291 | const bool support_wimax_coexist; | 289 | const bool support_wimax_coexist; |
292 | }; | 290 | }; |
293 | 291 | ||
@@ -332,9 +330,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
332 | int iwl_commit_rxon(struct iwl_priv *priv); | 330 | int iwl_commit_rxon(struct iwl_priv *priv); |
333 | int iwl_set_mode(struct iwl_priv *priv, int mode); | 331 | int iwl_set_mode(struct iwl_priv *priv, int mode); |
334 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 332 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
335 | struct ieee80211_if_init_conf *conf); | 333 | struct ieee80211_vif *vif); |
336 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 334 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
337 | struct ieee80211_if_init_conf *conf); | 335 | struct ieee80211_vif *vif); |
338 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | 336 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); |
339 | void iwl_config_ap(struct iwl_priv *priv); | 337 | void iwl_config_ap(struct iwl_priv *priv); |
340 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | 338 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, |
@@ -581,7 +579,9 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
581 | * Error Handling Debugging | 579 | * Error Handling Debugging |
582 | ******************************************************/ | 580 | ******************************************************/ |
583 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 581 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
584 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | 582 | int iwl_dump_nic_event_log(struct iwl_priv *priv, |
583 | bool full_log, char **buf, bool display); | ||
584 | void iwl_dump_csr(struct iwl_priv *priv); | ||
585 | #ifdef CONFIG_IWLWIFI_DEBUG | 585 | #ifdef CONFIG_IWLWIFI_DEBUG |
586 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 586 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); |
587 | #else | 587 | #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 f8e4e4b18d02..10b0aa8024c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1518,8 +1518,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1518 | * iwl3945_print_event_log - Dump error event log to syslog | 1518 | * iwl3945_print_event_log - Dump error event log to syslog |
1519 | * | 1519 | * |
1520 | */ | 1520 | */ |
1521 | static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | 1521 | static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, |
1522 | u32 num_events, u32 mode) | 1522 | u32 num_events, u32 mode, |
1523 | int pos, char **buf, size_t bufsz) | ||
1523 | { | 1524 | { |
1524 | u32 i; | 1525 | u32 i; |
1525 | u32 base; /* SRAM byte address of event log header */ | 1526 | u32 base; /* SRAM byte address of event log header */ |
@@ -1529,7 +1530,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1529 | unsigned long reg_flags; | 1530 | unsigned long reg_flags; |
1530 | 1531 | ||
1531 | if (num_events == 0) | 1532 | if (num_events == 0) |
1532 | return; | 1533 | return pos; |
1533 | 1534 | ||
1534 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1535 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1535 | 1536 | ||
@@ -1555,26 +1556,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1555 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1556 | time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1556 | if (mode == 0) { | 1557 | if (mode == 0) { |
1557 | /* data, ev */ | 1558 | /* data, ev */ |
1558 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1559 | if (bufsz) { |
1559 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | 1560 | pos += scnprintf(*buf + pos, bufsz - pos, |
1561 | "0x%08x:%04u\n", | ||
1562 | time, ev); | ||
1563 | } else { | ||
1564 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | ||
1565 | trace_iwlwifi_dev_ucode_event(priv, 0, | ||
1566 | time, ev); | ||
1567 | } | ||
1560 | } else { | 1568 | } else { |
1561 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); | 1569 | data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); |
1562 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1570 | if (bufsz) { |
1563 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | 1571 | pos += scnprintf(*buf + pos, bufsz - pos, |
1572 | "%010u:0x%08x:%04u\n", | ||
1573 | time, data, ev); | ||
1574 | } else { | ||
1575 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", | ||
1576 | time, data, ev); | ||
1577 | trace_iwlwifi_dev_ucode_event(priv, time, | ||
1578 | data, ev); | ||
1579 | } | ||
1564 | } | 1580 | } |
1565 | } | 1581 | } |
1566 | 1582 | ||
1567 | /* Allow device to power down */ | 1583 | /* Allow device to power down */ |
1568 | iwl_release_nic_access(priv); | 1584 | iwl_release_nic_access(priv); |
1569 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1585 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1586 | return pos; | ||
1570 | } | 1587 | } |
1571 | 1588 | ||
1572 | /** | 1589 | /** |
1573 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | 1590 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog |
1574 | */ | 1591 | */ |
1575 | static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | 1592 | static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, |
1576 | u32 num_wraps, u32 next_entry, | 1593 | u32 num_wraps, u32 next_entry, |
1577 | u32 size, u32 mode) | 1594 | u32 size, u32 mode, |
1595 | int pos, char **buf, size_t bufsz) | ||
1578 | { | 1596 | { |
1579 | /* | 1597 | /* |
1580 | * display the newest DEFAULT_LOG_ENTRIES entries | 1598 | * display the newest DEFAULT_LOG_ENTRIES entries |
@@ -1582,21 +1600,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1582 | */ | 1600 | */ |
1583 | if (num_wraps) { | 1601 | if (num_wraps) { |
1584 | if (next_entry < size) { | 1602 | if (next_entry < size) { |
1585 | iwl3945_print_event_log(priv, | 1603 | pos = iwl3945_print_event_log(priv, |
1586 | capacity - (size - next_entry), | 1604 | capacity - (size - next_entry), |
1587 | size - next_entry, mode); | 1605 | size - next_entry, mode, |
1588 | iwl3945_print_event_log(priv, 0, | 1606 | pos, buf, bufsz); |
1589 | next_entry, mode); | 1607 | pos = iwl3945_print_event_log(priv, 0, |
1608 | next_entry, mode, | ||
1609 | pos, buf, bufsz); | ||
1590 | } else | 1610 | } else |
1591 | iwl3945_print_event_log(priv, next_entry - size, | 1611 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1592 | size, mode); | 1612 | size, mode, |
1613 | pos, buf, bufsz); | ||
1593 | } else { | 1614 | } else { |
1594 | if (next_entry < size) | 1615 | if (next_entry < size) |
1595 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1616 | pos = iwl3945_print_event_log(priv, 0, |
1617 | next_entry, mode, | ||
1618 | pos, buf, bufsz); | ||
1596 | else | 1619 | else |
1597 | iwl3945_print_event_log(priv, next_entry - size, | 1620 | pos = iwl3945_print_event_log(priv, next_entry - size, |
1598 | size, mode); | 1621 | size, mode, |
1622 | pos, buf, bufsz); | ||
1599 | } | 1623 | } |
1624 | return pos; | ||
1600 | } | 1625 | } |
1601 | 1626 | ||
1602 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1627 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
@@ -1604,7 +1629,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1604 | 1629 | ||
1605 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | 1630 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1606 | 1631 | ||
1607 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | 1632 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
1633 | char **buf, bool display) | ||
1608 | { | 1634 | { |
1609 | u32 base; /* SRAM byte address of event log header */ | 1635 | u32 base; /* SRAM byte address of event log header */ |
1610 | u32 capacity; /* event log capacity in # entries */ | 1636 | u32 capacity; /* event log capacity in # entries */ |
@@ -1612,11 +1638,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1612 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 1638 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
1613 | u32 next_entry; /* index of next entry to be written by uCode */ | 1639 | u32 next_entry; /* index of next entry to be written by uCode */ |
1614 | u32 size; /* # entries that we'll print */ | 1640 | u32 size; /* # entries that we'll print */ |
1641 | int pos = 0; | ||
1642 | size_t bufsz = 0; | ||
1615 | 1643 | ||
1616 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 1644 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
1617 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { | 1645 | if (!iwl3945_hw_valid_rtc_data_addr(base)) { |
1618 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); | 1646 | IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); |
1619 | return; | 1647 | return pos; |
1620 | } | 1648 | } |
1621 | 1649 | ||
1622 | /* event log header */ | 1650 | /* event log header */ |
@@ -1642,7 +1670,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1642 | /* bail out if nothing in log */ | 1670 | /* bail out if nothing in log */ |
1643 | if (size == 0) { | 1671 | if (size == 0) { |
1644 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); | 1672 | IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); |
1645 | return; | 1673 | return pos; |
1646 | } | 1674 | } |
1647 | 1675 | ||
1648 | #ifdef CONFIG_IWLWIFI_DEBUG | 1676 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -1658,25 +1686,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | |||
1658 | size); | 1686 | size); |
1659 | 1687 | ||
1660 | #ifdef CONFIG_IWLWIFI_DEBUG | 1688 | #ifdef CONFIG_IWLWIFI_DEBUG |
1689 | if (display) { | ||
1690 | if (full_log) | ||
1691 | bufsz = capacity * 48; | ||
1692 | else | ||
1693 | bufsz = size * 48; | ||
1694 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
1695 | if (!*buf) | ||
1696 | return pos; | ||
1697 | } | ||
1661 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | 1698 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { |
1662 | /* if uCode has wrapped back to top of log, | 1699 | /* if uCode has wrapped back to top of log, |
1663 | * start at the oldest entry, | 1700 | * start at the oldest entry, |
1664 | * i.e the next one that uCode would fill. | 1701 | * i.e the next one that uCode would fill. |
1665 | */ | 1702 | */ |
1666 | if (num_wraps) | 1703 | if (num_wraps) |
1667 | iwl3945_print_event_log(priv, next_entry, | 1704 | pos = iwl3945_print_event_log(priv, next_entry, |
1668 | capacity - next_entry, mode); | 1705 | capacity - next_entry, mode, |
1706 | pos, buf, bufsz); | ||
1669 | 1707 | ||
1670 | /* (then/else) start at top of log */ | 1708 | /* (then/else) start at top of log */ |
1671 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1709 | pos = iwl3945_print_event_log(priv, 0, next_entry, mode, |
1710 | pos, buf, bufsz); | ||
1672 | } else | 1711 | } else |
1673 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1712 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1674 | next_entry, size, mode); | 1713 | next_entry, size, mode, |
1714 | pos, buf, bufsz); | ||
1675 | #else | 1715 | #else |
1676 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | 1716 | pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1677 | next_entry, size, mode); | 1717 | next_entry, size, mode, |
1718 | pos, buf, bufsz); | ||
1678 | #endif | 1719 | #endif |
1679 | 1720 | return pos; | |
1680 | } | 1721 | } |
1681 | 1722 | ||
1682 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1723 | 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 3db3d8b07491..fd399e6b1930 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 b9b371bfa30f..42051f7cad6d 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 6a8d2b291d8c..d5a9dcae4059 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 db38a5a719fa..f9f195f7b17c 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, |
@@ -619,7 +619,7 @@ static int lbs_thread(void *data) | |||
619 | if (priv->connect_status == LBS_CONNECTED) | 619 | if (priv->connect_status == LBS_CONNECTED) |
620 | netif_wake_queue(priv->dev); | 620 | netif_wake_queue(priv->dev); |
621 | if (priv->mesh_dev && | 621 | if (priv->mesh_dev && |
622 | priv->mesh_connect_status == LBS_CONNECTED) | 622 | lbs_mesh_connected(priv)) |
623 | netif_wake_queue(priv->mesh_dev); | 623 | netif_wake_queue(priv->mesh_dev); |
624 | } | 624 | } |
625 | } | 625 | } |
@@ -806,18 +806,6 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | |||
806 | return 0; | 806 | return 0; |
807 | } | 807 | } |
808 | 808 | ||
809 | static void lbs_sync_channel_worker(struct work_struct *work) | ||
810 | { | ||
811 | struct lbs_private *priv = container_of(work, struct lbs_private, | ||
812 | sync_channel); | ||
813 | |||
814 | lbs_deb_enter(LBS_DEB_MAIN); | ||
815 | if (lbs_update_channel(priv)) | ||
816 | lbs_pr_info("Channel synchronization failed."); | ||
817 | lbs_deb_leave(LBS_DEB_MAIN); | ||
818 | } | ||
819 | |||
820 | |||
821 | static int lbs_init_adapter(struct lbs_private *priv) | 809 | static int lbs_init_adapter(struct lbs_private *priv) |
822 | { | 810 | { |
823 | size_t bufsize; | 811 | size_t bufsize; |
@@ -845,14 +833,12 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
845 | memset(priv->current_addr, 0xff, ETH_ALEN); | 833 | memset(priv->current_addr, 0xff, ETH_ALEN); |
846 | 834 | ||
847 | priv->connect_status = LBS_DISCONNECTED; | 835 | priv->connect_status = LBS_DISCONNECTED; |
848 | priv->mesh_connect_status = LBS_DISCONNECTED; | ||
849 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 836 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
850 | priv->mode = IW_MODE_INFRA; | 837 | priv->mode = IW_MODE_INFRA; |
851 | priv->channel = DEFAULT_AD_HOC_CHANNEL; | 838 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
852 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 839 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
853 | priv->radio_on = 1; | 840 | priv->radio_on = 1; |
854 | priv->enablehwauto = 1; | 841 | priv->enablehwauto = 1; |
855 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
856 | priv->psmode = LBS802_11POWERMODECAM; | 842 | priv->psmode = LBS802_11POWERMODECAM; |
857 | priv->psstate = PS_STATE_FULL_POWER; | 843 | priv->psstate = PS_STATE_FULL_POWER; |
858 | priv->is_deep_sleep = 0; | 844 | priv->is_deep_sleep = 0; |
@@ -997,11 +983,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
997 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); | 983 | INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); |
998 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 984 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
999 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); | 985 | INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); |
1000 | INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); | ||
1001 | |||
1002 | priv->mesh_open = 0; | ||
1003 | sprintf(priv->mesh_ssid, "mesh"); | ||
1004 | priv->mesh_ssid_len = 4; | ||
1005 | 986 | ||
1006 | priv->wol_criteria = 0xffffffff; | 987 | priv->wol_criteria = 0xffffffff; |
1007 | priv->wol_gpio = 0xff; | 988 | priv->wol_gpio = 0xff; |
@@ -1075,6 +1056,17 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1075 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 1056 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1076 | 1057 | ||
1077 | 1058 | ||
1059 | static int lbs_rtap_supported(struct lbs_private *priv) | ||
1060 | { | ||
1061 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
1062 | return 1; | ||
1063 | |||
1064 | /* newer firmware use a capability mask */ | ||
1065 | return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
1066 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); | ||
1067 | } | ||
1068 | |||
1069 | |||
1078 | int lbs_start_card(struct lbs_private *priv) | 1070 | int lbs_start_card(struct lbs_private *priv) |
1079 | { | 1071 | { |
1080 | struct net_device *dev = priv->dev; | 1072 | struct net_device *dev = priv->dev; |
@@ -1094,12 +1086,14 @@ int lbs_start_card(struct lbs_private *priv) | |||
1094 | 1086 | ||
1095 | lbs_update_channel(priv); | 1087 | lbs_update_channel(priv); |
1096 | 1088 | ||
1089 | lbs_init_mesh(priv); | ||
1090 | |||
1097 | /* | 1091 | /* |
1098 | * While rtap isn't related to mesh, only mesh-enabled | 1092 | * While rtap isn't related to mesh, only mesh-enabled |
1099 | * firmware implements the rtap functionality via | 1093 | * firmware implements the rtap functionality via |
1100 | * CMD_802_11_MONITOR_MODE. | 1094 | * CMD_802_11_MONITOR_MODE. |
1101 | */ | 1095 | */ |
1102 | if (lbs_init_mesh(priv)) { | 1096 | if (lbs_rtap_supported(priv)) { |
1103 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) | 1097 | if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) |
1104 | lbs_pr_err("cannot register lbs_rtap attribute\n"); | 1098 | lbs_pr_err("cannot register lbs_rtap attribute\n"); |
1105 | } | 1099 | } |
@@ -1133,7 +1127,9 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1133 | netif_carrier_off(dev); | 1127 | netif_carrier_off(dev); |
1134 | 1128 | ||
1135 | lbs_debugfs_remove_one(priv); | 1129 | lbs_debugfs_remove_one(priv); |
1136 | if (lbs_deinit_mesh(priv)) | 1130 | lbs_deinit_mesh(priv); |
1131 | |||
1132 | if (lbs_rtap_supported(priv)) | ||
1137 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); | 1133 | device_remove_file(&dev->dev, &dev_attr_lbs_rtap); |
1138 | 1134 | ||
1139 | /* Delete the timeout of the currently processing command */ | 1135 | /* 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 b0b1c7841500..220361e69cd3 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -635,7 +635,7 @@ out: | |||
635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) | 635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) |
636 | netif_wake_queue(priv->dev); | 636 | netif_wake_queue(priv->dev); |
637 | 637 | ||
638 | if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && | 638 | if (priv->mesh_dev && lbs_mesh_connected(priv) && |
639 | !priv->tx_pending_len) | 639 | !priv->tx_pending_len) |
640 | netif_wake_queue(priv->mesh_dev); | 640 | netif_wake_queue(priv->mesh_dev); |
641 | 641 | ||
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/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 26a1abd5bb03..ba3eb0101d55 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, | 320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, |
321 | struct ieee80211_if_init_conf *conf) | 321 | struct ieee80211_vif *vif) |
322 | { | 322 | { |
323 | struct lbtf_private *priv = hw->priv; | 323 | struct lbtf_private *priv = hw->priv; |
324 | if (priv->vif != NULL) | 324 | if (priv->vif != NULL) |
325 | return -EOPNOTSUPP; | 325 | return -EOPNOTSUPP; |
326 | 326 | ||
327 | priv->vif = conf->vif; | 327 | priv->vif = vif; |
328 | switch (conf->type) { | 328 | switch (vif->type) { |
329 | case NL80211_IFTYPE_MESH_POINT: | 329 | case NL80211_IFTYPE_MESH_POINT: |
330 | case NL80211_IFTYPE_AP: | 330 | case NL80211_IFTYPE_AP: |
331 | lbtf_set_mode(priv, LBTF_AP_MODE); | 331 | lbtf_set_mode(priv, LBTF_AP_MODE); |
@@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, | |||
337 | priv->vif = NULL; | 337 | priv->vif = NULL; |
338 | return -EOPNOTSUPP; | 338 | return -EOPNOTSUPP; |
339 | } | 339 | } |
340 | lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); | 340 | lbtf_set_mac_address(priv, (u8 *) vif->addr); |
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, | 344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, |
345 | struct ieee80211_if_init_conf *conf) | 345 | struct ieee80211_vif *vif) |
346 | { | 346 | { |
347 | struct lbtf_private *priv = hw->priv; | 347 | struct lbtf_private *priv = hw->priv; |
348 | 348 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 88e41176e7fd..84df3fcf37b3 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); |
@@ -553,24 +584,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) | |||
553 | 584 | ||
554 | 585 | ||
555 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | 586 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, |
556 | struct ieee80211_if_init_conf *conf) | 587 | struct ieee80211_vif *vif) |
557 | { | 588 | { |
558 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 589 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
559 | wiphy_name(hw->wiphy), __func__, conf->type, | 590 | wiphy_name(hw->wiphy), __func__, vif->type, |
560 | conf->mac_addr); | 591 | vif->addr); |
561 | hwsim_set_magic(conf->vif); | 592 | hwsim_set_magic(vif); |
562 | return 0; | 593 | return 0; |
563 | } | 594 | } |
564 | 595 | ||
565 | 596 | ||
566 | static void mac80211_hwsim_remove_interface( | 597 | static void mac80211_hwsim_remove_interface( |
567 | struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) | 598 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
568 | { | 599 | { |
569 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 600 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
570 | wiphy_name(hw->wiphy), __func__, conf->type, | 601 | wiphy_name(hw->wiphy), __func__, vif->type, |
571 | conf->mac_addr); | 602 | vif->addr); |
572 | hwsim_check_magic(conf->vif); | 603 | hwsim_check_magic(vif); |
573 | hwsim_clear_magic(conf->vif); | 604 | hwsim_clear_magic(vif); |
574 | } | 605 | } |
575 | 606 | ||
576 | 607 | ||
@@ -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,41 @@ 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 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | ||
900 | { | ||
901 | /* | ||
902 | * In this special case, there's nothing we need to | ||
903 | * do because hwsim does transmission synchronously. | ||
904 | * In the future, when it does transmissions via | ||
905 | * userspace, we may need to do something. | ||
906 | */ | ||
907 | } | ||
908 | |||
909 | |||
830 | static const struct ieee80211_ops mac80211_hwsim_ops = | 910 | static const struct ieee80211_ops mac80211_hwsim_ops = |
831 | { | 911 | { |
832 | .tx = mac80211_hwsim_tx, | 912 | .tx = mac80211_hwsim_tx, |
@@ -841,6 +921,8 @@ static const struct ieee80211_ops mac80211_hwsim_ops = | |||
841 | .set_tim = mac80211_hwsim_set_tim, | 921 | .set_tim = mac80211_hwsim_set_tim, |
842 | .conf_tx = mac80211_hwsim_conf_tx, | 922 | .conf_tx = mac80211_hwsim_conf_tx, |
843 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 923 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
924 | .ampdu_action = mac80211_hwsim_ampdu_action, | ||
925 | .flush = mac80211_hwsim_flush, | ||
844 | }; | 926 | }; |
845 | 927 | ||
846 | 928 | ||
@@ -1082,7 +1164,9 @@ static int __init init_mac80211_hwsim(void) | |||
1082 | BIT(NL80211_IFTYPE_MESH_POINT); | 1164 | BIT(NL80211_IFTYPE_MESH_POINT); |
1083 | 1165 | ||
1084 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1166 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
1085 | IEEE80211_HW_SIGNAL_DBM; | 1167 | IEEE80211_HW_SIGNAL_DBM | |
1168 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | ||
1169 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; | ||
1086 | 1170 | ||
1087 | /* ask mac80211 to reserve space for magic */ | 1171 | /* ask mac80211 to reserve space for magic */ |
1088 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1172 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 59f92105b0c2..a04863633d1a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" | 27 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" |
28 | #define MWL8K_NAME KBUILD_MODNAME | 28 | #define MWL8K_NAME KBUILD_MODNAME |
29 | #define MWL8K_VERSION "0.10" | 29 | #define MWL8K_VERSION "0.11" |
30 | 30 | ||
31 | /* Register definitions */ | 31 | /* Register definitions */ |
32 | #define MWL8K_HIU_GEN_PTR 0x00000c10 | 32 | #define MWL8K_HIU_GEN_PTR 0x00000c10 |
@@ -92,8 +92,7 @@ struct mwl8k_device_info { | |||
92 | char *part_name; | 92 | char *part_name; |
93 | char *helper_image; | 93 | char *helper_image; |
94 | char *fw_image; | 94 | char *fw_image; |
95 | struct rxd_ops *rxd_ops; | 95 | struct rxd_ops *ap_rxd_ops; |
96 | u16 modes; | ||
97 | }; | 96 | }; |
98 | 97 | ||
99 | struct mwl8k_rx_queue { | 98 | struct mwl8k_rx_queue { |
@@ -126,29 +125,23 @@ struct mwl8k_tx_queue { | |||
126 | struct sk_buff **skb; | 125 | struct sk_buff **skb; |
127 | }; | 126 | }; |
128 | 127 | ||
129 | /* Pointers to the firmware data and meta information about it. */ | 128 | struct mwl8k_priv { |
130 | struct mwl8k_firmware { | 129 | struct ieee80211_hw *hw; |
131 | /* Boot helper code */ | 130 | struct pci_dev *pdev; |
132 | struct firmware *helper; | ||
133 | 131 | ||
134 | /* Microcode */ | 132 | struct mwl8k_device_info *device_info; |
135 | struct firmware *ucode; | ||
136 | }; | ||
137 | 133 | ||
138 | struct mwl8k_priv { | ||
139 | void __iomem *sram; | 134 | void __iomem *sram; |
140 | void __iomem *regs; | 135 | void __iomem *regs; |
141 | struct ieee80211_hw *hw; | ||
142 | 136 | ||
143 | struct pci_dev *pdev; | 137 | /* firmware */ |
138 | struct firmware *fw_helper; | ||
139 | struct firmware *fw_ucode; | ||
144 | 140 | ||
145 | struct mwl8k_device_info *device_info; | 141 | /* hardware/firmware parameters */ |
146 | bool ap_fw; | 142 | bool ap_fw; |
147 | struct rxd_ops *rxd_ops; | 143 | struct rxd_ops *rxd_ops; |
148 | 144 | ||
149 | /* firmware files and meta data */ | ||
150 | struct mwl8k_firmware fw; | ||
151 | |||
152 | /* firmware access */ | 145 | /* firmware access */ |
153 | struct mutex fw_mutex; | 146 | struct mutex fw_mutex; |
154 | struct task_struct *fw_mutex_owner; | 147 | struct task_struct *fw_mutex_owner; |
@@ -192,6 +185,10 @@ struct mwl8k_priv { | |||
192 | bool sniffer_enabled; | 185 | bool sniffer_enabled; |
193 | bool wmm_enabled; | 186 | bool wmm_enabled; |
194 | 187 | ||
188 | struct work_struct sta_notify_worker; | ||
189 | spinlock_t sta_notify_list_lock; | ||
190 | struct list_head sta_notify_list; | ||
191 | |||
195 | /* XXX need to convert this to handle multiple interfaces */ | 192 | /* XXX need to convert this to handle multiple interfaces */ |
196 | bool capture_beacon; | 193 | bool capture_beacon; |
197 | u8 capture_bssid[ETH_ALEN]; | 194 | u8 capture_bssid[ETH_ALEN]; |
@@ -211,25 +208,20 @@ struct mwl8k_priv { | |||
211 | 208 | ||
212 | /* Per interface specific private data */ | 209 | /* Per interface specific private data */ |
213 | struct mwl8k_vif { | 210 | struct mwl8k_vif { |
214 | /* backpointer to parent config block */ | 211 | /* Local MAC address. */ |
215 | struct mwl8k_priv *priv; | 212 | u8 mac_addr[ETH_ALEN]; |
216 | |||
217 | /* BSS config of AP or IBSS from mac80211*/ | ||
218 | struct ieee80211_bss_conf bss_info; | ||
219 | |||
220 | /* BSSID of AP or IBSS */ | ||
221 | u8 bssid[ETH_ALEN]; | ||
222 | u8 mac_addr[ETH_ALEN]; | ||
223 | |||
224 | /* Index into station database.Returned by update_sta_db call */ | ||
225 | u8 peer_id; | ||
226 | 213 | ||
227 | /* Non AMPDU sequence number assigned by driver */ | 214 | /* Non AMPDU sequence number assigned by driver */ |
228 | u16 seqno; | 215 | u16 seqno; |
229 | }; | 216 | }; |
230 | |||
231 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) | 217 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) |
232 | 218 | ||
219 | struct mwl8k_sta { | ||
220 | /* Index into station database. Returned by UPDATE_STADB. */ | ||
221 | u8 peer_id; | ||
222 | }; | ||
223 | #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) | ||
224 | |||
233 | static const struct ieee80211_channel mwl8k_channels[] = { | 225 | static const struct ieee80211_channel mwl8k_channels[] = { |
234 | { .center_freq = 2412, .hw_value = 1, }, | 226 | { .center_freq = 2412, .hw_value = 1, }, |
235 | { .center_freq = 2417, .hw_value = 2, }, | 227 | { .center_freq = 2417, .hw_value = 2, }, |
@@ -242,6 +234,9 @@ static const struct ieee80211_channel mwl8k_channels[] = { | |||
242 | { .center_freq = 2452, .hw_value = 9, }, | 234 | { .center_freq = 2452, .hw_value = 9, }, |
243 | { .center_freq = 2457, .hw_value = 10, }, | 235 | { .center_freq = 2457, .hw_value = 10, }, |
244 | { .center_freq = 2462, .hw_value = 11, }, | 236 | { .center_freq = 2462, .hw_value = 11, }, |
237 | { .center_freq = 2467, .hw_value = 12, }, | ||
238 | { .center_freq = 2472, .hw_value = 13, }, | ||
239 | { .center_freq = 2484, .hw_value = 14, }, | ||
245 | }; | 240 | }; |
246 | 241 | ||
247 | static const struct ieee80211_rate mwl8k_rates[] = { | 242 | static const struct ieee80211_rate mwl8k_rates[] = { |
@@ -261,10 +256,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { | |||
261 | { .bitrate = 720, .hw_value = 144, }, | 256 | { .bitrate = 720, .hw_value = 144, }, |
262 | }; | 257 | }; |
263 | 258 | ||
264 | static const u8 mwl8k_rateids[12] = { | ||
265 | 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, | ||
266 | }; | ||
267 | |||
268 | /* Set or get info from Firmware */ | 259 | /* Set or get info from Firmware */ |
269 | #define MWL8K_CMD_SET 0x0001 | 260 | #define MWL8K_CMD_SET 0x0001 |
270 | #define MWL8K_CMD_GET 0x0000 | 261 | #define MWL8K_CMD_GET 0x0000 |
@@ -355,8 +346,8 @@ static void mwl8k_release_fw(struct firmware **fw) | |||
355 | 346 | ||
356 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) | 347 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) |
357 | { | 348 | { |
358 | mwl8k_release_fw(&priv->fw.ucode); | 349 | mwl8k_release_fw(&priv->fw_ucode); |
359 | mwl8k_release_fw(&priv->fw.helper); | 350 | mwl8k_release_fw(&priv->fw_helper); |
360 | } | 351 | } |
361 | 352 | ||
362 | /* Request fw image */ | 353 | /* Request fw image */ |
@@ -377,7 +368,7 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
377 | int rc; | 368 | int rc; |
378 | 369 | ||
379 | if (di->helper_image != NULL) { | 370 | if (di->helper_image != NULL) { |
380 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper); | 371 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); |
381 | if (rc) { | 372 | if (rc) { |
382 | printk(KERN_ERR "%s: Error requesting helper " | 373 | printk(KERN_ERR "%s: Error requesting helper " |
383 | "firmware file %s\n", pci_name(priv->pdev), | 374 | "firmware file %s\n", pci_name(priv->pdev), |
@@ -386,11 +377,11 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
386 | } | 377 | } |
387 | } | 378 | } |
388 | 379 | ||
389 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode); | 380 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); |
390 | if (rc) { | 381 | if (rc) { |
391 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", | 382 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", |
392 | pci_name(priv->pdev), di->fw_image); | 383 | pci_name(priv->pdev), di->fw_image); |
393 | mwl8k_release_fw(&priv->fw.helper); | 384 | mwl8k_release_fw(&priv->fw_helper); |
394 | return rc; | 385 | return rc; |
395 | } | 386 | } |
396 | 387 | ||
@@ -551,13 +542,12 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, | |||
551 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) | 542 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) |
552 | { | 543 | { |
553 | struct mwl8k_priv *priv = hw->priv; | 544 | struct mwl8k_priv *priv = hw->priv; |
554 | struct firmware *fw = priv->fw.ucode; | 545 | struct firmware *fw = priv->fw_ucode; |
555 | struct mwl8k_device_info *di = priv->device_info; | ||
556 | int rc; | 546 | int rc; |
557 | int loops; | 547 | int loops; |
558 | 548 | ||
559 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { | 549 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { |
560 | struct firmware *helper = priv->fw.helper; | 550 | struct firmware *helper = priv->fw_helper; |
561 | 551 | ||
562 | if (helper == NULL) { | 552 | if (helper == NULL) { |
563 | printk(KERN_ERR "%s: helper image needed but none " | 553 | printk(KERN_ERR "%s: helper image needed but none " |
@@ -584,10 +574,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
584 | return rc; | 574 | return rc; |
585 | } | 575 | } |
586 | 576 | ||
587 | if (di->modes & BIT(NL80211_IFTYPE_AP)) | 577 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); |
588 | iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); | ||
589 | else | ||
590 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); | ||
591 | 578 | ||
592 | loops = 500000; | 579 | loops = 500000; |
593 | do { | 580 | do { |
@@ -610,91 +597,6 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
610 | } | 597 | } |
611 | 598 | ||
612 | 599 | ||
613 | /* | ||
614 | * Defines shared between transmission and reception. | ||
615 | */ | ||
616 | /* HT control fields for firmware */ | ||
617 | struct ewc_ht_info { | ||
618 | __le16 control1; | ||
619 | __le16 control2; | ||
620 | __le16 control3; | ||
621 | } __attribute__((packed)); | ||
622 | |||
623 | /* Firmware Station database operations */ | ||
624 | #define MWL8K_STA_DB_ADD_ENTRY 0 | ||
625 | #define MWL8K_STA_DB_MODIFY_ENTRY 1 | ||
626 | #define MWL8K_STA_DB_DEL_ENTRY 2 | ||
627 | #define MWL8K_STA_DB_FLUSH 3 | ||
628 | |||
629 | /* Peer Entry flags - used to define the type of the peer node */ | ||
630 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | ||
631 | |||
632 | struct peer_capability_info { | ||
633 | /* Peer type - AP vs. STA. */ | ||
634 | __u8 peer_type; | ||
635 | |||
636 | /* Basic 802.11 capabilities from assoc resp. */ | ||
637 | __le16 basic_caps; | ||
638 | |||
639 | /* Set if peer supports 802.11n high throughput (HT). */ | ||
640 | __u8 ht_support; | ||
641 | |||
642 | /* Valid if HT is supported. */ | ||
643 | __le16 ht_caps; | ||
644 | __u8 extended_ht_caps; | ||
645 | struct ewc_ht_info ewc_info; | ||
646 | |||
647 | /* Legacy rate table. Intersection of our rates and peer rates. */ | ||
648 | __u8 legacy_rates[12]; | ||
649 | |||
650 | /* HT rate table. Intersection of our rates and peer rates. */ | ||
651 | __u8 ht_rates[16]; | ||
652 | __u8 pad[16]; | ||
653 | |||
654 | /* If set, interoperability mode, no proprietary extensions. */ | ||
655 | __u8 interop; | ||
656 | __u8 pad2; | ||
657 | __u8 station_id; | ||
658 | __le16 amsdu_enabled; | ||
659 | } __attribute__((packed)); | ||
660 | |||
661 | /* Inline functions to manipulate QoS field in data descriptor. */ | ||
662 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) | ||
663 | { | ||
664 | u16 val_mask = 1 << 4; | ||
665 | |||
666 | /* End of Service Period Bit 4 */ | ||
667 | return qos | val_mask; | ||
668 | } | ||
669 | |||
670 | static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) | ||
671 | { | ||
672 | u16 val_mask = 0x3; | ||
673 | u8 shift = 5; | ||
674 | u16 qos_mask = ~(val_mask << shift); | ||
675 | |||
676 | /* Ack Policy Bit 5-6 */ | ||
677 | return (qos & qos_mask) | ((ack_policy & val_mask) << shift); | ||
678 | } | ||
679 | |||
680 | static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) | ||
681 | { | ||
682 | u16 val_mask = 1 << 7; | ||
683 | |||
684 | /* AMSDU present Bit 7 */ | ||
685 | return qos | val_mask; | ||
686 | } | ||
687 | |||
688 | static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) | ||
689 | { | ||
690 | u16 val_mask = 0xff; | ||
691 | u8 shift = 8; | ||
692 | u16 qos_mask = ~(val_mask << shift); | ||
693 | |||
694 | /* Queue Length Bits 8-15 */ | ||
695 | return (qos & qos_mask) | ((len & val_mask) << shift); | ||
696 | } | ||
697 | |||
698 | /* DMA header used by firmware and hardware. */ | 600 | /* DMA header used by firmware and hardware. */ |
699 | struct mwl8k_dma_data { | 601 | struct mwl8k_dma_data { |
700 | __le16 fwlen; | 602 | __le16 fwlen; |
@@ -761,9 +663,9 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) | |||
761 | 663 | ||
762 | 664 | ||
763 | /* | 665 | /* |
764 | * Packet reception for 88w8366. | 666 | * Packet reception for 88w8366 AP firmware. |
765 | */ | 667 | */ |
766 | struct mwl8k_rxd_8366 { | 668 | struct mwl8k_rxd_8366_ap { |
767 | __le16 pkt_len; | 669 | __le16 pkt_len; |
768 | __u8 sq2; | 670 | __u8 sq2; |
769 | __u8 rate; | 671 | __u8 rate; |
@@ -781,23 +683,23 @@ struct mwl8k_rxd_8366 { | |||
781 | __u8 rx_ctrl; | 683 | __u8 rx_ctrl; |
782 | } __attribute__((packed)); | 684 | } __attribute__((packed)); |
783 | 685 | ||
784 | #define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80 | 686 | #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 |
785 | #define MWL8K_8366_RATE_INFO_40MHZ 0x40 | 687 | #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 |
786 | #define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f) | 688 | #define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) |
787 | 689 | ||
788 | #define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 | 690 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
789 | 691 | ||
790 | static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) | 692 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
791 | { | 693 | { |
792 | struct mwl8k_rxd_8366 *rxd = _rxd; | 694 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
793 | 695 | ||
794 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 696 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
795 | rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST; | 697 | rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; |
796 | } | 698 | } |
797 | 699 | ||
798 | static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | 700 | static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) |
799 | { | 701 | { |
800 | struct mwl8k_rxd_8366 *rxd = _rxd; | 702 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
801 | 703 | ||
802 | rxd->pkt_len = cpu_to_le16(len); | 704 | rxd->pkt_len = cpu_to_le16(len); |
803 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 705 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -806,12 +708,12 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | |||
806 | } | 708 | } |
807 | 709 | ||
808 | static int | 710 | static int |
809 | mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | 711 | mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, |
810 | __le16 *qos) | 712 | __le16 *qos) |
811 | { | 713 | { |
812 | struct mwl8k_rxd_8366 *rxd = _rxd; | 714 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
813 | 715 | ||
814 | if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST)) | 716 | if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) |
815 | return -1; | 717 | return -1; |
816 | rmb(); | 718 | rmb(); |
817 | 719 | ||
@@ -820,11 +722,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
820 | status->signal = -rxd->rssi; | 722 | status->signal = -rxd->rssi; |
821 | status->noise = -rxd->noise_floor; | 723 | status->noise = -rxd->noise_floor; |
822 | 724 | ||
823 | if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) { | 725 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { |
824 | status->flag |= RX_FLAG_HT; | 726 | status->flag |= RX_FLAG_HT; |
825 | if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ) | 727 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) |
826 | status->flag |= RX_FLAG_40MHZ; | 728 | status->flag |= RX_FLAG_40MHZ; |
827 | status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate); | 729 | status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); |
828 | } else { | 730 | } else { |
829 | int i; | 731 | int i; |
830 | 732 | ||
@@ -844,17 +746,17 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
844 | return le16_to_cpu(rxd->pkt_len); | 746 | return le16_to_cpu(rxd->pkt_len); |
845 | } | 747 | } |
846 | 748 | ||
847 | static struct rxd_ops rxd_8366_ops = { | 749 | static struct rxd_ops rxd_8366_ap_ops = { |
848 | .rxd_size = sizeof(struct mwl8k_rxd_8366), | 750 | .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), |
849 | .rxd_init = mwl8k_rxd_8366_init, | 751 | .rxd_init = mwl8k_rxd_8366_ap_init, |
850 | .rxd_refill = mwl8k_rxd_8366_refill, | 752 | .rxd_refill = mwl8k_rxd_8366_ap_refill, |
851 | .rxd_process = mwl8k_rxd_8366_process, | 753 | .rxd_process = mwl8k_rxd_8366_ap_process, |
852 | }; | 754 | }; |
853 | 755 | ||
854 | /* | 756 | /* |
855 | * Packet reception for 88w8687. | 757 | * Packet reception for STA firmware. |
856 | */ | 758 | */ |
857 | struct mwl8k_rxd_8687 { | 759 | struct mwl8k_rxd_sta { |
858 | __le16 pkt_len; | 760 | __le16 pkt_len; |
859 | __u8 link_quality; | 761 | __u8 link_quality; |
860 | __u8 noise_level; | 762 | __u8 noise_level; |
@@ -871,26 +773,26 @@ struct mwl8k_rxd_8687 { | |||
871 | __u8 pad2[2]; | 773 | __u8 pad2[2]; |
872 | } __attribute__((packed)); | 774 | } __attribute__((packed)); |
873 | 775 | ||
874 | #define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000 | 776 | #define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 |
875 | #define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) | 777 | #define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) |
876 | #define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) | 778 | #define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) |
877 | #define MWL8K_8687_RATE_INFO_40MHZ 0x0004 | 779 | #define MWL8K_STA_RATE_INFO_40MHZ 0x0004 |
878 | #define MWL8K_8687_RATE_INFO_SHORTGI 0x0002 | 780 | #define MWL8K_STA_RATE_INFO_SHORTGI 0x0002 |
879 | #define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001 | 781 | #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 |
880 | 782 | ||
881 | #define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02 | 783 | #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 |
882 | 784 | ||
883 | static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr) | 785 | static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) |
884 | { | 786 | { |
885 | struct mwl8k_rxd_8687 *rxd = _rxd; | 787 | struct mwl8k_rxd_sta *rxd = _rxd; |
886 | 788 | ||
887 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 789 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
888 | rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST; | 790 | rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST; |
889 | } | 791 | } |
890 | 792 | ||
891 | static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | 793 | static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) |
892 | { | 794 | { |
893 | struct mwl8k_rxd_8687 *rxd = _rxd; | 795 | struct mwl8k_rxd_sta *rxd = _rxd; |
894 | 796 | ||
895 | rxd->pkt_len = cpu_to_le16(len); | 797 | rxd->pkt_len = cpu_to_le16(len); |
896 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 798 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -899,13 +801,13 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | |||
899 | } | 801 | } |
900 | 802 | ||
901 | static int | 803 | static int |
902 | mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | 804 | mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, |
903 | __le16 *qos) | 805 | __le16 *qos) |
904 | { | 806 | { |
905 | struct mwl8k_rxd_8687 *rxd = _rxd; | 807 | struct mwl8k_rxd_sta *rxd = _rxd; |
906 | u16 rate_info; | 808 | u16 rate_info; |
907 | 809 | ||
908 | if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST)) | 810 | if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST)) |
909 | return -1; | 811 | return -1; |
910 | rmb(); | 812 | rmb(); |
911 | 813 | ||
@@ -915,16 +817,16 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
915 | 817 | ||
916 | status->signal = -rxd->rssi; | 818 | status->signal = -rxd->rssi; |
917 | status->noise = -rxd->noise_level; | 819 | status->noise = -rxd->noise_level; |
918 | status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); | 820 | status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); |
919 | status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); | 821 | status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); |
920 | 822 | ||
921 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE) | 823 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE) |
922 | status->flag |= RX_FLAG_SHORTPRE; | 824 | status->flag |= RX_FLAG_SHORTPRE; |
923 | if (rate_info & MWL8K_8687_RATE_INFO_40MHZ) | 825 | if (rate_info & MWL8K_STA_RATE_INFO_40MHZ) |
924 | status->flag |= RX_FLAG_40MHZ; | 826 | status->flag |= RX_FLAG_40MHZ; |
925 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI) | 827 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI) |
926 | status->flag |= RX_FLAG_SHORT_GI; | 828 | status->flag |= RX_FLAG_SHORT_GI; |
927 | if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT) | 829 | if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) |
928 | status->flag |= RX_FLAG_HT; | 830 | status->flag |= RX_FLAG_HT; |
929 | 831 | ||
930 | status->band = IEEE80211_BAND_2GHZ; | 832 | status->band = IEEE80211_BAND_2GHZ; |
@@ -935,11 +837,11 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
935 | return le16_to_cpu(rxd->pkt_len); | 837 | return le16_to_cpu(rxd->pkt_len); |
936 | } | 838 | } |
937 | 839 | ||
938 | static struct rxd_ops rxd_8687_ops = { | 840 | static struct rxd_ops rxd_sta_ops = { |
939 | .rxd_size = sizeof(struct mwl8k_rxd_8687), | 841 | .rxd_size = sizeof(struct mwl8k_rxd_sta), |
940 | .rxd_init = mwl8k_rxd_8687_init, | 842 | .rxd_init = mwl8k_rxd_sta_init, |
941 | .rxd_refill = mwl8k_rxd_8687_refill, | 843 | .rxd_refill = mwl8k_rxd_sta_refill, |
942 | .rxd_process = mwl8k_rxd_8687_process, | 844 | .rxd_process = mwl8k_rxd_sta_process, |
943 | }; | 845 | }; |
944 | 846 | ||
945 | 847 | ||
@@ -1153,16 +1055,18 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1153 | * Packet transmission. | 1055 | * Packet transmission. |
1154 | */ | 1056 | */ |
1155 | 1057 | ||
1156 | /* Transmit packet ACK policy */ | ||
1157 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 | ||
1158 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 | ||
1159 | |||
1160 | #define MWL8K_TXD_STATUS_OK 0x00000001 | 1058 | #define MWL8K_TXD_STATUS_OK 0x00000001 |
1161 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 | 1059 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 |
1162 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 | 1060 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 |
1163 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 | 1061 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 |
1164 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 | 1062 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 |
1165 | 1063 | ||
1064 | #define MWL8K_QOS_QLEN_UNSPEC 0xff00 | ||
1065 | #define MWL8K_QOS_ACK_POLICY_MASK 0x0060 | ||
1066 | #define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000 | ||
1067 | #define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060 | ||
1068 | #define MWL8K_QOS_EOSP 0x0010 | ||
1069 | |||
1166 | struct mwl8k_tx_desc { | 1070 | struct mwl8k_tx_desc { |
1167 | __le32 status; | 1071 | __le32 status; |
1168 | __u8 data_rate; | 1072 | __u8 data_rate; |
@@ -1316,8 +1220,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | |||
1316 | } | 1220 | } |
1317 | 1221 | ||
1318 | if (priv->pending_tx_pkts < oldcount) { | 1222 | if (priv->pending_tx_pkts < oldcount) { |
1319 | printk(KERN_NOTICE "%s: timeout waiting for tx " | 1223 | printk(KERN_NOTICE "%s: waiting for tx rings " |
1320 | "rings to drain (%d -> %d pkts), retrying\n", | 1224 | "to drain (%d -> %d pkts)\n", |
1321 | wiphy_name(hw->wiphy), oldcount, | 1225 | wiphy_name(hw->wiphy), oldcount, |
1322 | priv->pending_tx_pkts); | 1226 | priv->pending_tx_pkts); |
1323 | retry = 1; | 1227 | retry = 1; |
@@ -1459,24 +1363,17 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1459 | if (ieee80211_is_mgmt(wh->frame_control) || | 1363 | if (ieee80211_is_mgmt(wh->frame_control) || |
1460 | ieee80211_is_ctl(wh->frame_control)) { | 1364 | ieee80211_is_ctl(wh->frame_control)) { |
1461 | txdatarate = 0; | 1365 | txdatarate = 0; |
1462 | qos = mwl8k_qos_setbit_eosp(qos); | 1366 | qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP; |
1463 | /* Set Queue size to unspecified */ | ||
1464 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1465 | } else if (ieee80211_is_data(wh->frame_control)) { | 1367 | } else if (ieee80211_is_data(wh->frame_control)) { |
1466 | txdatarate = 1; | 1368 | txdatarate = 1; |
1467 | if (is_multicast_ether_addr(wh->addr1)) | 1369 | if (is_multicast_ether_addr(wh->addr1)) |
1468 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; | 1370 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; |
1469 | 1371 | ||
1470 | /* Send pkt in an aggregate if AMPDU frame. */ | 1372 | qos &= ~MWL8K_QOS_ACK_POLICY_MASK; |
1471 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | 1373 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) |
1472 | qos = mwl8k_qos_setbit_ack(qos, | 1374 | qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK; |
1473 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1474 | else | 1375 | else |
1475 | qos = mwl8k_qos_setbit_ack(qos, | 1376 | qos |= MWL8K_QOS_ACK_POLICY_NORMAL; |
1476 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1477 | |||
1478 | if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
1479 | qos = mwl8k_qos_setbit_amsdu(qos); | ||
1480 | } | 1377 | } |
1481 | 1378 | ||
1482 | dma = pci_map_single(priv->pdev, skb->data, | 1379 | dma = pci_map_single(priv->pdev, skb->data, |
@@ -1503,7 +1400,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1503 | tx->pkt_phys_addr = cpu_to_le32(dma); | 1400 | tx->pkt_phys_addr = cpu_to_le32(dma); |
1504 | tx->pkt_len = cpu_to_le16(skb->len); | 1401 | tx->pkt_len = cpu_to_le16(skb->len); |
1505 | tx->rate_info = 0; | 1402 | tx->rate_info = 0; |
1506 | tx->peer_id = mwl8k_vif->peer_id; | 1403 | if (!priv->ap_fw && tx_info->control.sta != NULL) |
1404 | tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; | ||
1405 | else | ||
1406 | tx->peer_id = 0; | ||
1507 | wmb(); | 1407 | wmb(); |
1508 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); | 1408 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); |
1509 | 1409 | ||
@@ -1678,6 +1578,68 @@ struct mwl8k_cmd_get_hw_spec_sta { | |||
1678 | __le32 total_rxd; | 1578 | __le32 total_rxd; |
1679 | } __attribute__((packed)); | 1579 | } __attribute__((packed)); |
1680 | 1580 | ||
1581 | #define MWL8K_CAP_MAX_AMSDU 0x20000000 | ||
1582 | #define MWL8K_CAP_GREENFIELD 0x08000000 | ||
1583 | #define MWL8K_CAP_AMPDU 0x04000000 | ||
1584 | #define MWL8K_CAP_RX_STBC 0x01000000 | ||
1585 | #define MWL8K_CAP_TX_STBC 0x00800000 | ||
1586 | #define MWL8K_CAP_SHORTGI_40MHZ 0x00400000 | ||
1587 | #define MWL8K_CAP_SHORTGI_20MHZ 0x00200000 | ||
1588 | #define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000 | ||
1589 | #define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000 | ||
1590 | #define MWL8K_CAP_DELAY_BA 0x00003000 | ||
1591 | #define MWL8K_CAP_MIMO 0x00000200 | ||
1592 | #define MWL8K_CAP_40MHZ 0x00000100 | ||
1593 | |||
1594 | static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) | ||
1595 | { | ||
1596 | struct mwl8k_priv *priv = hw->priv; | ||
1597 | int rx_streams; | ||
1598 | int tx_streams; | ||
1599 | |||
1600 | priv->band.ht_cap.ht_supported = 1; | ||
1601 | |||
1602 | if (cap & MWL8K_CAP_MAX_AMSDU) | ||
1603 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1604 | if (cap & MWL8K_CAP_GREENFIELD) | ||
1605 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1606 | if (cap & MWL8K_CAP_AMPDU) { | ||
1607 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
1608 | priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
1609 | priv->band.ht_cap.ampdu_density = | ||
1610 | IEEE80211_HT_MPDU_DENSITY_NONE; | ||
1611 | } | ||
1612 | if (cap & MWL8K_CAP_RX_STBC) | ||
1613 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; | ||
1614 | if (cap & MWL8K_CAP_TX_STBC) | ||
1615 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
1616 | if (cap & MWL8K_CAP_SHORTGI_40MHZ) | ||
1617 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
1618 | if (cap & MWL8K_CAP_SHORTGI_20MHZ) | ||
1619 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
1620 | if (cap & MWL8K_CAP_DELAY_BA) | ||
1621 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; | ||
1622 | if (cap & MWL8K_CAP_40MHZ) | ||
1623 | priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1624 | |||
1625 | rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); | ||
1626 | tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); | ||
1627 | |||
1628 | priv->band.ht_cap.mcs.rx_mask[0] = 0xff; | ||
1629 | if (rx_streams >= 2) | ||
1630 | priv->band.ht_cap.mcs.rx_mask[1] = 0xff; | ||
1631 | if (rx_streams >= 3) | ||
1632 | priv->band.ht_cap.mcs.rx_mask[2] = 0xff; | ||
1633 | priv->band.ht_cap.mcs.rx_mask[4] = 0x01; | ||
1634 | priv->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1635 | |||
1636 | if (rx_streams != tx_streams) { | ||
1637 | priv->band.ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1638 | priv->band.ht_cap.mcs.tx_params |= (tx_streams - 1) << | ||
1639 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
1640 | } | ||
1641 | } | ||
1642 | |||
1681 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | 1643 | static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) |
1682 | { | 1644 | { |
1683 | struct mwl8k_priv *priv = hw->priv; | 1645 | struct mwl8k_priv *priv = hw->priv; |
@@ -1708,6 +1670,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | |||
1708 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1670 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1709 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1671 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
1710 | priv->hw_rev = cmd->hw_rev; | 1672 | priv->hw_rev = cmd->hw_rev; |
1673 | if (cmd->caps & cpu_to_le32(MWL8K_CAP_MIMO)) | ||
1674 | mwl8k_set_ht_caps(hw, le32_to_cpu(cmd->caps)); | ||
1711 | } | 1675 | } |
1712 | 1676 | ||
1713 | kfree(cmd); | 1677 | kfree(cmd); |
@@ -1897,9 +1861,9 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, | |||
1897 | } | 1861 | } |
1898 | 1862 | ||
1899 | /* | 1863 | /* |
1900 | * CMD_802_11_GET_STAT. | 1864 | * CMD_GET_STAT. |
1901 | */ | 1865 | */ |
1902 | struct mwl8k_cmd_802_11_get_stat { | 1866 | struct mwl8k_cmd_get_stat { |
1903 | struct mwl8k_cmd_pkt header; | 1867 | struct mwl8k_cmd_pkt header; |
1904 | __le32 stats[64]; | 1868 | __le32 stats[64]; |
1905 | } __attribute__((packed)); | 1869 | } __attribute__((packed)); |
@@ -1909,10 +1873,10 @@ struct mwl8k_cmd_802_11_get_stat { | |||
1909 | #define MWL8K_STAT_FCS_ERROR 24 | 1873 | #define MWL8K_STAT_FCS_ERROR 24 |
1910 | #define MWL8K_STAT_RTS_SUCCESS 11 | 1874 | #define MWL8K_STAT_RTS_SUCCESS 11 |
1911 | 1875 | ||
1912 | static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | 1876 | static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw, |
1913 | struct ieee80211_low_level_stats *stats) | 1877 | struct ieee80211_low_level_stats *stats) |
1914 | { | 1878 | { |
1915 | struct mwl8k_cmd_802_11_get_stat *cmd; | 1879 | struct mwl8k_cmd_get_stat *cmd; |
1916 | int rc; | 1880 | int rc; |
1917 | 1881 | ||
1918 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1882 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -1939,9 +1903,9 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | |||
1939 | } | 1903 | } |
1940 | 1904 | ||
1941 | /* | 1905 | /* |
1942 | * CMD_802_11_RADIO_CONTROL. | 1906 | * CMD_RADIO_CONTROL. |
1943 | */ | 1907 | */ |
1944 | struct mwl8k_cmd_802_11_radio_control { | 1908 | struct mwl8k_cmd_radio_control { |
1945 | struct mwl8k_cmd_pkt header; | 1909 | struct mwl8k_cmd_pkt header; |
1946 | __le16 action; | 1910 | __le16 action; |
1947 | __le16 control; | 1911 | __le16 control; |
@@ -1949,10 +1913,10 @@ struct mwl8k_cmd_802_11_radio_control { | |||
1949 | } __attribute__((packed)); | 1913 | } __attribute__((packed)); |
1950 | 1914 | ||
1951 | static int | 1915 | static int |
1952 | mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | 1916 | mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) |
1953 | { | 1917 | { |
1954 | struct mwl8k_priv *priv = hw->priv; | 1918 | struct mwl8k_priv *priv = hw->priv; |
1955 | struct mwl8k_cmd_802_11_radio_control *cmd; | 1919 | struct mwl8k_cmd_radio_control *cmd; |
1956 | int rc; | 1920 | int rc; |
1957 | 1921 | ||
1958 | if (enable == priv->radio_on && !force) | 1922 | if (enable == priv->radio_on && !force) |
@@ -1977,36 +1941,32 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | |||
1977 | return rc; | 1941 | return rc; |
1978 | } | 1942 | } |
1979 | 1943 | ||
1980 | static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) | 1944 | static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw) |
1981 | { | 1945 | { |
1982 | return mwl8k_cmd_802_11_radio_control(hw, 0, 0); | 1946 | return mwl8k_cmd_radio_control(hw, 0, 0); |
1983 | } | 1947 | } |
1984 | 1948 | ||
1985 | static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) | 1949 | static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) |
1986 | { | 1950 | { |
1987 | return mwl8k_cmd_802_11_radio_control(hw, 1, 0); | 1951 | return mwl8k_cmd_radio_control(hw, 1, 0); |
1988 | } | 1952 | } |
1989 | 1953 | ||
1990 | static int | 1954 | static int |
1991 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | 1955 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) |
1992 | { | 1956 | { |
1993 | struct mwl8k_priv *priv; | 1957 | struct mwl8k_priv *priv = hw->priv; |
1994 | |||
1995 | if (hw == NULL || hw->priv == NULL) | ||
1996 | return -EINVAL; | ||
1997 | priv = hw->priv; | ||
1998 | 1958 | ||
1999 | priv->radio_short_preamble = short_preamble; | 1959 | priv->radio_short_preamble = short_preamble; |
2000 | 1960 | ||
2001 | return mwl8k_cmd_802_11_radio_control(hw, 1, 1); | 1961 | return mwl8k_cmd_radio_control(hw, 1, 1); |
2002 | } | 1962 | } |
2003 | 1963 | ||
2004 | /* | 1964 | /* |
2005 | * CMD_802_11_RF_TX_POWER. | 1965 | * CMD_RF_TX_POWER. |
2006 | */ | 1966 | */ |
2007 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 | 1967 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 |
2008 | 1968 | ||
2009 | struct mwl8k_cmd_802_11_rf_tx_power { | 1969 | struct mwl8k_cmd_rf_tx_power { |
2010 | struct mwl8k_cmd_pkt header; | 1970 | struct mwl8k_cmd_pkt header; |
2011 | __le16 action; | 1971 | __le16 action; |
2012 | __le16 support_level; | 1972 | __le16 support_level; |
@@ -2015,9 +1975,9 @@ struct mwl8k_cmd_802_11_rf_tx_power { | |||
2015 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; | 1975 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; |
2016 | } __attribute__((packed)); | 1976 | } __attribute__((packed)); |
2017 | 1977 | ||
2018 | static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) | 1978 | static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) |
2019 | { | 1979 | { |
2020 | struct mwl8k_cmd_802_11_rf_tx_power *cmd; | 1980 | struct mwl8k_cmd_rf_tx_power *cmd; |
2021 | int rc; | 1981 | int rc; |
2022 | 1982 | ||
2023 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1983 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -2103,7 +2063,7 @@ struct mwl8k_cmd_set_post_scan { | |||
2103 | } __attribute__((packed)); | 2063 | } __attribute__((packed)); |
2104 | 2064 | ||
2105 | static int | 2065 | static int |
2106 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) | 2066 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac) |
2107 | { | 2067 | { |
2108 | struct mwl8k_cmd_set_post_scan *cmd; | 2068 | struct mwl8k_cmd_set_post_scan *cmd; |
2109 | int rc; | 2069 | int rc; |
@@ -2134,8 +2094,9 @@ struct mwl8k_cmd_set_rf_channel { | |||
2134 | } __attribute__((packed)); | 2094 | } __attribute__((packed)); |
2135 | 2095 | ||
2136 | static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | 2096 | static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, |
2137 | struct ieee80211_channel *channel) | 2097 | struct ieee80211_conf *conf) |
2138 | { | 2098 | { |
2099 | struct ieee80211_channel *channel = conf->channel; | ||
2139 | struct mwl8k_cmd_set_rf_channel *cmd; | 2100 | struct mwl8k_cmd_set_rf_channel *cmd; |
2140 | int rc; | 2101 | int rc; |
2141 | 2102 | ||
@@ -2147,10 +2108,17 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | |||
2147 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2108 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2148 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 2109 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2149 | cmd->current_channel = channel->hw_value; | 2110 | cmd->current_channel = channel->hw_value; |
2111 | |||
2150 | if (channel->band == IEEE80211_BAND_2GHZ) | 2112 | if (channel->band == IEEE80211_BAND_2GHZ) |
2151 | cmd->channel_flags = cpu_to_le32(0x00000081); | 2113 | cmd->channel_flags |= cpu_to_le32(0x00000001); |
2152 | else | 2114 | |
2153 | cmd->channel_flags = cpu_to_le32(0x00000000); | 2115 | if (conf->channel_type == NL80211_CHAN_NO_HT || |
2116 | conf->channel_type == NL80211_CHAN_HT20) | ||
2117 | cmd->channel_flags |= cpu_to_le32(0x00000080); | ||
2118 | else if (conf->channel_type == NL80211_CHAN_HT40MINUS) | ||
2119 | cmd->channel_flags |= cpu_to_le32(0x000001900); | ||
2120 | else if (conf->channel_type == NL80211_CHAN_HT40PLUS) | ||
2121 | cmd->channel_flags |= cpu_to_le32(0x000000900); | ||
2154 | 2122 | ||
2155 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2123 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2156 | kfree(cmd); | 2124 | kfree(cmd); |
@@ -2159,85 +2127,75 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | |||
2159 | } | 2127 | } |
2160 | 2128 | ||
2161 | /* | 2129 | /* |
2162 | * CMD_SET_SLOT. | 2130 | * CMD_SET_AID. |
2163 | */ | 2131 | */ |
2164 | struct mwl8k_cmd_set_slot { | 2132 | #define MWL8K_FRAME_PROT_DISABLED 0x00 |
2165 | struct mwl8k_cmd_pkt header; | 2133 | #define MWL8K_FRAME_PROT_11G 0x07 |
2166 | __le16 action; | 2134 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 |
2167 | __u8 short_slot; | 2135 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 |
2168 | } __attribute__((packed)); | ||
2169 | |||
2170 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) | ||
2171 | { | ||
2172 | struct mwl8k_cmd_set_slot *cmd; | ||
2173 | int rc; | ||
2174 | |||
2175 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2176 | if (cmd == NULL) | ||
2177 | return -ENOMEM; | ||
2178 | |||
2179 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); | ||
2180 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2181 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2182 | cmd->short_slot = short_slot_time; | ||
2183 | |||
2184 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2185 | kfree(cmd); | ||
2186 | 2136 | ||
2187 | return rc; | 2137 | struct mwl8k_cmd_update_set_aid { |
2188 | } | 2138 | struct mwl8k_cmd_pkt header; |
2139 | __le16 aid; | ||
2189 | 2140 | ||
2190 | /* | 2141 | /* AP's MAC address (BSSID) */ |
2191 | * CMD_MIMO_CONFIG. | 2142 | __u8 bssid[ETH_ALEN]; |
2192 | */ | 2143 | __le16 protection_mode; |
2193 | struct mwl8k_cmd_mimo_config { | 2144 | __u8 supp_rates[14]; |
2194 | struct mwl8k_cmd_pkt header; | ||
2195 | __le32 action; | ||
2196 | __u8 rx_antenna_map; | ||
2197 | __u8 tx_antenna_map; | ||
2198 | } __attribute__((packed)); | 2145 | } __attribute__((packed)); |
2199 | 2146 | ||
2200 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) | 2147 | static void legacy_rate_mask_to_array(u8 *rates, u32 mask) |
2201 | { | 2148 | { |
2202 | struct mwl8k_cmd_mimo_config *cmd; | 2149 | int i; |
2203 | int rc; | 2150 | int j; |
2204 | |||
2205 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2206 | if (cmd == NULL) | ||
2207 | return -ENOMEM; | ||
2208 | |||
2209 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); | ||
2210 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2211 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); | ||
2212 | cmd->rx_antenna_map = rx; | ||
2213 | cmd->tx_antenna_map = tx; | ||
2214 | 2151 | ||
2215 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2152 | /* |
2216 | kfree(cmd); | 2153 | * Clear nonstandard rates 4 and 13. |
2154 | */ | ||
2155 | mask &= 0x1fef; | ||
2217 | 2156 | ||
2218 | return rc; | 2157 | for (i = 0, j = 0; i < 14; i++) { |
2158 | if (mask & (1 << i)) | ||
2159 | rates[j++] = mwl8k_rates[i].hw_value; | ||
2160 | } | ||
2219 | } | 2161 | } |
2220 | 2162 | ||
2221 | /* | 2163 | static int |
2222 | * CMD_ENABLE_SNIFFER. | 2164 | mwl8k_cmd_set_aid(struct ieee80211_hw *hw, |
2223 | */ | 2165 | struct ieee80211_vif *vif, u32 legacy_rate_mask) |
2224 | struct mwl8k_cmd_enable_sniffer { | ||
2225 | struct mwl8k_cmd_pkt header; | ||
2226 | __le32 action; | ||
2227 | } __attribute__((packed)); | ||
2228 | |||
2229 | static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2230 | { | 2166 | { |
2231 | struct mwl8k_cmd_enable_sniffer *cmd; | 2167 | struct mwl8k_cmd_update_set_aid *cmd; |
2168 | u16 prot_mode; | ||
2232 | int rc; | 2169 | int rc; |
2233 | 2170 | ||
2234 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2171 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2235 | if (cmd == NULL) | 2172 | if (cmd == NULL) |
2236 | return -ENOMEM; | 2173 | return -ENOMEM; |
2237 | 2174 | ||
2238 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | 2175 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); |
2239 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2176 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2240 | cmd->action = cpu_to_le32(!!enable); | 2177 | cmd->aid = cpu_to_le16(vif->bss_conf.aid); |
2178 | memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); | ||
2179 | |||
2180 | if (vif->bss_conf.use_cts_prot) { | ||
2181 | prot_mode = MWL8K_FRAME_PROT_11G; | ||
2182 | } else { | ||
2183 | switch (vif->bss_conf.ht_operation_mode & | ||
2184 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2185 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2186 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2187 | break; | ||
2188 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2189 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2190 | break; | ||
2191 | default: | ||
2192 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2193 | break; | ||
2194 | } | ||
2195 | } | ||
2196 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2197 | |||
2198 | legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask); | ||
2241 | 2199 | ||
2242 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2200 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2243 | kfree(cmd); | 2201 | kfree(cmd); |
@@ -2246,37 +2204,32 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
2246 | } | 2204 | } |
2247 | 2205 | ||
2248 | /* | 2206 | /* |
2249 | * CMD_SET_MAC_ADDR. | 2207 | * CMD_SET_RATE. |
2250 | */ | 2208 | */ |
2251 | struct mwl8k_cmd_set_mac_addr { | 2209 | struct mwl8k_cmd_set_rate { |
2252 | struct mwl8k_cmd_pkt header; | 2210 | struct mwl8k_cmd_pkt header; |
2253 | union { | 2211 | __u8 legacy_rates[14]; |
2254 | struct { | 2212 | |
2255 | __le16 mac_type; | 2213 | /* Bitmap for supported MCS codes. */ |
2256 | __u8 mac_addr[ETH_ALEN]; | 2214 | __u8 mcs_set[16]; |
2257 | } mbss; | 2215 | __u8 reserved[16]; |
2258 | __u8 mac_addr[ETH_ALEN]; | ||
2259 | }; | ||
2260 | } __attribute__((packed)); | 2216 | } __attribute__((packed)); |
2261 | 2217 | ||
2262 | static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | 2218 | static int |
2219 | mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2220 | u32 legacy_rate_mask, u8 *mcs_rates) | ||
2263 | { | 2221 | { |
2264 | struct mwl8k_priv *priv = hw->priv; | 2222 | struct mwl8k_cmd_set_rate *cmd; |
2265 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2266 | int rc; | 2223 | int rc; |
2267 | 2224 | ||
2268 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2225 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2269 | if (cmd == NULL) | 2226 | if (cmd == NULL) |
2270 | return -ENOMEM; | 2227 | return -ENOMEM; |
2271 | 2228 | ||
2272 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | 2229 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); |
2273 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2230 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2274 | if (priv->ap_fw) { | 2231 | legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); |
2275 | cmd->mbss.mac_type = 0; | 2232 | memcpy(cmd->mcs_set, mcs_rates, 16); |
2276 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2277 | } else { | ||
2278 | memcpy(cmd->mac_addr, mac, ETH_ALEN); | ||
2279 | } | ||
2280 | 2233 | ||
2281 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2234 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2282 | kfree(cmd); | 2235 | kfree(cmd); |
@@ -2284,29 +2237,40 @@ static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | |||
2284 | return rc; | 2237 | return rc; |
2285 | } | 2238 | } |
2286 | 2239 | ||
2287 | |||
2288 | /* | 2240 | /* |
2289 | * CMD_SET_RATEADAPT_MODE. | 2241 | * CMD_FINALIZE_JOIN. |
2290 | */ | 2242 | */ |
2291 | struct mwl8k_cmd_set_rate_adapt_mode { | 2243 | #define MWL8K_FJ_BEACON_MAXLEN 128 |
2244 | |||
2245 | struct mwl8k_cmd_finalize_join { | ||
2292 | struct mwl8k_cmd_pkt header; | 2246 | struct mwl8k_cmd_pkt header; |
2293 | __le16 action; | 2247 | __le32 sleep_interval; /* Number of beacon periods to sleep */ |
2294 | __le16 mode; | 2248 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; |
2295 | } __attribute__((packed)); | 2249 | } __attribute__((packed)); |
2296 | 2250 | ||
2297 | static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | 2251 | static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, |
2252 | int framelen, int dtim) | ||
2298 | { | 2253 | { |
2299 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | 2254 | struct mwl8k_cmd_finalize_join *cmd; |
2255 | struct ieee80211_mgmt *payload = frame; | ||
2256 | int payload_len; | ||
2300 | int rc; | 2257 | int rc; |
2301 | 2258 | ||
2302 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2259 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2303 | if (cmd == NULL) | 2260 | if (cmd == NULL) |
2304 | return -ENOMEM; | 2261 | return -ENOMEM; |
2305 | 2262 | ||
2306 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | 2263 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); |
2307 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2264 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2308 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 2265 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); |
2309 | cmd->mode = cpu_to_le16(mode); | 2266 | |
2267 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2268 | if (payload_len < 0) | ||
2269 | payload_len = 0; | ||
2270 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2271 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2272 | |||
2273 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2310 | 2274 | ||
2311 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2275 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2312 | kfree(cmd); | 2276 | kfree(cmd); |
@@ -2315,59 +2279,57 @@ static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | |||
2315 | } | 2279 | } |
2316 | 2280 | ||
2317 | /* | 2281 | /* |
2318 | * CMD_SET_WMM_MODE. | 2282 | * CMD_SET_RTS_THRESHOLD. |
2319 | */ | 2283 | */ |
2320 | struct mwl8k_cmd_set_wmm { | 2284 | struct mwl8k_cmd_set_rts_threshold { |
2321 | struct mwl8k_cmd_pkt header; | 2285 | struct mwl8k_cmd_pkt header; |
2322 | __le16 action; | 2286 | __le16 action; |
2287 | __le16 threshold; | ||
2323 | } __attribute__((packed)); | 2288 | } __attribute__((packed)); |
2324 | 2289 | ||
2325 | static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) | 2290 | static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, |
2291 | u16 action, u16 threshold) | ||
2326 | { | 2292 | { |
2327 | struct mwl8k_priv *priv = hw->priv; | 2293 | struct mwl8k_cmd_set_rts_threshold *cmd; |
2328 | struct mwl8k_cmd_set_wmm *cmd; | ||
2329 | int rc; | 2294 | int rc; |
2330 | 2295 | ||
2331 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2296 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2332 | if (cmd == NULL) | 2297 | if (cmd == NULL) |
2333 | return -ENOMEM; | 2298 | return -ENOMEM; |
2334 | 2299 | ||
2335 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); | 2300 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); |
2336 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2301 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2337 | cmd->action = cpu_to_le16(!!enable); | 2302 | cmd->action = cpu_to_le16(action); |
2303 | cmd->threshold = cpu_to_le16(threshold); | ||
2338 | 2304 | ||
2339 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2305 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2340 | kfree(cmd); | 2306 | kfree(cmd); |
2341 | 2307 | ||
2342 | if (!rc) | ||
2343 | priv->wmm_enabled = enable; | ||
2344 | |||
2345 | return rc; | 2308 | return rc; |
2346 | } | 2309 | } |
2347 | 2310 | ||
2348 | /* | 2311 | /* |
2349 | * CMD_SET_RTS_THRESHOLD. | 2312 | * CMD_SET_SLOT. |
2350 | */ | 2313 | */ |
2351 | struct mwl8k_cmd_rts_threshold { | 2314 | struct mwl8k_cmd_set_slot { |
2352 | struct mwl8k_cmd_pkt header; | 2315 | struct mwl8k_cmd_pkt header; |
2353 | __le16 action; | 2316 | __le16 action; |
2354 | __le16 threshold; | 2317 | __u8 short_slot; |
2355 | } __attribute__((packed)); | 2318 | } __attribute__((packed)); |
2356 | 2319 | ||
2357 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | 2320 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) |
2358 | u16 action, u16 threshold) | ||
2359 | { | 2321 | { |
2360 | struct mwl8k_cmd_rts_threshold *cmd; | 2322 | struct mwl8k_cmd_set_slot *cmd; |
2361 | int rc; | 2323 | int rc; |
2362 | 2324 | ||
2363 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2325 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2364 | if (cmd == NULL) | 2326 | if (cmd == NULL) |
2365 | return -ENOMEM; | 2327 | return -ENOMEM; |
2366 | 2328 | ||
2367 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); | 2329 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); |
2368 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2330 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2369 | cmd->action = cpu_to_le16(action); | 2331 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2370 | cmd->threshold = cpu_to_le16(threshold); | 2332 | cmd->short_slot = short_slot_time; |
2371 | 2333 | ||
2372 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2334 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2373 | kfree(cmd); | 2335 | kfree(cmd); |
@@ -2426,9 +2388,9 @@ struct mwl8k_cmd_set_edca_params { | |||
2426 | MWL8K_SET_EDCA_AIFS) | 2388 | MWL8K_SET_EDCA_AIFS) |
2427 | 2389 | ||
2428 | static int | 2390 | static int |
2429 | mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | 2391 | mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, |
2430 | __u16 cw_min, __u16 cw_max, | 2392 | __u16 cw_min, __u16 cw_max, |
2431 | __u8 aifs, __u16 txop) | 2393 | __u8 aifs, __u16 txop) |
2432 | { | 2394 | { |
2433 | struct mwl8k_priv *priv = hw->priv; | 2395 | struct mwl8k_priv *priv = hw->priv; |
2434 | struct mwl8k_cmd_set_edca_params *cmd; | 2396 | struct mwl8k_cmd_set_edca_params *cmd; |
@@ -2467,202 +2429,60 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | |||
2467 | } | 2429 | } |
2468 | 2430 | ||
2469 | /* | 2431 | /* |
2470 | * CMD_FINALIZE_JOIN. | 2432 | * CMD_SET_WMM_MODE. |
2471 | */ | 2433 | */ |
2472 | #define MWL8K_FJ_BEACON_MAXLEN 128 | 2434 | struct mwl8k_cmd_set_wmm_mode { |
2473 | |||
2474 | struct mwl8k_cmd_finalize_join { | ||
2475 | struct mwl8k_cmd_pkt header; | 2435 | struct mwl8k_cmd_pkt header; |
2476 | __le32 sleep_interval; /* Number of beacon periods to sleep */ | 2436 | __le16 action; |
2477 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; | ||
2478 | } __attribute__((packed)); | 2437 | } __attribute__((packed)); |
2479 | 2438 | ||
2480 | static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | 2439 | static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) |
2481 | int framelen, int dtim) | ||
2482 | { | 2440 | { |
2483 | struct mwl8k_cmd_finalize_join *cmd; | 2441 | struct mwl8k_priv *priv = hw->priv; |
2484 | struct ieee80211_mgmt *payload = frame; | 2442 | struct mwl8k_cmd_set_wmm_mode *cmd; |
2485 | int payload_len; | ||
2486 | int rc; | 2443 | int rc; |
2487 | 2444 | ||
2488 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2445 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2489 | if (cmd == NULL) | 2446 | if (cmd == NULL) |
2490 | return -ENOMEM; | 2447 | return -ENOMEM; |
2491 | 2448 | ||
2492 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); | 2449 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); |
2493 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2450 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2494 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); | 2451 | cmd->action = cpu_to_le16(!!enable); |
2495 | |||
2496 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2497 | if (payload_len < 0) | ||
2498 | payload_len = 0; | ||
2499 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2500 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2501 | |||
2502 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2503 | 2452 | ||
2504 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2453 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2505 | kfree(cmd); | 2454 | kfree(cmd); |
2506 | 2455 | ||
2507 | return rc; | 2456 | if (!rc) |
2508 | } | 2457 | priv->wmm_enabled = enable; |
2509 | |||
2510 | /* | ||
2511 | * CMD_UPDATE_STADB. | ||
2512 | */ | ||
2513 | struct mwl8k_cmd_update_sta_db { | ||
2514 | struct mwl8k_cmd_pkt header; | ||
2515 | |||
2516 | /* See STADB_ACTION_TYPE */ | ||
2517 | __le32 action; | ||
2518 | |||
2519 | /* Peer MAC address */ | ||
2520 | __u8 peer_addr[ETH_ALEN]; | ||
2521 | |||
2522 | __le32 reserved; | ||
2523 | |||
2524 | /* Peer info - valid during add/update. */ | ||
2525 | struct peer_capability_info peer_info; | ||
2526 | } __attribute__((packed)); | ||
2527 | |||
2528 | static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | ||
2529 | struct ieee80211_vif *vif, __u32 action) | ||
2530 | { | ||
2531 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2532 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2533 | struct mwl8k_cmd_update_sta_db *cmd; | ||
2534 | struct peer_capability_info *peer_info; | ||
2535 | int rc; | ||
2536 | |||
2537 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2538 | if (cmd == NULL) | ||
2539 | return -ENOMEM; | ||
2540 | |||
2541 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2542 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2543 | |||
2544 | cmd->action = cpu_to_le32(action); | ||
2545 | peer_info = &cmd->peer_info; | ||
2546 | memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); | ||
2547 | |||
2548 | switch (action) { | ||
2549 | case MWL8K_STA_DB_ADD_ENTRY: | ||
2550 | case MWL8K_STA_DB_MODIFY_ENTRY: | ||
2551 | /* Build peer_info block */ | ||
2552 | peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2553 | peer_info->basic_caps = cpu_to_le16(info->assoc_capability); | ||
2554 | memcpy(peer_info->legacy_rates, mwl8k_rateids, | ||
2555 | sizeof(mwl8k_rateids)); | ||
2556 | peer_info->interop = 1; | ||
2557 | peer_info->amsdu_enabled = 0; | ||
2558 | |||
2559 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2560 | if (rc == 0) | ||
2561 | mv_vif->peer_id = peer_info->station_id; | ||
2562 | |||
2563 | break; | ||
2564 | |||
2565 | case MWL8K_STA_DB_DEL_ENTRY: | ||
2566 | case MWL8K_STA_DB_FLUSH: | ||
2567 | default: | ||
2568 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2569 | if (rc == 0) | ||
2570 | mv_vif->peer_id = 0; | ||
2571 | break; | ||
2572 | } | ||
2573 | kfree(cmd); | ||
2574 | |||
2575 | return rc; | ||
2576 | } | ||
2577 | |||
2578 | /* | ||
2579 | * CMD_SET_AID. | ||
2580 | */ | ||
2581 | #define MWL8K_FRAME_PROT_DISABLED 0x00 | ||
2582 | #define MWL8K_FRAME_PROT_11G 0x07 | ||
2583 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 | ||
2584 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 | ||
2585 | |||
2586 | struct mwl8k_cmd_update_set_aid { | ||
2587 | struct mwl8k_cmd_pkt header; | ||
2588 | __le16 aid; | ||
2589 | |||
2590 | /* AP's MAC address (BSSID) */ | ||
2591 | __u8 bssid[ETH_ALEN]; | ||
2592 | __le16 protection_mode; | ||
2593 | __u8 supp_rates[14]; | ||
2594 | } __attribute__((packed)); | ||
2595 | |||
2596 | static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | ||
2597 | struct ieee80211_vif *vif) | ||
2598 | { | ||
2599 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2600 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2601 | struct mwl8k_cmd_update_set_aid *cmd; | ||
2602 | u16 prot_mode; | ||
2603 | int rc; | ||
2604 | |||
2605 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2606 | if (cmd == NULL) | ||
2607 | return -ENOMEM; | ||
2608 | |||
2609 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); | ||
2610 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2611 | cmd->aid = cpu_to_le16(info->aid); | ||
2612 | |||
2613 | memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); | ||
2614 | |||
2615 | if (info->use_cts_prot) { | ||
2616 | prot_mode = MWL8K_FRAME_PROT_11G; | ||
2617 | } else { | ||
2618 | switch (info->ht_operation_mode & | ||
2619 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2620 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2621 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2622 | break; | ||
2623 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2624 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2625 | break; | ||
2626 | default: | ||
2627 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2628 | break; | ||
2629 | } | ||
2630 | } | ||
2631 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2632 | |||
2633 | memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | ||
2634 | |||
2635 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2636 | kfree(cmd); | ||
2637 | 2458 | ||
2638 | return rc; | 2459 | return rc; |
2639 | } | 2460 | } |
2640 | 2461 | ||
2641 | /* | 2462 | /* |
2642 | * CMD_SET_RATE. | 2463 | * CMD_MIMO_CONFIG. |
2643 | */ | 2464 | */ |
2644 | struct mwl8k_cmd_update_rateset { | 2465 | struct mwl8k_cmd_mimo_config { |
2645 | struct mwl8k_cmd_pkt header; | 2466 | struct mwl8k_cmd_pkt header; |
2646 | __u8 legacy_rates[14]; | 2467 | __le32 action; |
2647 | 2468 | __u8 rx_antenna_map; | |
2648 | /* Bitmap for supported MCS codes. */ | 2469 | __u8 tx_antenna_map; |
2649 | __u8 mcs_set[16]; | ||
2650 | __u8 reserved[16]; | ||
2651 | } __attribute__((packed)); | 2470 | } __attribute__((packed)); |
2652 | 2471 | ||
2653 | static int mwl8k_update_rateset(struct ieee80211_hw *hw, | 2472 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) |
2654 | struct ieee80211_vif *vif) | ||
2655 | { | 2473 | { |
2656 | struct mwl8k_cmd_update_rateset *cmd; | 2474 | struct mwl8k_cmd_mimo_config *cmd; |
2657 | int rc; | 2475 | int rc; |
2658 | 2476 | ||
2659 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2477 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2660 | if (cmd == NULL) | 2478 | if (cmd == NULL) |
2661 | return -ENOMEM; | 2479 | return -ENOMEM; |
2662 | 2480 | ||
2663 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); | 2481 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); |
2664 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2482 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2665 | memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | 2483 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); |
2484 | cmd->rx_antenna_map = rx; | ||
2485 | cmd->tx_antenna_map = tx; | ||
2666 | 2486 | ||
2667 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2487 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2668 | kfree(cmd); | 2488 | kfree(cmd); |
@@ -2755,6 +2575,217 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, | |||
2755 | return rc; | 2575 | return rc; |
2756 | } | 2576 | } |
2757 | 2577 | ||
2578 | /* | ||
2579 | * CMD_ENABLE_SNIFFER. | ||
2580 | */ | ||
2581 | struct mwl8k_cmd_enable_sniffer { | ||
2582 | struct mwl8k_cmd_pkt header; | ||
2583 | __le32 action; | ||
2584 | } __attribute__((packed)); | ||
2585 | |||
2586 | static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2587 | { | ||
2588 | struct mwl8k_cmd_enable_sniffer *cmd; | ||
2589 | int rc; | ||
2590 | |||
2591 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2592 | if (cmd == NULL) | ||
2593 | return -ENOMEM; | ||
2594 | |||
2595 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | ||
2596 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2597 | cmd->action = cpu_to_le32(!!enable); | ||
2598 | |||
2599 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2600 | kfree(cmd); | ||
2601 | |||
2602 | return rc; | ||
2603 | } | ||
2604 | |||
2605 | /* | ||
2606 | * CMD_SET_MAC_ADDR. | ||
2607 | */ | ||
2608 | struct mwl8k_cmd_set_mac_addr { | ||
2609 | struct mwl8k_cmd_pkt header; | ||
2610 | union { | ||
2611 | struct { | ||
2612 | __le16 mac_type; | ||
2613 | __u8 mac_addr[ETH_ALEN]; | ||
2614 | } mbss; | ||
2615 | __u8 mac_addr[ETH_ALEN]; | ||
2616 | }; | ||
2617 | } __attribute__((packed)); | ||
2618 | |||
2619 | static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | ||
2620 | { | ||
2621 | struct mwl8k_priv *priv = hw->priv; | ||
2622 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2623 | int rc; | ||
2624 | |||
2625 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2626 | if (cmd == NULL) | ||
2627 | return -ENOMEM; | ||
2628 | |||
2629 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | ||
2630 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2631 | if (priv->ap_fw) { | ||
2632 | cmd->mbss.mac_type = 0; | ||
2633 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2634 | } else { | ||
2635 | memcpy(cmd->mac_addr, mac, ETH_ALEN); | ||
2636 | } | ||
2637 | |||
2638 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2639 | kfree(cmd); | ||
2640 | |||
2641 | return rc; | ||
2642 | } | ||
2643 | |||
2644 | /* | ||
2645 | * CMD_SET_RATEADAPT_MODE. | ||
2646 | */ | ||
2647 | struct mwl8k_cmd_set_rate_adapt_mode { | ||
2648 | struct mwl8k_cmd_pkt header; | ||
2649 | __le16 action; | ||
2650 | __le16 mode; | ||
2651 | } __attribute__((packed)); | ||
2652 | |||
2653 | static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) | ||
2654 | { | ||
2655 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | ||
2656 | int rc; | ||
2657 | |||
2658 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2659 | if (cmd == NULL) | ||
2660 | return -ENOMEM; | ||
2661 | |||
2662 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | ||
2663 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2664 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2665 | cmd->mode = cpu_to_le16(mode); | ||
2666 | |||
2667 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2668 | kfree(cmd); | ||
2669 | |||
2670 | return rc; | ||
2671 | } | ||
2672 | |||
2673 | /* | ||
2674 | * CMD_UPDATE_STADB. | ||
2675 | */ | ||
2676 | struct ewc_ht_info { | ||
2677 | __le16 control1; | ||
2678 | __le16 control2; | ||
2679 | __le16 control3; | ||
2680 | } __attribute__((packed)); | ||
2681 | |||
2682 | struct peer_capability_info { | ||
2683 | /* Peer type - AP vs. STA. */ | ||
2684 | __u8 peer_type; | ||
2685 | |||
2686 | /* Basic 802.11 capabilities from assoc resp. */ | ||
2687 | __le16 basic_caps; | ||
2688 | |||
2689 | /* Set if peer supports 802.11n high throughput (HT). */ | ||
2690 | __u8 ht_support; | ||
2691 | |||
2692 | /* Valid if HT is supported. */ | ||
2693 | __le16 ht_caps; | ||
2694 | __u8 extended_ht_caps; | ||
2695 | struct ewc_ht_info ewc_info; | ||
2696 | |||
2697 | /* Legacy rate table. Intersection of our rates and peer rates. */ | ||
2698 | __u8 legacy_rates[12]; | ||
2699 | |||
2700 | /* HT rate table. Intersection of our rates and peer rates. */ | ||
2701 | __u8 ht_rates[16]; | ||
2702 | __u8 pad[16]; | ||
2703 | |||
2704 | /* If set, interoperability mode, no proprietary extensions. */ | ||
2705 | __u8 interop; | ||
2706 | __u8 pad2; | ||
2707 | __u8 station_id; | ||
2708 | __le16 amsdu_enabled; | ||
2709 | } __attribute__((packed)); | ||
2710 | |||
2711 | struct mwl8k_cmd_update_stadb { | ||
2712 | struct mwl8k_cmd_pkt header; | ||
2713 | |||
2714 | /* See STADB_ACTION_TYPE */ | ||
2715 | __le32 action; | ||
2716 | |||
2717 | /* Peer MAC address */ | ||
2718 | __u8 peer_addr[ETH_ALEN]; | ||
2719 | |||
2720 | __le32 reserved; | ||
2721 | |||
2722 | /* Peer info - valid during add/update. */ | ||
2723 | struct peer_capability_info peer_info; | ||
2724 | } __attribute__((packed)); | ||
2725 | |||
2726 | #define MWL8K_STA_DB_MODIFY_ENTRY 1 | ||
2727 | #define MWL8K_STA_DB_DEL_ENTRY 2 | ||
2728 | |||
2729 | /* Peer Entry flags - used to define the type of the peer node */ | ||
2730 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | ||
2731 | |||
2732 | static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, | ||
2733 | struct ieee80211_vif *vif, | ||
2734 | struct ieee80211_sta *sta) | ||
2735 | { | ||
2736 | struct mwl8k_cmd_update_stadb *cmd; | ||
2737 | struct peer_capability_info *p; | ||
2738 | int rc; | ||
2739 | |||
2740 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2741 | if (cmd == NULL) | ||
2742 | return -ENOMEM; | ||
2743 | |||
2744 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2745 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2746 | cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); | ||
2747 | memcpy(cmd->peer_addr, sta->addr, ETH_ALEN); | ||
2748 | |||
2749 | p = &cmd->peer_info; | ||
2750 | p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2751 | p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); | ||
2752 | p->ht_support = sta->ht_cap.ht_supported; | ||
2753 | p->ht_caps = sta->ht_cap.cap; | ||
2754 | p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | | ||
2755 | ((sta->ht_cap.ampdu_density & 7) << 2); | ||
2756 | legacy_rate_mask_to_array(p->legacy_rates, | ||
2757 | sta->supp_rates[IEEE80211_BAND_2GHZ]); | ||
2758 | memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); | ||
2759 | p->interop = 1; | ||
2760 | p->amsdu_enabled = 0; | ||
2761 | |||
2762 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2763 | kfree(cmd); | ||
2764 | |||
2765 | return rc ? rc : p->station_id; | ||
2766 | } | ||
2767 | |||
2768 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, | ||
2769 | struct ieee80211_vif *vif, u8 *addr) | ||
2770 | { | ||
2771 | struct mwl8k_cmd_update_stadb *cmd; | ||
2772 | int rc; | ||
2773 | |||
2774 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2775 | if (cmd == NULL) | ||
2776 | return -ENOMEM; | ||
2777 | |||
2778 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2779 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2780 | cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY); | ||
2781 | memcpy(cmd->peer_addr, addr, ETH_ALEN); | ||
2782 | |||
2783 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2784 | kfree(cmd); | ||
2785 | |||
2786 | return rc; | ||
2787 | } | ||
2788 | |||
2758 | 2789 | ||
2759 | /* | 2790 | /* |
2760 | * Interrupt handling. | 2791 | * Interrupt handling. |
@@ -2836,11 +2867,11 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2836 | 2867 | ||
2837 | rc = mwl8k_fw_lock(hw); | 2868 | rc = mwl8k_fw_lock(hw); |
2838 | if (!rc) { | 2869 | if (!rc) { |
2839 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 2870 | rc = mwl8k_cmd_radio_enable(hw); |
2840 | 2871 | ||
2841 | if (!priv->ap_fw) { | 2872 | if (!priv->ap_fw) { |
2842 | if (!rc) | 2873 | if (!rc) |
2843 | rc = mwl8k_enable_sniffer(hw, 0); | 2874 | rc = mwl8k_cmd_enable_sniffer(hw, 0); |
2844 | 2875 | ||
2845 | if (!rc) | 2876 | if (!rc) |
2846 | rc = mwl8k_cmd_set_pre_scan(hw); | 2877 | rc = mwl8k_cmd_set_pre_scan(hw); |
@@ -2851,10 +2882,10 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2851 | } | 2882 | } |
2852 | 2883 | ||
2853 | if (!rc) | 2884 | if (!rc) |
2854 | rc = mwl8k_cmd_setrateadaptmode(hw, 0); | 2885 | rc = mwl8k_cmd_set_rateadapt_mode(hw, 0); |
2855 | 2886 | ||
2856 | if (!rc) | 2887 | if (!rc) |
2857 | rc = mwl8k_set_wmm(hw, 0); | 2888 | rc = mwl8k_cmd_set_wmm_mode(hw, 0); |
2858 | 2889 | ||
2859 | mwl8k_fw_unlock(hw); | 2890 | mwl8k_fw_unlock(hw); |
2860 | } | 2891 | } |
@@ -2873,7 +2904,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2873 | struct mwl8k_priv *priv = hw->priv; | 2904 | struct mwl8k_priv *priv = hw->priv; |
2874 | int i; | 2905 | int i; |
2875 | 2906 | ||
2876 | mwl8k_cmd_802_11_radio_disable(hw); | 2907 | mwl8k_cmd_radio_disable(hw); |
2877 | 2908 | ||
2878 | ieee80211_stop_queues(hw); | 2909 | ieee80211_stop_queues(hw); |
2879 | 2910 | ||
@@ -2895,7 +2926,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2895 | } | 2926 | } |
2896 | 2927 | ||
2897 | static int mwl8k_add_interface(struct ieee80211_hw *hw, | 2928 | static int mwl8k_add_interface(struct ieee80211_hw *hw, |
2898 | struct ieee80211_if_init_conf *conf) | 2929 | struct ieee80211_vif *vif) |
2899 | { | 2930 | { |
2900 | struct mwl8k_priv *priv = hw->priv; | 2931 | struct mwl8k_priv *priv = hw->priv; |
2901 | struct mwl8k_vif *mwl8k_vif; | 2932 | struct mwl8k_vif *mwl8k_vif; |
@@ -2909,7 +2940,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2909 | /* | 2940 | /* |
2910 | * We only support managed interfaces for now. | 2941 | * We only support managed interfaces for now. |
2911 | */ | 2942 | */ |
2912 | if (conf->type != NL80211_IFTYPE_STATION) | 2943 | if (vif->type != NL80211_IFTYPE_STATION) |
2913 | return -EINVAL; | 2944 | return -EINVAL; |
2914 | 2945 | ||
2915 | /* | 2946 | /* |
@@ -2925,34 +2956,31 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2925 | } | 2956 | } |
2926 | 2957 | ||
2927 | /* Clean out driver private area */ | 2958 | /* Clean out driver private area */ |
2928 | mwl8k_vif = MWL8K_VIF(conf->vif); | 2959 | mwl8k_vif = MWL8K_VIF(vif); |
2929 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | 2960 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); |
2930 | 2961 | ||
2931 | /* Set and save the mac address */ | 2962 | /* Set and save the mac address */ |
2932 | mwl8k_set_mac_addr(hw, conf->mac_addr); | 2963 | mwl8k_cmd_set_mac_addr(hw, vif->addr); |
2933 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); | 2964 | memcpy(mwl8k_vif->mac_addr, vif->addr, ETH_ALEN); |
2934 | |||
2935 | /* Back pointer to parent config block */ | ||
2936 | mwl8k_vif->priv = priv; | ||
2937 | 2965 | ||
2938 | /* Set Initial sequence number to zero */ | 2966 | /* Set Initial sequence number to zero */ |
2939 | mwl8k_vif->seqno = 0; | 2967 | mwl8k_vif->seqno = 0; |
2940 | 2968 | ||
2941 | priv->vif = conf->vif; | 2969 | priv->vif = vif; |
2942 | priv->current_channel = NULL; | 2970 | priv->current_channel = NULL; |
2943 | 2971 | ||
2944 | return 0; | 2972 | return 0; |
2945 | } | 2973 | } |
2946 | 2974 | ||
2947 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, | 2975 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, |
2948 | struct ieee80211_if_init_conf *conf) | 2976 | struct ieee80211_vif *vif) |
2949 | { | 2977 | { |
2950 | struct mwl8k_priv *priv = hw->priv; | 2978 | struct mwl8k_priv *priv = hw->priv; |
2951 | 2979 | ||
2952 | if (priv->vif == NULL) | 2980 | if (priv->vif == NULL) |
2953 | return; | 2981 | return; |
2954 | 2982 | ||
2955 | mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 2983 | mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); |
2956 | 2984 | ||
2957 | priv->vif = NULL; | 2985 | priv->vif = NULL; |
2958 | } | 2986 | } |
@@ -2964,7 +2992,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2964 | int rc; | 2992 | int rc; |
2965 | 2993 | ||
2966 | if (conf->flags & IEEE80211_CONF_IDLE) { | 2994 | if (conf->flags & IEEE80211_CONF_IDLE) { |
2967 | mwl8k_cmd_802_11_radio_disable(hw); | 2995 | mwl8k_cmd_radio_disable(hw); |
2968 | priv->current_channel = NULL; | 2996 | priv->current_channel = NULL; |
2969 | return 0; | 2997 | return 0; |
2970 | } | 2998 | } |
@@ -2973,11 +3001,11 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2973 | if (rc) | 3001 | if (rc) |
2974 | return rc; | 3002 | return rc; |
2975 | 3003 | ||
2976 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 3004 | rc = mwl8k_cmd_radio_enable(hw); |
2977 | if (rc) | 3005 | if (rc) |
2978 | goto out; | 3006 | goto out; |
2979 | 3007 | ||
2980 | rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); | 3008 | rc = mwl8k_cmd_set_rf_channel(hw, conf); |
2981 | if (rc) | 3009 | if (rc) |
2982 | goto out; | 3010 | goto out; |
2983 | 3011 | ||
@@ -2985,7 +3013,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2985 | 3013 | ||
2986 | if (conf->power_level > 18) | 3014 | if (conf->power_level > 18) |
2987 | conf->power_level = 18; | 3015 | conf->power_level = 18; |
2988 | rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); | 3016 | rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); |
2989 | if (rc) | 3017 | if (rc) |
2990 | goto out; | 3018 | goto out; |
2991 | 3019 | ||
@@ -3009,67 +3037,78 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | |||
3009 | u32 changed) | 3037 | u32 changed) |
3010 | { | 3038 | { |
3011 | struct mwl8k_priv *priv = hw->priv; | 3039 | struct mwl8k_priv *priv = hw->priv; |
3012 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | 3040 | u32 ap_legacy_rates; |
3041 | u8 ap_mcs_rates[16]; | ||
3013 | int rc; | 3042 | int rc; |
3014 | 3043 | ||
3015 | if ((changed & BSS_CHANGED_ASSOC) == 0) | 3044 | if (mwl8k_fw_lock(hw)) |
3016 | return; | 3045 | return; |
3017 | 3046 | ||
3018 | priv->capture_beacon = false; | 3047 | /* |
3048 | * No need to capture a beacon if we're no longer associated. | ||
3049 | */ | ||
3050 | if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc) | ||
3051 | priv->capture_beacon = false; | ||
3019 | 3052 | ||
3020 | rc = mwl8k_fw_lock(hw); | 3053 | /* |
3021 | if (rc) | 3054 | * Get the AP's legacy and MCS rates. |
3022 | return; | 3055 | */ |
3056 | ap_legacy_rates = 0; | ||
3057 | if (vif->bss_conf.assoc) { | ||
3058 | struct ieee80211_sta *ap; | ||
3059 | rcu_read_lock(); | ||
3060 | |||
3061 | ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); | ||
3062 | if (ap == NULL) { | ||
3063 | rcu_read_unlock(); | ||
3064 | goto out; | ||
3065 | } | ||
3023 | 3066 | ||
3024 | if (info->assoc) { | 3067 | ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; |
3025 | memcpy(&mwl8k_vif->bss_info, info, | 3068 | memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); |
3026 | sizeof(struct ieee80211_bss_conf)); | ||
3027 | 3069 | ||
3028 | memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); | 3070 | rcu_read_unlock(); |
3071 | } | ||
3029 | 3072 | ||
3030 | /* Install rates */ | 3073 | if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { |
3031 | rc = mwl8k_update_rateset(hw, vif); | 3074 | rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates); |
3032 | if (rc) | 3075 | if (rc) |
3033 | goto out; | 3076 | goto out; |
3034 | 3077 | ||
3035 | /* Turn on rate adaptation */ | ||
3036 | rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, | 3078 | rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, |
3037 | MWL8K_UCAST_RATE, NULL); | 3079 | MWL8K_UCAST_RATE, NULL); |
3038 | if (rc) | 3080 | if (rc) |
3039 | goto out; | 3081 | goto out; |
3082 | } | ||
3040 | 3083 | ||
3041 | /* Set radio preamble */ | 3084 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
3042 | rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); | 3085 | rc = mwl8k_set_radio_preamble(hw, |
3043 | if (rc) | 3086 | vif->bss_conf.use_short_preamble); |
3044 | goto out; | ||
3045 | |||
3046 | /* Set slot time */ | ||
3047 | rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); | ||
3048 | if (rc) | 3087 | if (rc) |
3049 | goto out; | 3088 | goto out; |
3089 | } | ||
3050 | 3090 | ||
3051 | /* Update peer rate info */ | 3091 | if (changed & BSS_CHANGED_ERP_SLOT) { |
3052 | rc = mwl8k_cmd_update_sta_db(hw, vif, | 3092 | rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); |
3053 | MWL8K_STA_DB_MODIFY_ENTRY); | ||
3054 | if (rc) | 3093 | if (rc) |
3055 | goto out; | 3094 | goto out; |
3095 | } | ||
3056 | 3096 | ||
3057 | /* Set AID */ | 3097 | if (((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) || |
3058 | rc = mwl8k_cmd_set_aid(hw, vif); | 3098 | (changed & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT))) { |
3099 | rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates); | ||
3059 | if (rc) | 3100 | if (rc) |
3060 | goto out; | 3101 | goto out; |
3102 | } | ||
3061 | 3103 | ||
3104 | if (vif->bss_conf.assoc && | ||
3105 | (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) { | ||
3062 | /* | 3106 | /* |
3063 | * Finalize the join. Tell rx handler to process | 3107 | * Finalize the join. Tell rx handler to process |
3064 | * next beacon from our BSSID. | 3108 | * next beacon from our BSSID. |
3065 | */ | 3109 | */ |
3066 | memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); | 3110 | memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN); |
3067 | priv->capture_beacon = true; | 3111 | priv->capture_beacon = true; |
3068 | } else { | ||
3069 | rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); | ||
3070 | memset(&mwl8k_vif->bss_info, 0, | ||
3071 | sizeof(struct ieee80211_bss_conf)); | ||
3072 | memset(mwl8k_vif->bssid, 0, ETH_ALEN); | ||
3073 | } | 3112 | } |
3074 | 3113 | ||
3075 | out: | 3114 | out: |
@@ -3114,7 +3153,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | |||
3114 | } | 3153 | } |
3115 | 3154 | ||
3116 | if (!priv->sniffer_enabled) { | 3155 | if (!priv->sniffer_enabled) { |
3117 | if (mwl8k_enable_sniffer(hw, 1)) | 3156 | if (mwl8k_cmd_enable_sniffer(hw, 1)) |
3118 | return 0; | 3157 | return 0; |
3119 | priv->sniffer_enabled = true; | 3158 | priv->sniffer_enabled = true; |
3120 | } | 3159 | } |
@@ -3163,7 +3202,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3163 | } | 3202 | } |
3164 | 3203 | ||
3165 | if (priv->sniffer_enabled) { | 3204 | if (priv->sniffer_enabled) { |
3166 | mwl8k_enable_sniffer(hw, 0); | 3205 | mwl8k_cmd_enable_sniffer(hw, 0); |
3167 | priv->sniffer_enabled = false; | 3206 | priv->sniffer_enabled = false; |
3168 | } | 3207 | } |
3169 | 3208 | ||
@@ -3174,7 +3213,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3174 | */ | 3213 | */ |
3175 | mwl8k_cmd_set_pre_scan(hw); | 3214 | mwl8k_cmd_set_pre_scan(hw); |
3176 | } else { | 3215 | } else { |
3177 | u8 *bssid; | 3216 | const u8 *bssid; |
3178 | 3217 | ||
3179 | /* | 3218 | /* |
3180 | * Enable the BSS filter. | 3219 | * Enable the BSS filter. |
@@ -3186,7 +3225,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3186 | */ | 3225 | */ |
3187 | bssid = "\x01\x00\x00\x00\x00\x00"; | 3226 | bssid = "\x01\x00\x00\x00\x00\x00"; |
3188 | if (priv->vif != NULL) | 3227 | if (priv->vif != NULL) |
3189 | bssid = MWL8K_VIF(priv->vif)->bssid; | 3228 | bssid = priv->vif->bss_conf.bssid; |
3190 | 3229 | ||
3191 | mwl8k_cmd_set_post_scan(hw, bssid); | 3230 | mwl8k_cmd_set_post_scan(hw, bssid); |
3192 | } | 3231 | } |
@@ -3213,7 +3252,79 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3213 | 3252 | ||
3214 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 3253 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
3215 | { | 3254 | { |
3216 | return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); | 3255 | return mwl8k_cmd_set_rts_threshold(hw, MWL8K_CMD_SET, value); |
3256 | } | ||
3257 | |||
3258 | struct mwl8k_sta_notify_item | ||
3259 | { | ||
3260 | struct list_head list; | ||
3261 | struct ieee80211_vif *vif; | ||
3262 | enum sta_notify_cmd cmd; | ||
3263 | struct ieee80211_sta sta; | ||
3264 | }; | ||
3265 | |||
3266 | static void mwl8k_sta_notify_worker(struct work_struct *work) | ||
3267 | { | ||
3268 | struct mwl8k_priv *priv = | ||
3269 | container_of(work, struct mwl8k_priv, sta_notify_worker); | ||
3270 | struct ieee80211_hw *hw = priv->hw; | ||
3271 | |||
3272 | spin_lock_bh(&priv->sta_notify_list_lock); | ||
3273 | while (!list_empty(&priv->sta_notify_list)) { | ||
3274 | struct mwl8k_sta_notify_item *s; | ||
3275 | |||
3276 | s = list_entry(priv->sta_notify_list.next, | ||
3277 | struct mwl8k_sta_notify_item, list); | ||
3278 | list_del(&s->list); | ||
3279 | |||
3280 | spin_unlock_bh(&priv->sta_notify_list_lock); | ||
3281 | |||
3282 | if (s->cmd == STA_NOTIFY_ADD) { | ||
3283 | int rc; | ||
3284 | |||
3285 | rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); | ||
3286 | if (rc >= 0) { | ||
3287 | struct ieee80211_sta *sta; | ||
3288 | |||
3289 | rcu_read_lock(); | ||
3290 | sta = ieee80211_find_sta(s->vif, s->sta.addr); | ||
3291 | if (sta != NULL) | ||
3292 | MWL8K_STA(sta)->peer_id = rc; | ||
3293 | rcu_read_unlock(); | ||
3294 | } | ||
3295 | } else { | ||
3296 | mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); | ||
3297 | } | ||
3298 | |||
3299 | kfree(s); | ||
3300 | |||
3301 | spin_lock_bh(&priv->sta_notify_list_lock); | ||
3302 | } | ||
3303 | spin_unlock_bh(&priv->sta_notify_list_lock); | ||
3304 | } | ||
3305 | |||
3306 | static void | ||
3307 | mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
3308 | enum sta_notify_cmd cmd, struct ieee80211_sta *sta) | ||
3309 | { | ||
3310 | struct mwl8k_priv *priv = hw->priv; | ||
3311 | struct mwl8k_sta_notify_item *s; | ||
3312 | |||
3313 | if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE) | ||
3314 | return; | ||
3315 | |||
3316 | s = kmalloc(sizeof(*s), GFP_ATOMIC); | ||
3317 | if (s != NULL) { | ||
3318 | s->vif = vif; | ||
3319 | s->cmd = cmd; | ||
3320 | s->sta = *sta; | ||
3321 | |||
3322 | spin_lock(&priv->sta_notify_list_lock); | ||
3323 | list_add_tail(&s->list, &priv->sta_notify_list); | ||
3324 | spin_unlock(&priv->sta_notify_list_lock); | ||
3325 | |||
3326 | ieee80211_queue_work(hw, &priv->sta_notify_worker); | ||
3327 | } | ||
3217 | } | 3328 | } |
3218 | 3329 | ||
3219 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 3330 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -3225,14 +3336,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
3225 | rc = mwl8k_fw_lock(hw); | 3336 | rc = mwl8k_fw_lock(hw); |
3226 | if (!rc) { | 3337 | if (!rc) { |
3227 | if (!priv->wmm_enabled) | 3338 | if (!priv->wmm_enabled) |
3228 | rc = mwl8k_set_wmm(hw, 1); | 3339 | rc = mwl8k_cmd_set_wmm_mode(hw, 1); |
3229 | 3340 | ||
3230 | if (!rc) | 3341 | if (!rc) |
3231 | rc = mwl8k_set_edca_params(hw, queue, | 3342 | rc = mwl8k_cmd_set_edca_params(hw, queue, |
3232 | params->cw_min, | 3343 | params->cw_min, |
3233 | params->cw_max, | 3344 | params->cw_max, |
3234 | params->aifs, | 3345 | params->aifs, |
3235 | params->txop); | 3346 | params->txop); |
3236 | 3347 | ||
3237 | mwl8k_fw_unlock(hw); | 3348 | mwl8k_fw_unlock(hw); |
3238 | } | 3349 | } |
@@ -3261,7 +3372,23 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, | |||
3261 | static int mwl8k_get_stats(struct ieee80211_hw *hw, | 3372 | static int mwl8k_get_stats(struct ieee80211_hw *hw, |
3262 | struct ieee80211_low_level_stats *stats) | 3373 | struct ieee80211_low_level_stats *stats) |
3263 | { | 3374 | { |
3264 | return mwl8k_cmd_802_11_get_stat(hw, stats); | 3375 | return mwl8k_cmd_get_stat(hw, stats); |
3376 | } | ||
3377 | |||
3378 | static int | ||
3379 | mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
3380 | enum ieee80211_ampdu_mlme_action action, | ||
3381 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | ||
3382 | { | ||
3383 | switch (action) { | ||
3384 | case IEEE80211_AMPDU_RX_START: | ||
3385 | case IEEE80211_AMPDU_RX_STOP: | ||
3386 | if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | ||
3387 | return -ENOTSUPP; | ||
3388 | return 0; | ||
3389 | default: | ||
3390 | return -ENOTSUPP; | ||
3391 | } | ||
3265 | } | 3392 | } |
3266 | 3393 | ||
3267 | static const struct ieee80211_ops mwl8k_ops = { | 3394 | static const struct ieee80211_ops mwl8k_ops = { |
@@ -3275,9 +3402,11 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3275 | .prepare_multicast = mwl8k_prepare_multicast, | 3402 | .prepare_multicast = mwl8k_prepare_multicast, |
3276 | .configure_filter = mwl8k_configure_filter, | 3403 | .configure_filter = mwl8k_configure_filter, |
3277 | .set_rts_threshold = mwl8k_set_rts_threshold, | 3404 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3405 | .sta_notify = mwl8k_sta_notify, | ||
3278 | .conf_tx = mwl8k_conf_tx, | 3406 | .conf_tx = mwl8k_conf_tx, |
3279 | .get_tx_stats = mwl8k_get_tx_stats, | 3407 | .get_tx_stats = mwl8k_get_tx_stats, |
3280 | .get_stats = mwl8k_get_stats, | 3408 | .get_stats = mwl8k_get_stats, |
3409 | .ampdu_action = mwl8k_ampdu_action, | ||
3281 | }; | 3410 | }; |
3282 | 3411 | ||
3283 | static void mwl8k_tx_reclaim_handler(unsigned long data) | 3412 | static void mwl8k_tx_reclaim_handler(unsigned long data) |
@@ -3302,37 +3431,42 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) | |||
3302 | struct mwl8k_priv *priv = | 3431 | struct mwl8k_priv *priv = |
3303 | container_of(work, struct mwl8k_priv, finalize_join_worker); | 3432 | container_of(work, struct mwl8k_priv, finalize_join_worker); |
3304 | struct sk_buff *skb = priv->beacon_skb; | 3433 | struct sk_buff *skb = priv->beacon_skb; |
3305 | u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; | ||
3306 | 3434 | ||
3307 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); | 3435 | mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, |
3436 | priv->vif->bss_conf.dtim_period); | ||
3308 | dev_kfree_skb(skb); | 3437 | dev_kfree_skb(skb); |
3309 | 3438 | ||
3310 | priv->beacon_skb = NULL; | 3439 | priv->beacon_skb = NULL; |
3311 | } | 3440 | } |
3312 | 3441 | ||
3313 | enum { | 3442 | enum { |
3314 | MWL8687 = 0, | 3443 | MWL8363 = 0, |
3444 | MWL8687, | ||
3315 | MWL8366, | 3445 | MWL8366, |
3316 | }; | 3446 | }; |
3317 | 3447 | ||
3318 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | 3448 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { |
3319 | { | 3449 | [MWL8363] = { |
3450 | .part_name = "88w8363", | ||
3451 | .helper_image = "mwl8k/helper_8363.fw", | ||
3452 | .fw_image = "mwl8k/fmimage_8363.fw", | ||
3453 | }, | ||
3454 | [MWL8687] = { | ||
3320 | .part_name = "88w8687", | 3455 | .part_name = "88w8687", |
3321 | .helper_image = "mwl8k/helper_8687.fw", | 3456 | .helper_image = "mwl8k/helper_8687.fw", |
3322 | .fw_image = "mwl8k/fmimage_8687.fw", | 3457 | .fw_image = "mwl8k/fmimage_8687.fw", |
3323 | .rxd_ops = &rxd_8687_ops, | ||
3324 | .modes = BIT(NL80211_IFTYPE_STATION), | ||
3325 | }, | 3458 | }, |
3326 | { | 3459 | [MWL8366] = { |
3327 | .part_name = "88w8366", | 3460 | .part_name = "88w8366", |
3328 | .helper_image = "mwl8k/helper_8366.fw", | 3461 | .helper_image = "mwl8k/helper_8366.fw", |
3329 | .fw_image = "mwl8k/fmimage_8366.fw", | 3462 | .fw_image = "mwl8k/fmimage_8366.fw", |
3330 | .rxd_ops = &rxd_8366_ops, | 3463 | .ap_rxd_ops = &rxd_8366_ap_ops, |
3331 | .modes = 0, | ||
3332 | }, | 3464 | }, |
3333 | }; | 3465 | }; |
3334 | 3466 | ||
3335 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { | 3467 | static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { |
3468 | { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, | ||
3469 | { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, | ||
3336 | { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, | 3470 | { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, |
3337 | { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, | 3471 | { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, |
3338 | { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, | 3472 | { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, |
@@ -3354,6 +3488,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3354 | printed_version = 1; | 3488 | printed_version = 1; |
3355 | } | 3489 | } |
3356 | 3490 | ||
3491 | |||
3357 | rc = pci_enable_device(pdev); | 3492 | rc = pci_enable_device(pdev); |
3358 | if (rc) { | 3493 | if (rc) { |
3359 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", | 3494 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", |
@@ -3370,6 +3505,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3370 | 3505 | ||
3371 | pci_set_master(pdev); | 3506 | pci_set_master(pdev); |
3372 | 3507 | ||
3508 | |||
3373 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); | 3509 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); |
3374 | if (hw == NULL) { | 3510 | if (hw == NULL) { |
3375 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); | 3511 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); |
@@ -3377,17 +3513,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3377 | goto err_free_reg; | 3513 | goto err_free_reg; |
3378 | } | 3514 | } |
3379 | 3515 | ||
3516 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3517 | pci_set_drvdata(pdev, hw); | ||
3518 | |||
3380 | priv = hw->priv; | 3519 | priv = hw->priv; |
3381 | priv->hw = hw; | 3520 | priv->hw = hw; |
3382 | priv->pdev = pdev; | 3521 | priv->pdev = pdev; |
3383 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 3522 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
3384 | priv->rxd_ops = priv->device_info->rxd_ops; | ||
3385 | priv->sniffer_enabled = false; | ||
3386 | priv->wmm_enabled = false; | ||
3387 | priv->pending_tx_pkts = 0; | ||
3388 | 3523 | ||
3389 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3390 | pci_set_drvdata(pdev, hw); | ||
3391 | 3524 | ||
3392 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 3525 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
3393 | if (priv->sram == NULL) { | 3526 | if (priv->sram == NULL) { |
@@ -3410,6 +3543,47 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3410 | } | 3543 | } |
3411 | } | 3544 | } |
3412 | 3545 | ||
3546 | |||
3547 | /* Reset firmware and hardware */ | ||
3548 | mwl8k_hw_reset(priv); | ||
3549 | |||
3550 | /* Ask userland hotplug daemon for the device firmware */ | ||
3551 | rc = mwl8k_request_firmware(priv); | ||
3552 | if (rc) { | ||
3553 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3554 | wiphy_name(hw->wiphy)); | ||
3555 | goto err_stop_firmware; | ||
3556 | } | ||
3557 | |||
3558 | /* Load firmware into hardware */ | ||
3559 | rc = mwl8k_load_firmware(hw); | ||
3560 | if (rc) { | ||
3561 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3562 | wiphy_name(hw->wiphy)); | ||
3563 | goto err_stop_firmware; | ||
3564 | } | ||
3565 | |||
3566 | /* Reclaim memory once firmware is successfully loaded */ | ||
3567 | mwl8k_release_firmware(priv); | ||
3568 | |||
3569 | |||
3570 | if (priv->ap_fw) { | ||
3571 | priv->rxd_ops = priv->device_info->ap_rxd_ops; | ||
3572 | if (priv->rxd_ops == NULL) { | ||
3573 | printk(KERN_ERR "%s: Driver does not have AP " | ||
3574 | "firmware image support for this hardware\n", | ||
3575 | wiphy_name(hw->wiphy)); | ||
3576 | goto err_stop_firmware; | ||
3577 | } | ||
3578 | } else { | ||
3579 | priv->rxd_ops = &rxd_sta_ops; | ||
3580 | } | ||
3581 | |||
3582 | priv->sniffer_enabled = false; | ||
3583 | priv->wmm_enabled = false; | ||
3584 | priv->pending_tx_pkts = 0; | ||
3585 | |||
3586 | |||
3413 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); | 3587 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); |
3414 | priv->band.band = IEEE80211_BAND_2GHZ; | 3588 | priv->band.band = IEEE80211_BAND_2GHZ; |
3415 | priv->band.channels = priv->channels; | 3589 | priv->band.channels = priv->channels; |
@@ -3432,17 +3606,21 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3432 | 3606 | ||
3433 | hw->queues = MWL8K_TX_QUEUES; | 3607 | hw->queues = MWL8K_TX_QUEUES; |
3434 | 3608 | ||
3435 | hw->wiphy->interface_modes = priv->device_info->modes; | ||
3436 | |||
3437 | /* Set rssi and noise values to dBm */ | 3609 | /* Set rssi and noise values to dBm */ |
3438 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; | 3610 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; |
3439 | hw->vif_data_size = sizeof(struct mwl8k_vif); | 3611 | hw->vif_data_size = sizeof(struct mwl8k_vif); |
3612 | hw->sta_data_size = sizeof(struct mwl8k_sta); | ||
3440 | priv->vif = NULL; | 3613 | priv->vif = NULL; |
3441 | 3614 | ||
3442 | /* Set default radio state and preamble */ | 3615 | /* Set default radio state and preamble */ |
3443 | priv->radio_on = 0; | 3616 | priv->radio_on = 0; |
3444 | priv->radio_short_preamble = 0; | 3617 | priv->radio_short_preamble = 0; |
3445 | 3618 | ||
3619 | /* Station database handling */ | ||
3620 | INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker); | ||
3621 | spin_lock_init(&priv->sta_notify_list_lock); | ||
3622 | INIT_LIST_HEAD(&priv->sta_notify_list); | ||
3623 | |||
3446 | /* Finalize join worker */ | 3624 | /* Finalize join worker */ |
3447 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); | 3625 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); |
3448 | 3626 | ||
@@ -3454,11 +3632,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3454 | /* Power management cookie */ | 3632 | /* Power management cookie */ |
3455 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); | 3633 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); |
3456 | if (priv->cookie == NULL) | 3634 | if (priv->cookie == NULL) |
3457 | goto err_iounmap; | 3635 | goto err_stop_firmware; |
3458 | 3636 | ||
3459 | rc = mwl8k_rxq_init(hw, 0); | 3637 | rc = mwl8k_rxq_init(hw, 0); |
3460 | if (rc) | 3638 | if (rc) |
3461 | goto err_iounmap; | 3639 | goto err_free_cookie; |
3462 | rxq_refill(hw, 0, INT_MAX); | 3640 | rxq_refill(hw, 0, INT_MAX); |
3463 | 3641 | ||
3464 | mutex_init(&priv->fw_mutex); | 3642 | mutex_init(&priv->fw_mutex); |
@@ -3489,28 +3667,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3489 | goto err_free_queues; | 3667 | goto err_free_queues; |
3490 | } | 3668 | } |
3491 | 3669 | ||
3492 | /* Reset firmware and hardware */ | ||
3493 | mwl8k_hw_reset(priv); | ||
3494 | |||
3495 | /* Ask userland hotplug daemon for the device firmware */ | ||
3496 | rc = mwl8k_request_firmware(priv); | ||
3497 | if (rc) { | ||
3498 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3499 | wiphy_name(hw->wiphy)); | ||
3500 | goto err_free_irq; | ||
3501 | } | ||
3502 | |||
3503 | /* Load firmware into hardware */ | ||
3504 | rc = mwl8k_load_firmware(hw); | ||
3505 | if (rc) { | ||
3506 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3507 | wiphy_name(hw->wiphy)); | ||
3508 | goto err_stop_firmware; | ||
3509 | } | ||
3510 | |||
3511 | /* Reclaim memory once firmware is successfully loaded */ | ||
3512 | mwl8k_release_firmware(priv); | ||
3513 | |||
3514 | /* | 3670 | /* |
3515 | * Temporarily enable interrupts. Initial firmware host | 3671 | * Temporarily enable interrupts. Initial firmware host |
3516 | * commands use interrupts and avoids polling. Disable | 3672 | * commands use interrupts and avoids polling. Disable |
@@ -3525,26 +3681,28 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3525 | rc = mwl8k_cmd_set_hw_spec(hw); | 3681 | rc = mwl8k_cmd_set_hw_spec(hw); |
3526 | } else { | 3682 | } else { |
3527 | rc = mwl8k_cmd_get_hw_spec_sta(hw); | 3683 | rc = mwl8k_cmd_get_hw_spec_sta(hw); |
3684 | |||
3685 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
3528 | } | 3686 | } |
3529 | if (rc) { | 3687 | if (rc) { |
3530 | printk(KERN_ERR "%s: Cannot initialise firmware\n", | 3688 | printk(KERN_ERR "%s: Cannot initialise firmware\n", |
3531 | wiphy_name(hw->wiphy)); | 3689 | wiphy_name(hw->wiphy)); |
3532 | goto err_stop_firmware; | 3690 | goto err_free_irq; |
3533 | } | 3691 | } |
3534 | 3692 | ||
3535 | /* Turn radio off */ | 3693 | /* Turn radio off */ |
3536 | rc = mwl8k_cmd_802_11_radio_disable(hw); | 3694 | rc = mwl8k_cmd_radio_disable(hw); |
3537 | if (rc) { | 3695 | if (rc) { |
3538 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); | 3696 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); |
3539 | goto err_stop_firmware; | 3697 | goto err_free_irq; |
3540 | } | 3698 | } |
3541 | 3699 | ||
3542 | /* Clear MAC address */ | 3700 | /* Clear MAC address */ |
3543 | rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 3701 | rc = mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); |
3544 | if (rc) { | 3702 | if (rc) { |
3545 | printk(KERN_ERR "%s: Cannot clear MAC address\n", | 3703 | printk(KERN_ERR "%s: Cannot clear MAC address\n", |
3546 | wiphy_name(hw->wiphy)); | 3704 | wiphy_name(hw->wiphy)); |
3547 | goto err_stop_firmware; | 3705 | goto err_free_irq; |
3548 | } | 3706 | } |
3549 | 3707 | ||
3550 | /* Disable interrupts */ | 3708 | /* Disable interrupts */ |
@@ -3555,7 +3713,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3555 | if (rc) { | 3713 | if (rc) { |
3556 | printk(KERN_ERR "%s: Cannot register device\n", | 3714 | printk(KERN_ERR "%s: Cannot register device\n", |
3557 | wiphy_name(hw->wiphy)); | 3715 | wiphy_name(hw->wiphy)); |
3558 | goto err_stop_firmware; | 3716 | goto err_free_queues; |
3559 | } | 3717 | } |
3560 | 3718 | ||
3561 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", | 3719 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", |
@@ -3567,10 +3725,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3567 | 3725 | ||
3568 | return 0; | 3726 | return 0; |
3569 | 3727 | ||
3570 | err_stop_firmware: | ||
3571 | mwl8k_hw_reset(priv); | ||
3572 | mwl8k_release_firmware(priv); | ||
3573 | |||
3574 | err_free_irq: | 3728 | err_free_irq: |
3575 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3729 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3576 | free_irq(priv->pdev->irq, hw); | 3730 | free_irq(priv->pdev->irq, hw); |
@@ -3580,11 +3734,16 @@ err_free_queues: | |||
3580 | mwl8k_txq_deinit(hw, i); | 3734 | mwl8k_txq_deinit(hw, i); |
3581 | mwl8k_rxq_deinit(hw, 0); | 3735 | mwl8k_rxq_deinit(hw, 0); |
3582 | 3736 | ||
3583 | err_iounmap: | 3737 | err_free_cookie: |
3584 | if (priv->cookie != NULL) | 3738 | if (priv->cookie != NULL) |
3585 | pci_free_consistent(priv->pdev, 4, | 3739 | pci_free_consistent(priv->pdev, 4, |
3586 | priv->cookie, priv->cookie_dma); | 3740 | priv->cookie, priv->cookie_dma); |
3587 | 3741 | ||
3742 | err_stop_firmware: | ||
3743 | mwl8k_hw_reset(priv); | ||
3744 | mwl8k_release_firmware(priv); | ||
3745 | |||
3746 | err_iounmap: | ||
3588 | if (priv->regs != NULL) | 3747 | if (priv->regs != NULL) |
3589 | pci_iounmap(pdev, priv->regs); | 3748 | pci_iounmap(pdev, priv->regs); |
3590 | 3749 | ||
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 18012dbfb45d..26428e4c9c60 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | static int p54_add_interface(struct ieee80211_hw *dev, | 218 | static int p54_add_interface(struct ieee80211_hw *dev, |
219 | struct ieee80211_if_init_conf *conf) | 219 | struct ieee80211_vif *vif) |
220 | { | 220 | { |
221 | struct p54_common *priv = dev->priv; | 221 | struct p54_common *priv = dev->priv; |
222 | 222 | ||
@@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
226 | return -EOPNOTSUPP; | 226 | return -EOPNOTSUPP; |
227 | } | 227 | } |
228 | 228 | ||
229 | priv->vif = conf->vif; | 229 | priv->vif = vif; |
230 | 230 | ||
231 | switch (conf->type) { | 231 | switch (vif->type) { |
232 | case NL80211_IFTYPE_STATION: | 232 | case NL80211_IFTYPE_STATION: |
233 | case NL80211_IFTYPE_ADHOC: | 233 | case NL80211_IFTYPE_ADHOC: |
234 | case NL80211_IFTYPE_AP: | 234 | case NL80211_IFTYPE_AP: |
235 | case NL80211_IFTYPE_MESH_POINT: | 235 | case NL80211_IFTYPE_MESH_POINT: |
236 | priv->mode = conf->type; | 236 | priv->mode = vif->type; |
237 | break; | 237 | break; |
238 | default: | 238 | default: |
239 | mutex_unlock(&priv->conf_mutex); | 239 | mutex_unlock(&priv->conf_mutex); |
240 | return -EOPNOTSUPP; | 240 | return -EOPNOTSUPP; |
241 | } | 241 | } |
242 | 242 | ||
243 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 243 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
244 | p54_setup_mac(priv); | 244 | p54_setup_mac(priv); |
245 | mutex_unlock(&priv->conf_mutex); | 245 | mutex_unlock(&priv->conf_mutex); |
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static void p54_remove_interface(struct ieee80211_hw *dev, | 249 | static void p54_remove_interface(struct ieee80211_hw *dev, |
250 | struct ieee80211_if_init_conf *conf) | 250 | struct ieee80211_vif *vif) |
251 | { | 251 | { |
252 | struct p54_common *priv = dev->priv; | 252 | struct p54_common *priv = dev->priv; |
253 | 253 | ||
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/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bf60689aaabb..3ca824a91ad9 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -54,12 +54,12 @@ config RT61PCI | |||
54 | When compiled as a module, this driver will be called rt61pci. | 54 | When compiled as a module, this driver will be called rt61pci. |
55 | 55 | ||
56 | config RT2800PCI_PCI | 56 | config RT2800PCI_PCI |
57 | tristate | 57 | boolean |
58 | depends on PCI | 58 | depends on PCI |
59 | default y | 59 | default y |
60 | 60 | ||
61 | config RT2800PCI_SOC | 61 | config RT2800PCI_SOC |
62 | tristate | 62 | boolean |
63 | depends on RALINK_RT288X || RALINK_RT305X | 63 | depends on RALINK_RT288X || RALINK_RT305X |
64 | default y | 64 | default y |
65 | 65 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e7f46405a418..d86d233c6810 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
451 | /* | 451 | /* |
452 | * RF2420 chipset don't need any additional actions. | 452 | * RF2420 chipset don't need any additional actions. |
453 | */ | 453 | */ |
454 | if (rt2x00_rf(&rt2x00dev->chip, RF2420)) | 454 | if (rt2x00_rf(rt2x00dev, RF2420)) |
455 | return; | 455 | return; |
456 | 456 | ||
457 | /* | 457 | /* |
@@ -1343,8 +1343,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1344 | rt2x00_print_chip(rt2x00dev); | 1344 | rt2x00_print_chip(rt2x00dev); |
1345 | 1345 | ||
1346 | if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && | 1346 | if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { |
1347 | !rt2x00_rf(&rt2x00dev->chip, RF2421)) { | ||
1348 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1347 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1349 | return -ENODEV; | 1348 | return -ENODEV; |
1350 | } | 1349 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 408fcfc120f5..46cbc6ef66ab 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
440 | /* | 440 | /* |
441 | * RT2525E and RT5222 need to flip TX I/Q | 441 | * RT2525E and RT5222 need to flip TX I/Q |
442 | */ | 442 | */ |
443 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 443 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
444 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
445 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 444 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
446 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); | 445 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); |
447 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); | 446 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); |
@@ -449,7 +448,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
449 | /* | 448 | /* |
450 | * RT2525E does not need RX I/Q Flip. | 449 | * RT2525E does not need RX I/Q Flip. |
451 | */ | 450 | */ |
452 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 451 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
453 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 452 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
454 | } else { | 453 | } else { |
455 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); | 454 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); |
@@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
475 | * Switch on tuning bits. | 474 | * Switch on tuning bits. |
476 | * For RT2523 devices we do not need to update the R1 register. | 475 | * For RT2523 devices we do not need to update the R1 register. |
477 | */ | 476 | */ |
478 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) | 477 | if (!rt2x00_rf(rt2x00dev, RF2523)) |
479 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); | 478 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); |
480 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); | 479 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); |
481 | 480 | ||
482 | /* | 481 | /* |
483 | * For RT2525 we should first set the channel to half band higher. | 482 | * For RT2525 we should first set the channel to half band higher. |
484 | */ | 483 | */ |
485 | if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 484 | if (rt2x00_rf(rt2x00dev, RF2525)) { |
486 | static const u32 vals[] = { | 485 | static const u32 vals[] = { |
487 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, | 486 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, |
488 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, | 487 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, |
@@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
516 | * Switch off tuning bits. | 515 | * Switch off tuning bits. |
517 | * For RT2523 devices we do not need to update the R1 register. | 516 | * For RT2523 devices we do not need to update the R1 register. |
518 | */ | 517 | */ |
519 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 518 | if (!rt2x00_rf(rt2x00dev, RF2523)) { |
520 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); | 519 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); |
521 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); | 520 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); |
522 | } | 521 | } |
@@ -640,7 +639,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
640 | * up to version C the link tuning should halt after 20 | 639 | * up to version C the link tuning should halt after 20 |
641 | * seconds while being associated. | 640 | * seconds while being associated. |
642 | */ | 641 | */ |
643 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && | 642 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D && |
644 | rt2x00dev->intf_associated && count > 20) | 643 | rt2x00dev->intf_associated && count > 20) |
645 | return; | 644 | return; |
646 | 645 | ||
@@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
650 | * should go straight to dynamic CCA tuning when they | 649 | * should go straight to dynamic CCA tuning when they |
651 | * are not associated. | 650 | * are not associated. |
652 | */ | 651 | */ |
653 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || | 652 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D || |
654 | !rt2x00dev->intf_associated) | 653 | !rt2x00dev->intf_associated) |
655 | goto dynamic_cca_tune; | 654 | goto dynamic_cca_tune; |
656 | 655 | ||
@@ -1507,12 +1506,12 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1507 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1506 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1508 | rt2x00_print_chip(rt2x00dev); | 1507 | rt2x00_print_chip(rt2x00dev); |
1509 | 1508 | ||
1510 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1509 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1511 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1510 | !rt2x00_rf(rt2x00dev, RF2523) && |
1512 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1511 | !rt2x00_rf(rt2x00dev, RF2524) && |
1513 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1512 | !rt2x00_rf(rt2x00dev, RF2525) && |
1514 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1513 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1515 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1514 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1516 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1515 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1517 | return -ENODEV; | 1516 | return -ENODEV; |
1518 | } | 1517 | } |
@@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1744 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1743 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1745 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1744 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1746 | 1745 | ||
1747 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1746 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1748 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1747 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1749 | spec->channels = rf_vals_bg_2522; | 1748 | spec->channels = rf_vals_bg_2522; |
1750 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1749 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1751 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1750 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1752 | spec->channels = rf_vals_bg_2523; | 1751 | spec->channels = rf_vals_bg_2523; |
1753 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1752 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1754 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1753 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1755 | spec->channels = rf_vals_bg_2524; | 1754 | spec->channels = rf_vals_bg_2524; |
1756 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1755 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1757 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1756 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1758 | spec->channels = rf_vals_bg_2525; | 1757 | spec->channels = rf_vals_bg_2525; |
1759 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1758 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1760 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1759 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1761 | spec->channels = rf_vals_bg_2525e; | 1760 | spec->channels = rf_vals_bg_2525e; |
1762 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1761 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1763 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1762 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1764 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1763 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1765 | spec->channels = rf_vals_5222; | 1764 | spec->channels = rf_vals_5222; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 83f2592c59de..9e6f865c57f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -565,8 +565,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
565 | /* | 565 | /* |
566 | * RT2525E and RT5222 need to flip TX I/Q | 566 | * RT2525E and RT5222 need to flip TX I/Q |
567 | */ | 567 | */ |
568 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 568 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
569 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
570 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 569 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
571 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); | 570 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); |
572 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); | 571 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); |
@@ -574,7 +573,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
574 | /* | 573 | /* |
575 | * RT2525E does not need RX I/Q Flip. | 574 | * RT2525E does not need RX I/Q Flip. |
576 | */ | 575 | */ |
577 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 576 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
578 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 577 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
579 | } else { | 578 | } else { |
580 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); | 579 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); |
@@ -598,7 +597,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
598 | /* | 597 | /* |
599 | * For RT2525E we should first set the channel to half band higher. | 598 | * For RT2525E we should first set the channel to half band higher. |
600 | */ | 599 | */ |
601 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 600 | if (rt2x00_rf(rt2x00dev, RF2525E)) { |
602 | static const u32 vals[] = { | 601 | static const u32 vals[] = { |
603 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, | 602 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, |
604 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, | 603 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, |
@@ -793,7 +792,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
793 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); | 792 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); |
794 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); | 793 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); |
795 | 794 | ||
796 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { | 795 | if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { |
797 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); | 796 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); |
798 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); | 797 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); |
799 | } else { | 798 | } else { |
@@ -1411,19 +1410,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1411 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); | 1410 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); |
1412 | rt2x00_print_chip(rt2x00dev); | 1411 | rt2x00_print_chip(rt2x00dev); |
1413 | 1412 | ||
1414 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) || | 1413 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || |
1415 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | 1414 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { |
1416 | |||
1417 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1415 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1418 | return -ENODEV; | 1416 | return -ENODEV; |
1419 | } | 1417 | } |
1420 | 1418 | ||
1421 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1419 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1422 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1420 | !rt2x00_rf(rt2x00dev, RF2523) && |
1423 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1421 | !rt2x00_rf(rt2x00dev, RF2524) && |
1424 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1422 | !rt2x00_rf(rt2x00dev, RF2525) && |
1425 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1423 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1426 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1424 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1427 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1425 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1428 | return -ENODEV; | 1426 | return -ENODEV; |
1429 | } | 1427 | } |
@@ -1667,22 +1665,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1667 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1665 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1668 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1666 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1669 | 1667 | ||
1670 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1668 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1671 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1669 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1672 | spec->channels = rf_vals_bg_2522; | 1670 | spec->channels = rf_vals_bg_2522; |
1673 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1671 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1674 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1672 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1675 | spec->channels = rf_vals_bg_2523; | 1673 | spec->channels = rf_vals_bg_2523; |
1676 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1674 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1677 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1675 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1678 | spec->channels = rf_vals_bg_2524; | 1676 | spec->channels = rf_vals_bg_2524; |
1679 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1677 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1680 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1678 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1681 | spec->channels = rf_vals_bg_2525; | 1679 | spec->channels = rf_vals_bg_2525; |
1682 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1680 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1683 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1681 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1684 | spec->channels = rf_vals_bg_2525e; | 1682 | spec->channels = rf_vals_bg_2525e; |
1685 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1683 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1686 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1684 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1687 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1685 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1688 | spec->channels = rf_vals_5222; | 1686 | spec->channels = rf_vals_5222; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9deae41cb784..126899091707 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | 38 | ||
39 | #include "rt2x00.h" | 39 | #include "rt2x00.h" |
40 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 40 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
41 | #include "rt2x00usb.h" | 41 | #include "rt2x00usb.h" |
42 | #endif | 42 | #endif |
43 | #include "rt2800lib.h" | 43 | #include "rt2800lib.h" |
@@ -220,8 +220,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
220 | /* | 220 | /* |
221 | * RT2880 and RT3052 don't support MCU requests. | 221 | * RT2880 and RT3052 don't support MCU requests. |
222 | */ | 222 | */ |
223 | if (rt2x00_rt(&rt2x00dev->chip, RT2880) || | 223 | if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052)) |
224 | rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
225 | return; | 224 | return; |
226 | 225 | ||
227 | mutex_lock(&rt2x00dev->csr_mutex); | 226 | mutex_lock(&rt2x00dev->csr_mutex); |
@@ -806,12 +805,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
806 | unsigned int tx_pin; | 805 | unsigned int tx_pin; |
807 | u8 bbp; | 806 | u8 bbp; |
808 | 807 | ||
809 | if ((rt2x00_rt(&rt2x00dev->chip, RT3070) || | 808 | if ((rt2x00_rt(rt2x00dev, RT3070) || |
810 | rt2x00_rt(&rt2x00dev->chip, RT3090)) && | 809 | rt2x00_rt(rt2x00dev, RT3090)) && |
811 | (rt2x00_rf(&rt2x00dev->chip, RF2020) || | 810 | (rt2x00_rf(rt2x00dev, RF2020) || |
812 | rt2x00_rf(&rt2x00dev->chip, RF3020) || | 811 | rt2x00_rf(rt2x00dev, RF3020) || |
813 | rt2x00_rf(&rt2x00dev->chip, RF3021) || | 812 | rt2x00_rf(rt2x00dev, RF3021) || |
814 | rt2x00_rf(&rt2x00dev->chip, RF3022))) | 813 | rt2x00_rf(rt2x00dev, RF3022))) |
815 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); | 814 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); |
816 | else | 815 | else |
817 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); | 816 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); |
@@ -878,7 +877,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
878 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | 877 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); |
879 | rt2800_bbp_write(rt2x00dev, 3, bbp); | 878 | rt2800_bbp_write(rt2x00dev, 3, bbp); |
880 | 879 | ||
881 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 880 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { |
882 | if (conf_is_ht40(conf)) { | 881 | if (conf_is_ht40(conf)) { |
883 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | 882 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); |
884 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 883 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
@@ -1041,7 +1040,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
1041 | { | 1040 | { |
1042 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 1041 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
1043 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1042 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1044 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) | 1043 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) |
1045 | return 0x1c + (2 * rt2x00dev->lna_gain); | 1044 | return 0x1c + (2 * rt2x00dev->lna_gain); |
1046 | else | 1045 | else |
1047 | return 0x2e + rt2x00dev->lna_gain; | 1046 | return 0x2e + rt2x00dev->lna_gain; |
@@ -1072,7 +1071,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
1072 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 1071 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
1073 | const u32 count) | 1072 | const u32 count) |
1074 | { | 1073 | { |
1075 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | 1074 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) |
1076 | return; | 1075 | return; |
1077 | 1076 | ||
1078 | /* | 1077 | /* |
@@ -1121,7 +1120,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1121 | 1120 | ||
1122 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1121 | if (rt2x00_intf_is_usb(rt2x00dev)) { |
1123 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | 1122 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); |
1124 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 1123 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
1125 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 1124 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
1126 | USB_MODE_RESET, REGISTER_TIMEOUT); | 1125 | USB_MODE_RESET, REGISTER_TIMEOUT); |
1127 | #endif | 1126 | #endif |
@@ -1158,7 +1157,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1158 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1157 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1159 | 1158 | ||
1160 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1159 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1161 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1160 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { |
1162 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1161 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1163 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 1162 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
1164 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1163 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -1185,8 +1184,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1185 | 1184 | ||
1186 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); | 1185 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); |
1187 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | 1186 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); |
1188 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && | 1187 | if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION && |
1189 | rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) | 1188 | rt2x00_rev(rt2x00dev) < RT3070_VERSION) |
1190 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | 1189 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); |
1191 | else | 1190 | else |
1192 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | 1191 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); |
@@ -1465,22 +1464,22 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1465 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 1464 | rt2800_bbp_write(rt2x00dev, 103, 0x00); |
1466 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1465 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1467 | 1466 | ||
1468 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 1467 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { |
1469 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 1468 | rt2800_bbp_write(rt2x00dev, 69, 0x16); |
1470 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 1469 | rt2800_bbp_write(rt2x00dev, 73, 0x12); |
1471 | } | 1470 | } |
1472 | 1471 | ||
1473 | if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) | 1472 | if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) |
1474 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1473 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
1475 | 1474 | ||
1476 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1475 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1477 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1476 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { |
1478 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 1477 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
1479 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1478 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
1480 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1479 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1481 | } | 1480 | } |
1482 | 1481 | ||
1483 | if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { | 1482 | if (rt2x00_rt(rt2x00dev, RT3052)) { |
1484 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | 1483 | rt2800_bbp_write(rt2x00dev, 31, 0x08); |
1485 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 1484 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
1486 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 1485 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
@@ -1566,13 +1565,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1566 | u8 bbp; | 1565 | u8 bbp; |
1567 | 1566 | ||
1568 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1567 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1569 | rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | 1568 | rt2x00_rev(rt2x00dev) != RT3070_VERSION) |
1570 | return 0; | 1569 | return 0; |
1571 | 1570 | ||
1572 | if (rt2x00_intf_is_pci(rt2x00dev)) { | 1571 | if (rt2x00_intf_is_pci(rt2x00dev)) { |
1573 | if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1572 | if (!rt2x00_rf(rt2x00dev, RF3020) && |
1574 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1573 | !rt2x00_rf(rt2x00dev, RF3021) && |
1575 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) | 1574 | !rt2x00_rf(rt2x00dev, RF3022)) |
1576 | return 0; | 1575 | return 0; |
1577 | } | 1576 | } |
1578 | 1577 | ||
@@ -1737,7 +1736,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1737 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); | 1736 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); |
1738 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | 1737 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); |
1739 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | 1738 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); |
1740 | } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { | 1739 | } else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) { |
1741 | /* | 1740 | /* |
1742 | * There is a max of 2 RX streams for RT28x0 series | 1741 | * There is a max of 2 RX streams for RT28x0 series |
1743 | */ | 1742 | */ |
@@ -1839,17 +1838,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1839 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1838 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1840 | 1839 | ||
1841 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1840 | if (rt2x00_intf_is_usb(rt2x00dev)) { |
1842 | struct rt2x00_chip *chip = &rt2x00dev->chip; | ||
1843 | |||
1844 | /* | 1841 | /* |
1845 | * The check for rt2860 is not a typo, some rt2870 hardware | 1842 | * The check for rt2860 is not a typo, some rt2870 hardware |
1846 | * identifies itself as rt2860 in the CSR register. | 1843 | * identifies itself as rt2860 in the CSR register. |
1847 | */ | 1844 | */ |
1848 | if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) || | 1845 | if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) || |
1849 | rt2x00_check_rev(chip, 0xfff00000, 0x28700000) || | 1846 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) || |
1850 | rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) { | 1847 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) { |
1851 | rt2x00_set_chip_rt(rt2x00dev, RT2870); | 1848 | rt2x00_set_chip_rt(rt2x00dev, RT2870); |
1852 | } else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) { | 1849 | } else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) { |
1853 | rt2x00_set_chip_rt(rt2x00dev, RT3070); | 1850 | rt2x00_set_chip_rt(rt2x00dev, RT3070); |
1854 | } else { | 1851 | } else { |
1855 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1852 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
@@ -1858,14 +1855,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1858 | } | 1855 | } |
1859 | rt2x00_print_chip(rt2x00dev); | 1856 | rt2x00_print_chip(rt2x00dev); |
1860 | 1857 | ||
1861 | if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && | 1858 | if (!rt2x00_rf(rt2x00dev, RF2820) && |
1862 | !rt2x00_rf(&rt2x00dev->chip, RF2850) && | 1859 | !rt2x00_rf(rt2x00dev, RF2850) && |
1863 | !rt2x00_rf(&rt2x00dev->chip, RF2720) && | 1860 | !rt2x00_rf(rt2x00dev, RF2720) && |
1864 | !rt2x00_rf(&rt2x00dev->chip, RF2750) && | 1861 | !rt2x00_rf(rt2x00dev, RF2750) && |
1865 | !rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1862 | !rt2x00_rf(rt2x00dev, RF3020) && |
1866 | !rt2x00_rf(&rt2x00dev->chip, RF2020) && | 1863 | !rt2x00_rf(rt2x00dev, RF2020) && |
1867 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1864 | !rt2x00_rf(rt2x00dev, RF3021) && |
1868 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) { | 1865 | !rt2x00_rf(rt2x00dev, RF3022)) { |
1869 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1866 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1870 | return -ENODEV; | 1867 | return -ENODEV; |
1871 | } | 1868 | } |
@@ -2013,7 +2010,6 @@ static const struct rf_channel rf_vals_302x[] = { | |||
2013 | 2010 | ||
2014 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 2011 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
2015 | { | 2012 | { |
2016 | struct rt2x00_chip *chip = &rt2x00dev->chip; | ||
2017 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 2013 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
2018 | struct channel_info *info; | 2014 | struct channel_info *info; |
2019 | char *tx_power1; | 2015 | char *tx_power1; |
@@ -2049,19 +2045,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2049 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2045 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2050 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2046 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2051 | 2047 | ||
2052 | if (rt2x00_rf(chip, RF2820) || | 2048 | if (rt2x00_rf(rt2x00dev, RF2820) || |
2053 | rt2x00_rf(chip, RF2720) || | 2049 | rt2x00_rf(rt2x00dev, RF2720) || |
2054 | (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) { | 2050 | (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) { |
2055 | spec->num_channels = 14; | 2051 | spec->num_channels = 14; |
2056 | spec->channels = rf_vals; | 2052 | spec->channels = rf_vals; |
2057 | } else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) { | 2053 | } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { |
2058 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2054 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2059 | spec->num_channels = ARRAY_SIZE(rf_vals); | 2055 | spec->num_channels = ARRAY_SIZE(rf_vals); |
2060 | spec->channels = rf_vals; | 2056 | spec->channels = rf_vals; |
2061 | } else if (rt2x00_rf(chip, RF3020) || | 2057 | } else if (rt2x00_rf(rt2x00dev, RF3020) || |
2062 | rt2x00_rf(chip, RF2020) || | 2058 | rt2x00_rf(rt2x00dev, RF2020) || |
2063 | rt2x00_rf(chip, RF3021) || | 2059 | rt2x00_rf(rt2x00dev, RF3021) || |
2064 | rt2x00_rf(chip, RF3022)) { | 2060 | rt2x00_rf(rt2x00dev, RF3022)) { |
2065 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); | 2061 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); |
2066 | spec->channels = rf_vals_302x; | 2062 | spec->channels = rf_vals_302x; |
2067 | } | 2063 | } |
@@ -2069,7 +2065,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2069 | /* | 2065 | /* |
2070 | * Initialize HT information. | 2066 | * Initialize HT information. |
2071 | */ | 2067 | */ |
2072 | if (!rt2x00_rf(chip, RF2020)) | 2068 | if (!rt2x00_rf(rt2x00dev, RF2020)) |
2073 | spec->ht.ht_supported = true; | 2069 | spec->ht.ht_supported = true; |
2074 | else | 2070 | else |
2075 | spec->ht.ht_supported = false; | 2071 | spec->ht.ht_supported = false; |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index dfc886fcb44d..b93eabb4fbe1 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -48,14 +48,6 @@ | |||
48 | #include "rt2800.h" | 48 | #include "rt2800.h" |
49 | #include "rt2800pci.h" | 49 | #include "rt2800pci.h" |
50 | 50 | ||
51 | #ifdef CONFIG_RT2800PCI_PCI_MODULE | ||
52 | #define CONFIG_RT2800PCI_PCI | ||
53 | #endif | ||
54 | |||
55 | #ifdef CONFIG_RT2800PCI_WISOC_MODULE | ||
56 | #define CONFIG_RT2800PCI_WISOC | ||
57 | #endif | ||
58 | |||
59 | /* | 51 | /* |
60 | * Allow hardware encryption to be disabled. | 52 | * Allow hardware encryption to be disabled. |
61 | */ | 53 | */ |
@@ -87,7 +79,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
87 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 79 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
88 | } | 80 | } |
89 | 81 | ||
90 | #ifdef CONFIG_RT2800PCI_WISOC | 82 | #ifdef CONFIG_RT2800PCI_SOC |
91 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 83 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
92 | { | 84 | { |
93 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ | 85 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ |
@@ -98,7 +90,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
98 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 90 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
99 | { | 91 | { |
100 | } | 92 | } |
101 | #endif /* CONFIG_RT2800PCI_WISOC */ | 93 | #endif /* CONFIG_RT2800PCI_SOC */ |
102 | 94 | ||
103 | #ifdef CONFIG_RT2800PCI_PCI | 95 | #ifdef CONFIG_RT2800PCI_PCI |
104 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 96 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -835,7 +827,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
835 | struct rxdone_entry_desc *rxdesc) | 827 | struct rxdone_entry_desc *rxdesc) |
836 | { | 828 | { |
837 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 829 | 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; | 830 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
840 | __le32 *rxd = entry_priv->desc; | 831 | __le32 *rxd = entry_priv->desc; |
841 | __le32 *rxwi = (__le32 *)entry->skb->data; | 832 | __le32 *rxwi = (__le32 *)entry->skb->data; |
@@ -883,10 +874,8 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
883 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) | 874 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) |
884 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 875 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
885 | 876 | ||
886 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { | 877 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) |
887 | rxdesc->dev_flags |= RXDONE_L2PAD; | 878 | rxdesc->dev_flags |= RXDONE_L2PAD; |
888 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
889 | } | ||
890 | 879 | ||
891 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 880 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
892 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 881 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -927,7 +916,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
927 | * Remove TXWI descriptor from start of buffer. | 916 | * Remove TXWI descriptor from start of buffer. |
928 | */ | 917 | */ |
929 | skb_pull(entry->skb, RXWI_DESC_SIZE); | 918 | skb_pull(entry->skb, RXWI_DESC_SIZE); |
930 | skb_trim(entry->skb, rxdesc->size); | ||
931 | } | 919 | } |
932 | 920 | ||
933 | /* | 921 | /* |
@@ -1133,8 +1121,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1133 | /* | 1121 | /* |
1134 | * This device requires firmware. | 1122 | * This device requires firmware. |
1135 | */ | 1123 | */ |
1136 | if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && | 1124 | if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052)) |
1137 | !rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
1138 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 1125 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
1139 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 1126 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
1140 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 1127 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
@@ -1255,7 +1242,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1255 | #endif /* CONFIG_RT2800PCI_PCI */ | 1242 | #endif /* CONFIG_RT2800PCI_PCI */ |
1256 | MODULE_LICENSE("GPL"); | 1243 | MODULE_LICENSE("GPL"); |
1257 | 1244 | ||
1258 | #ifdef CONFIG_RT2800PCI_WISOC | 1245 | #ifdef CONFIG_RT2800PCI_SOC |
1259 | #if defined(CONFIG_RALINK_RT288X) | 1246 | #if defined(CONFIG_RALINK_RT288X) |
1260 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); | 1247 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); |
1261 | #elif defined(CONFIG_RALINK_RT305X) | 1248 | #elif defined(CONFIG_RALINK_RT305X) |
@@ -1273,7 +1260,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1273 | .suspend = rt2x00soc_suspend, | 1260 | .suspend = rt2x00soc_suspend, |
1274 | .resume = rt2x00soc_resume, | 1261 | .resume = rt2x00soc_resume, |
1275 | }; | 1262 | }; |
1276 | #endif /* CONFIG_RT2800PCI_WISOC */ | 1263 | #endif /* CONFIG_RT2800PCI_SOC */ |
1277 | 1264 | ||
1278 | #ifdef CONFIG_RT2800PCI_PCI | 1265 | #ifdef CONFIG_RT2800PCI_PCI |
1279 | static struct pci_driver rt2800pci_driver = { | 1266 | static struct pci_driver rt2800pci_driver = { |
@@ -1290,7 +1277,7 @@ static int __init rt2800pci_init(void) | |||
1290 | { | 1277 | { |
1291 | int ret = 0; | 1278 | int ret = 0; |
1292 | 1279 | ||
1293 | #ifdef CONFIG_RT2800PCI_WISOC | 1280 | #ifdef CONFIG_RT2800PCI_SOC |
1294 | ret = platform_driver_register(&rt2800soc_driver); | 1281 | ret = platform_driver_register(&rt2800soc_driver); |
1295 | if (ret) | 1282 | if (ret) |
1296 | return ret; | 1283 | return ret; |
@@ -1298,7 +1285,7 @@ static int __init rt2800pci_init(void) | |||
1298 | #ifdef CONFIG_RT2800PCI_PCI | 1285 | #ifdef CONFIG_RT2800PCI_PCI |
1299 | ret = pci_register_driver(&rt2800pci_driver); | 1286 | ret = pci_register_driver(&rt2800pci_driver); |
1300 | if (ret) { | 1287 | if (ret) { |
1301 | #ifdef CONFIG_RT2800PCI_WISOC | 1288 | #ifdef CONFIG_RT2800PCI_SOC |
1302 | platform_driver_unregister(&rt2800soc_driver); | 1289 | platform_driver_unregister(&rt2800soc_driver); |
1303 | #endif | 1290 | #endif |
1304 | return ret; | 1291 | return ret; |
@@ -1313,7 +1300,7 @@ static void __exit rt2800pci_exit(void) | |||
1313 | #ifdef CONFIG_RT2800PCI_PCI | 1300 | #ifdef CONFIG_RT2800PCI_PCI |
1314 | pci_unregister_driver(&rt2800pci_driver); | 1301 | pci_unregister_driver(&rt2800pci_driver); |
1315 | #endif | 1302 | #endif |
1316 | #ifdef CONFIG_RT2800PCI_WISOC | 1303 | #ifdef CONFIG_RT2800PCI_SOC |
1317 | platform_driver_unregister(&rt2800soc_driver); | 1304 | platform_driver_unregister(&rt2800soc_driver); |
1318 | #endif | 1305 | #endif |
1319 | } | 1306 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ab95346cf6a3..0510f020dcf5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -92,7 +92,7 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | 92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, |
93 | const u8 *data, const size_t len) | 93 | const u8 *data, const size_t len) |
94 | { | 94 | { |
95 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | 95 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; |
96 | size_t offset = 0; | 96 | size_t offset = 0; |
97 | 97 | ||
98 | /* | 98 | /* |
@@ -138,7 +138,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
138 | u32 reg; | 138 | u32 reg; |
139 | u32 offset; | 139 | u32 offset; |
140 | u32 length; | 140 | u32 length; |
141 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | 141 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * Check which section of the firmware we need. | 144 | * Check which section of the firmware we need. |
@@ -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 dcfc8c25d1a7..096da85a66fa 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 |
@@ -937,25 +943,25 @@ static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) | |||
937 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 943 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
938 | } | 944 | } |
939 | 945 | ||
940 | static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) | 946 | static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
941 | { | 947 | { |
942 | return (chipset->rt == chip); | 948 | return (rt2x00dev->chip.rt == rt); |
943 | } | 949 | } |
944 | 950 | ||
945 | static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) | 951 | static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) |
946 | { | 952 | { |
947 | return (chipset->rf == chip); | 953 | return (rt2x00dev->chip.rf == rf); |
948 | } | 954 | } |
949 | 955 | ||
950 | static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) | 956 | static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev) |
951 | { | 957 | { |
952 | return chipset->rev; | 958 | return rt2x00dev->chip.rev; |
953 | } | 959 | } |
954 | 960 | ||
955 | static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, | 961 | static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev, |
956 | const u32 mask, const u32 rev) | 962 | const u32 mask, const u32 rev) |
957 | { | 963 | { |
958 | return ((chipset->rev & mask) == rev); | 964 | return ((rt2x00dev->chip.rev & mask) == rev); |
959 | } | 965 | } |
960 | 966 | ||
961 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | 967 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, |
@@ -964,20 +970,20 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | |||
964 | rt2x00dev->chip.intf = intf; | 970 | rt2x00dev->chip.intf = intf; |
965 | } | 971 | } |
966 | 972 | ||
967 | static inline bool rt2x00_intf(const struct rt2x00_chip *chipset, | 973 | static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, |
968 | enum rt2x00_chip_intf intf) | 974 | enum rt2x00_chip_intf intf) |
969 | { | 975 | { |
970 | return (chipset->intf == intf); | 976 | return (rt2x00dev->chip.intf == intf); |
971 | } | 977 | } |
972 | 978 | ||
973 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) | 979 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) |
974 | { | 980 | { |
975 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI); | 981 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); |
976 | } | 982 | } |
977 | 983 | ||
978 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) | 984 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) |
979 | { | 985 | { |
980 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB); | 986 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
981 | } | 987 | } |
982 | 988 | ||
983 | /** | 989 | /** |
@@ -1019,9 +1025,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1019 | int rt2x00mac_start(struct ieee80211_hw *hw); | 1025 | int rt2x00mac_start(struct ieee80211_hw *hw); |
1020 | void rt2x00mac_stop(struct ieee80211_hw *hw); | 1026 | void rt2x00mac_stop(struct ieee80211_hw *hw); |
1021 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 1027 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
1022 | struct ieee80211_if_init_conf *conf); | 1028 | struct ieee80211_vif *vif); |
1023 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 1029 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
1024 | struct ieee80211_if_init_conf *conf); | 1030 | struct ieee80211_vif *vif); |
1025 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); | 1031 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); |
1026 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 1032 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
1027 | unsigned int changed_flags, | 1033 | unsigned int changed_flags, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 265e66dba552..b93731b79903 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/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index de549c244ed8..00f1f939f1bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) | |||
187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); | 187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); |
188 | 188 | ||
189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
190 | struct ieee80211_if_init_conf *conf) | 190 | struct ieee80211_vif *vif) |
191 | { | 191 | { |
192 | struct rt2x00_dev *rt2x00dev = hw->priv; | 192 | struct rt2x00_dev *rt2x00dev = hw->priv; |
193 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 193 | struct rt2x00_intf *intf = vif_to_intf(vif); |
194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); | 194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); |
195 | struct queue_entry *entry = NULL; | 195 | struct queue_entry *entry = NULL; |
196 | unsigned int i; | 196 | unsigned int i; |
@@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | 203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
204 | return -ENODEV; | 204 | return -ENODEV; |
205 | 205 | ||
206 | switch (conf->type) { | 206 | switch (vif->type) { |
207 | case NL80211_IFTYPE_AP: | 207 | case NL80211_IFTYPE_AP: |
208 | /* | 208 | /* |
209 | * We don't support mixed combinations of | 209 | * We don't support mixed combinations of |
@@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
263 | * increase interface count and start initialization. | 263 | * increase interface count and start initialization. |
264 | */ | 264 | */ |
265 | 265 | ||
266 | if (conf->type == NL80211_IFTYPE_AP) | 266 | if (vif->type == NL80211_IFTYPE_AP) |
267 | rt2x00dev->intf_ap_count++; | 267 | rt2x00dev->intf_ap_count++; |
268 | else | 268 | else |
269 | rt2x00dev->intf_sta_count++; | 269 | rt2x00dev->intf_sta_count++; |
@@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
273 | mutex_init(&intf->beacon_skb_mutex); | 273 | mutex_init(&intf->beacon_skb_mutex); |
274 | intf->beacon = entry; | 274 | intf->beacon = entry; |
275 | 275 | ||
276 | if (conf->type == NL80211_IFTYPE_AP) | 276 | if (vif->type == NL80211_IFTYPE_AP) |
277 | memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); | 277 | memcpy(&intf->bssid, vif->addr, ETH_ALEN); |
278 | memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); | 278 | memcpy(&intf->mac, vif->addr, ETH_ALEN); |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * The MAC adddress must be configured after the device | 281 | * The MAC adddress must be configured after the device |
282 | * has been initialized. Otherwise the device can reset | 282 | * has been initialized. Otherwise the device can reset |
283 | * the MAC registers. | 283 | * the MAC registers. |
284 | */ | 284 | */ |
285 | rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); | 285 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * Some filters depend on the current working mode. We can force | 288 | * Some filters depend on the current working mode. We can force |
@@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); | 296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); |
297 | 297 | ||
298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
299 | struct ieee80211_if_init_conf *conf) | 299 | struct ieee80211_vif *vif) |
300 | { | 300 | { |
301 | struct rt2x00_dev *rt2x00dev = hw->priv; | 301 | struct rt2x00_dev *rt2x00dev = hw->priv; |
302 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 302 | struct rt2x00_intf *intf = vif_to_intf(vif); |
303 | 303 | ||
304 | /* | 304 | /* |
305 | * Don't allow interfaces to be remove while | 305 | * Don't allow interfaces to be remove while |
@@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
307 | * no interface is present. | 307 | * no interface is present. |
308 | */ | 308 | */ |
309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || | 309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
310 | (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || | 310 | (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || |
311 | (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) | 311 | (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | if (conf->type == NL80211_IFTYPE_AP) | 314 | if (vif->type == NL80211_IFTYPE_AP) |
315 | rt2x00dev->intf_ap_count--; | 315 | rt2x00dev->intf_ap_count--; |
316 | else | 316 | else |
317 | rt2x00dev->intf_sta_count--; | 317 | rt2x00dev->intf_sta_count--; |
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 9915a09141ef..0b4801a14601 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/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0ca589306d71..c353b497a65d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | |||
637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
639 | 639 | ||
640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325)); |
641 | rt2x00_rf(&rt2x00dev->chip, RF5325)); | ||
642 | 641 | ||
643 | /* | 642 | /* |
644 | * Configure the RX antenna. | 643 | * Configure the RX antenna. |
@@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
684 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 683 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
685 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 684 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
686 | 685 | ||
687 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); |
688 | rt2x00_rf(&rt2x00dev->chip, RF2529)); | ||
689 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
690 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); | 688 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); |
691 | 689 | ||
@@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
833 | 831 | ||
834 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); | 832 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); |
835 | 833 | ||
836 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 834 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) |
837 | rt2x00_rf(&rt2x00dev->chip, RF5325)) | ||
838 | rt61pci_config_antenna_5x(rt2x00dev, ant); | 835 | rt61pci_config_antenna_5x(rt2x00dev, ant); |
839 | else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) | 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) |
840 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
841 | else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { |
842 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) | 839 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) |
843 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
844 | else | 841 | else |
@@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
879 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 876 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
880 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 877 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
881 | 878 | ||
882 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 879 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
883 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
884 | 880 | ||
885 | rt61pci_bbp_read(rt2x00dev, 3, &r3); | 881 | rt61pci_bbp_read(rt2x00dev, 3, &r3); |
886 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 882 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -2302,10 +2298,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2302 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 2298 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
2303 | rt2x00_print_chip(rt2x00dev); | 2299 | rt2x00_print_chip(rt2x00dev); |
2304 | 2300 | ||
2305 | if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && | 2301 | if (!rt2x00_rf(rt2x00dev, RF5225) && |
2306 | !rt2x00_rf(&rt2x00dev->chip, RF5325) && | 2302 | !rt2x00_rf(rt2x00dev, RF5325) && |
2307 | !rt2x00_rf(&rt2x00dev->chip, RF2527) && | 2303 | !rt2x00_rf(rt2x00dev, RF2527) && |
2308 | !rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 2304 | !rt2x00_rf(rt2x00dev, RF2529)) { |
2309 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 2305 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
2310 | return -ENODEV; | 2306 | return -ENODEV; |
2311 | } | 2307 | } |
@@ -2360,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2360 | * the antenna settings should be gathered from the NIC | 2356 | * the antenna settings should be gathered from the NIC |
2361 | * eeprom word. | 2357 | * eeprom word. |
2362 | */ | 2358 | */ |
2363 | if (rt2x00_rf(&rt2x00dev->chip, RF2529) && | 2359 | if (rt2x00_rf(rt2x00dev, RF2529) && |
2364 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { | 2360 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { |
2365 | rt2x00dev->default_ant.rx = | 2361 | rt2x00dev->default_ant.rx = |
2366 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); | 2362 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); |
@@ -2571,8 +2567,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2571 | spec->channels = rf_vals_seq; | 2567 | spec->channels = rf_vals_seq; |
2572 | } | 2568 | } |
2573 | 2569 | ||
2574 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 2570 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) { |
2575 | rt2x00_rf(&rt2x00dev->chip, RF5325)) { | ||
2576 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2571 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2577 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); | 2572 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); |
2578 | } | 2573 | } |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ced3b6ab5e16..a02691294395 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
136 | * all others contain 20 bits. | 136 | * all others contain 20 bits. |
137 | */ | 137 | */ |
138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, | 138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, |
139 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 139 | 20 + (rt2x00_rf(rt2x00dev, RF5225) || |
140 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | 140 | rt2x00_rf(rt2x00dev, RF2527))); |
141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); |
142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); |
143 | 143 | ||
@@ -741,11 +741,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
741 | 741 | ||
742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); | 742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); |
743 | 743 | ||
744 | if (rt2x00_rf(&rt2x00dev->chip, RF5226) || | 744 | if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225)) |
745 | rt2x00_rf(&rt2x00dev->chip, RF5225)) | ||
746 | rt73usb_config_antenna_5x(rt2x00dev, ant); | 745 | rt73usb_config_antenna_5x(rt2x00dev, ant); |
747 | else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || | 746 | else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527)) |
748 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
749 | rt73usb_config_antenna_2x(rt2x00dev, ant); | 747 | rt73usb_config_antenna_2x(rt2x00dev, ant); |
750 | } | 748 | } |
751 | 749 | ||
@@ -779,8 +777,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
779 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 777 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
780 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 778 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
781 | 779 | ||
782 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 780 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
783 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
784 | 781 | ||
785 | rt73usb_bbp_read(rt2x00dev, 3, &r3); | 782 | rt73usb_bbp_read(rt2x00dev, 3, &r3); |
786 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 783 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -1210,8 +1207,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1210 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); | 1207 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); |
1211 | 1208 | ||
1212 | reg = 0x000023b0; | 1209 | reg = 0x000023b0; |
1213 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 1210 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)) |
1214 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
1215 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); | 1211 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); |
1216 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); | 1212 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); |
1217 | 1213 | ||
@@ -1827,16 +1823,16 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1827 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1823 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); |
1828 | rt2x00_print_chip(rt2x00dev); | 1824 | rt2x00_print_chip(rt2x00dev); |
1829 | 1825 | ||
1830 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || | 1826 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || |
1831 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | 1827 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { |
1832 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1828 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1833 | return -ENODEV; | 1829 | return -ENODEV; |
1834 | } | 1830 | } |
1835 | 1831 | ||
1836 | if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && | 1832 | if (!rt2x00_rf(rt2x00dev, RF5226) && |
1837 | !rt2x00_rf(&rt2x00dev->chip, RF2528) && | 1833 | !rt2x00_rf(rt2x00dev, RF2528) && |
1838 | !rt2x00_rf(&rt2x00dev->chip, RF5225) && | 1834 | !rt2x00_rf(rt2x00dev, RF5225) && |
1839 | !rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 1835 | !rt2x00_rf(rt2x00dev, RF2527)) { |
1840 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1836 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1841 | return -ENODEV; | 1837 | return -ENODEV; |
1842 | } | 1838 | } |
@@ -2081,17 +2077,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2081 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2077 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2082 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2078 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2083 | 2079 | ||
2084 | if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { | 2080 | if (rt2x00_rf(rt2x00dev, RF2528)) { |
2085 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); | 2081 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); |
2086 | spec->channels = rf_vals_bg_2528; | 2082 | spec->channels = rf_vals_bg_2528; |
2087 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { | 2083 | } else if (rt2x00_rf(rt2x00dev, RF5226)) { |
2088 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2084 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2089 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); | 2085 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); |
2090 | spec->channels = rf_vals_5226; | 2086 | spec->channels = rf_vals_5226; |
2091 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 2087 | } else if (rt2x00_rf(rt2x00dev, RF2527)) { |
2092 | spec->num_channels = 14; | 2088 | spec->num_channels = 14; |
2093 | spec->channels = rf_vals_5225_2527; | 2089 | spec->channels = rf_vals_5225_2527; |
2094 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { | 2090 | } else if (rt2x00_rf(rt2x00dev, RF5225)) { |
2095 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2091 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2096 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); | 2092 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); |
2097 | spec->channels = rf_vals_5225_2527; | 2093 | spec->channels = rf_vals_5225_2527; |
@@ -2354,6 +2350,7 @@ static struct usb_device_id rt73usb_device_table[] = { | |||
2354 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, | 2350 | { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, |
2355 | /* Buffalo */ | 2351 | /* Buffalo */ |
2356 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, | 2352 | { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, |
2353 | { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, | ||
2357 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, | 2354 | { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, |
2358 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, | 2355 | { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, |
2359 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, | 2356 | { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, |
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..de3844fe06d8 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h | |||
@@ -60,7 +60,6 @@ struct rtl8180_priv { | |||
60 | struct rtl818x_csr __iomem *map; | 60 | struct rtl818x_csr __iomem *map; |
61 | const struct rtl818x_rf_ops *rf; | 61 | const struct rtl818x_rf_ops *rf; |
62 | struct ieee80211_vif *vif; | 62 | struct ieee80211_vif *vif; |
63 | int mode; | ||
64 | 63 | ||
65 | /* rtl8180 driver specific */ | 64 | /* rtl8180 driver specific */ |
66 | spinlock_t lock; | 65 | spinlock_t lock; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 8a40a1439984..5a2b7199f5d5 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -82,8 +82,6 @@ static const struct ieee80211_channel rtl818x_channels[] = { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | 84 | ||
85 | |||
86 | |||
87 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | 85 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) |
88 | { | 86 | { |
89 | struct rtl8180_priv *priv = dev->priv; | 87 | struct rtl8180_priv *priv = dev->priv; |
@@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
615 | reg |= RTL818X_CMD_TX_ENABLE; | 613 | reg |= RTL818X_CMD_TX_ENABLE; |
616 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); | 614 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); |
617 | 615 | ||
618 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
619 | return 0; | 616 | return 0; |
620 | 617 | ||
621 | err_free_rings: | 618 | err_free_rings: |
@@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
633 | u8 reg; | 630 | u8 reg; |
634 | int i; | 631 | int i; |
635 | 632 | ||
636 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | ||
637 | |||
638 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | 633 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
639 | 634 | ||
640 | reg = rtl818x_ioread8(priv, &priv->map->CMD); | 635 | reg = rtl818x_ioread8(priv, &priv->map->CMD); |
@@ -657,38 +652,39 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
657 | } | 652 | } |
658 | 653 | ||
659 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 654 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
660 | struct ieee80211_if_init_conf *conf) | 655 | struct ieee80211_vif *vif) |
661 | { | 656 | { |
662 | struct rtl8180_priv *priv = dev->priv; | 657 | struct rtl8180_priv *priv = dev->priv; |
663 | 658 | ||
664 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 659 | /* |
665 | return -EOPNOTSUPP; | 660 | * We only support one active interface at a time. |
661 | */ | ||
662 | if (priv->vif) | ||
663 | return -EBUSY; | ||
666 | 664 | ||
667 | switch (conf->type) { | 665 | switch (vif->type) { |
668 | case NL80211_IFTYPE_STATION: | 666 | case NL80211_IFTYPE_STATION: |
669 | priv->mode = conf->type; | ||
670 | break; | 667 | break; |
671 | default: | 668 | default: |
672 | return -EOPNOTSUPP; | 669 | return -EOPNOTSUPP; |
673 | } | 670 | } |
674 | 671 | ||
675 | priv->vif = conf->vif; | 672 | priv->vif = vif; |
676 | 673 | ||
677 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 674 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
678 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 675 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
679 | le32_to_cpu(*(__le32 *)conf->mac_addr)); | 676 | le32_to_cpu(*(__le32 *)vif->addr)); |
680 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], | 677 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], |
681 | le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 678 | le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
682 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 679 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
683 | 680 | ||
684 | return 0; | 681 | return 0; |
685 | } | 682 | } |
686 | 683 | ||
687 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, | 684 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, |
688 | struct ieee80211_if_init_conf *conf) | 685 | struct ieee80211_vif *vif) |
689 | { | 686 | { |
690 | struct rtl8180_priv *priv = dev->priv; | 687 | struct rtl8180_priv *priv = dev->priv; |
691 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
692 | priv->vif = NULL; | 688 | priv->vif = NULL; |
693 | } | 689 | } |
694 | 690 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 6af0f3f71f3a..6bb32112e65c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
@@ -92,7 +92,7 @@ struct rtl8187_priv { | |||
92 | struct rtl818x_csr *map; | 92 | struct rtl818x_csr *map; |
93 | const struct rtl818x_rf_ops *rf; | 93 | const struct rtl818x_rf_ops *rf; |
94 | struct ieee80211_vif *vif; | 94 | struct ieee80211_vif *vif; |
95 | int mode; | 95 | |
96 | /* The mutex protects the TX loopback state. | 96 | /* The mutex protects the TX loopback state. |
97 | * Any attempt to set channels concurrently locks the device. | 97 | * Any attempt to set channels concurrently locks the device. |
98 | */ | 98 | */ |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index bc5726dd5fe4..f336c63053c1 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1018,31 +1018,30 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | static int rtl8187_add_interface(struct ieee80211_hw *dev, | 1020 | static int rtl8187_add_interface(struct ieee80211_hw *dev, |
1021 | struct ieee80211_if_init_conf *conf) | 1021 | struct ieee80211_vif *vif) |
1022 | { | 1022 | { |
1023 | struct rtl8187_priv *priv = dev->priv; | 1023 | struct rtl8187_priv *priv = dev->priv; |
1024 | int i; | 1024 | int i; |
1025 | int ret = -EOPNOTSUPP; | 1025 | int ret = -EOPNOTSUPP; |
1026 | 1026 | ||
1027 | mutex_lock(&priv->conf_mutex); | 1027 | mutex_lock(&priv->conf_mutex); |
1028 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1028 | if (priv->vif) |
1029 | goto exit; | 1029 | goto exit; |
1030 | 1030 | ||
1031 | switch (conf->type) { | 1031 | switch (vif->type) { |
1032 | case NL80211_IFTYPE_STATION: | 1032 | case NL80211_IFTYPE_STATION: |
1033 | priv->mode = conf->type; | ||
1034 | break; | 1033 | break; |
1035 | default: | 1034 | default: |
1036 | goto exit; | 1035 | goto exit; |
1037 | } | 1036 | } |
1038 | 1037 | ||
1039 | ret = 0; | 1038 | ret = 0; |
1040 | priv->vif = conf->vif; | 1039 | priv->vif = vif; |
1041 | 1040 | ||
1042 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 1041 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
1043 | for (i = 0; i < ETH_ALEN; i++) | 1042 | for (i = 0; i < ETH_ALEN; i++) |
1044 | rtl818x_iowrite8(priv, &priv->map->MAC[i], | 1043 | rtl818x_iowrite8(priv, &priv->map->MAC[i], |
1045 | ((u8 *)conf->mac_addr)[i]); | 1044 | ((u8 *)vif->addr)[i]); |
1046 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1045 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
1047 | 1046 | ||
1048 | exit: | 1047 | exit: |
@@ -1051,11 +1050,10 @@ exit: | |||
1051 | } | 1050 | } |
1052 | 1051 | ||
1053 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, | 1052 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, |
1054 | struct ieee80211_if_init_conf *conf) | 1053 | struct ieee80211_vif *vif) |
1055 | { | 1054 | { |
1056 | struct rtl8187_priv *priv = dev->priv; | 1055 | struct rtl8187_priv *priv = dev->priv; |
1057 | mutex_lock(&priv->conf_mutex); | 1056 | mutex_lock(&priv->conf_mutex); |
1058 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1059 | priv->vif = NULL; | 1057 | priv->vif = NULL; |
1060 | mutex_unlock(&priv->conf_mutex); | 1058 | mutex_unlock(&priv->conf_mutex); |
1061 | } | 1059 | } |
@@ -1365,7 +1363,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1365 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | 1363 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; |
1366 | 1364 | ||
1367 | 1365 | ||
1368 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1369 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1366 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
1370 | IEEE80211_HW_SIGNAL_DBM | | 1367 | IEEE80211_HW_SIGNAL_DBM | |
1371 | IEEE80211_HW_RX_INCLUDES_FCS; | 1368 | IEEE80211_HW_RX_INCLUDES_FCS; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index ded44c045eb2..f82aa8b4bdde 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
@@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work) | |||
33 | struct rtl8187_led *led = &priv->led_tx; | 33 | struct rtl8187_led *led = &priv->led_tx; |
34 | 34 | ||
35 | /* Don't change the LED, when the device is down. */ | 35 | /* Don't change the LED, when the device is down. */ |
36 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 36 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
37 | return ; | 37 | return ; |
38 | 38 | ||
39 | /* Skip if the LED is not registered. */ | 39 | /* Skip if the LED is not registered. */ |
@@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work) | |||
71 | struct rtl8187_led *led = &priv->led_tx; | 71 | struct rtl8187_led *led = &priv->led_tx; |
72 | 72 | ||
73 | /* Don't change the LED, when the device is down. */ | 73 | /* Don't change the LED, when the device is down. */ |
74 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 74 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
75 | return ; | 75 | return ; |
76 | 76 | ||
77 | /* Skip if the LED is not registered. */ | 77 | /* Skip if the LED is not registered. */ |
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..4e373f3dbc43 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 | /* |
@@ -510,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
510 | } | 511 | } |
511 | 512 | ||
512 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, | 513 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, |
513 | struct ieee80211_if_init_conf *conf) | 514 | struct ieee80211_vif *vif) |
514 | { | 515 | { |
515 | struct wl1251 *wl = hw->priv; | 516 | struct wl1251 *wl = hw->priv; |
516 | int ret = 0; | 517 | int ret = 0; |
517 | 518 | ||
518 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 519 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
519 | conf->type, conf->mac_addr); | 520 | vif->type, vif->addr); |
520 | 521 | ||
521 | mutex_lock(&wl->mutex); | 522 | mutex_lock(&wl->mutex); |
522 | if (wl->vif) { | 523 | if (wl->vif) { |
@@ -524,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
524 | goto out; | 525 | goto out; |
525 | } | 526 | } |
526 | 527 | ||
527 | wl->vif = conf->vif; | 528 | wl->vif = vif; |
528 | 529 | ||
529 | switch (conf->type) { | 530 | switch (vif->type) { |
530 | case NL80211_IFTYPE_STATION: | 531 | case NL80211_IFTYPE_STATION: |
531 | wl->bss_type = BSS_TYPE_STA_BSS; | 532 | wl->bss_type = BSS_TYPE_STA_BSS; |
532 | break; | 533 | break; |
@@ -538,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
538 | goto out; | 539 | goto out; |
539 | } | 540 | } |
540 | 541 | ||
541 | if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { | 542 | if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { |
542 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 543 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
543 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 544 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
544 | ret = wl1251_acx_station_id(wl); | 545 | ret = wl1251_acx_station_id(wl); |
545 | if (ret < 0) | 546 | if (ret < 0) |
@@ -552,7 +553,7 @@ out: | |||
552 | } | 553 | } |
553 | 554 | ||
554 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | 555 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, |
555 | struct ieee80211_if_init_conf *conf) | 556 | struct ieee80211_vif *vif) |
556 | { | 557 | { |
557 | struct wl1251 *wl = hw->priv; | 558 | struct wl1251 *wl = hw->priv; |
558 | 559 | ||
@@ -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/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861f..d0938db043b3 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -107,10 +107,9 @@ enum { | |||
107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
109 | 109 | ||
110 | #define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) | ||
111 | |||
112 | #define WL1271_FW_NAME "wl1271-fw.bin" | 110 | #define WL1271_FW_NAME "wl1271-fw.bin" |
113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | #define WL1271_NVS_LEN 468 | ||
114 | 113 | ||
115 | /* | 114 | /* |
116 | * Enable/disable 802.11a support for WL1273 | 115 | * Enable/disable 802.11a support for WL1273 |
@@ -276,6 +275,7 @@ struct wl1271_debugfs { | |||
276 | 275 | ||
277 | struct dentry *retry_count; | 276 | struct dentry *retry_count; |
278 | struct dentry *excessive_retries; | 277 | struct dentry *excessive_retries; |
278 | struct dentry *gpio_power; | ||
279 | }; | 279 | }; |
280 | 280 | ||
281 | #define NUM_TX_QUEUES 4 | 281 | #define NUM_TX_QUEUES 4 |
@@ -322,6 +322,17 @@ struct wl1271 { | |||
322 | enum wl1271_state state; | 322 | enum wl1271_state state; |
323 | struct mutex mutex; | 323 | struct mutex mutex; |
324 | 324 | ||
325 | #define WL1271_FLAG_STA_RATES_CHANGED (0) | ||
326 | #define WL1271_FLAG_STA_ASSOCIATED (1) | ||
327 | #define WL1271_FLAG_JOINED (2) | ||
328 | #define WL1271_FLAG_GPIO_POWER (3) | ||
329 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) | ||
330 | #define WL1271_FLAG_SCANNING (5) | ||
331 | #define WL1271_FLAG_IN_ELP (6) | ||
332 | #define WL1271_FLAG_PSM (7) | ||
333 | #define WL1271_FLAG_PSM_REQUESTED (8) | ||
334 | unsigned long flags; | ||
335 | |||
325 | struct wl1271_partition_set part; | 336 | struct wl1271_partition_set part; |
326 | 337 | ||
327 | struct wl1271_chip chip; | 338 | struct wl1271_chip chip; |
@@ -359,7 +370,6 @@ struct wl1271 { | |||
359 | 370 | ||
360 | /* Frames scheduled for transmission, not handled yet */ | 371 | /* Frames scheduled for transmission, not handled yet */ |
361 | struct sk_buff_head tx_queue; | 372 | struct sk_buff_head tx_queue; |
362 | bool tx_queue_stopped; | ||
363 | 373 | ||
364 | struct work_struct tx_work; | 374 | struct work_struct tx_work; |
365 | 375 | ||
@@ -387,14 +397,15 @@ struct wl1271 { | |||
387 | u32 mbox_ptr[2]; | 397 | u32 mbox_ptr[2]; |
388 | 398 | ||
389 | /* Are we currently scanning */ | 399 | /* Are we currently scanning */ |
390 | bool scanning; | ||
391 | struct wl1271_scan scan; | 400 | struct wl1271_scan scan; |
392 | 401 | ||
393 | /* Our association ID */ | 402 | /* Our association ID */ |
394 | u16 aid; | 403 | u16 aid; |
395 | 404 | ||
396 | /* currently configured rate set */ | 405 | /* currently configured rate set */ |
406 | u32 sta_rate_set; | ||
397 | u32 basic_rate_set; | 407 | u32 basic_rate_set; |
408 | u32 rate_set; | ||
398 | 409 | ||
399 | /* The current band */ | 410 | /* The current band */ |
400 | enum ieee80211_band band; | 411 | enum ieee80211_band band; |
@@ -405,18 +416,9 @@ struct wl1271 { | |||
405 | unsigned int rx_config; | 416 | unsigned int rx_config; |
406 | unsigned int rx_filter; | 417 | unsigned int rx_filter; |
407 | 418 | ||
408 | /* is firmware in elp mode */ | ||
409 | bool elp; | ||
410 | |||
411 | struct completion *elp_compl; | 419 | struct completion *elp_compl; |
412 | struct delayed_work elp_work; | 420 | struct delayed_work elp_work; |
413 | 421 | ||
414 | /* we can be in psm, but not in elp, we have to differentiate */ | ||
415 | bool psm; | ||
416 | |||
417 | /* PSM mode requested */ | ||
418 | bool psm_requested; | ||
419 | |||
420 | /* retry counter for PSM entries */ | 422 | /* retry counter for PSM entries */ |
421 | u8 psm_entry_retry; | 423 | u8 psm_entry_retry; |
422 | 424 | ||
@@ -435,9 +437,6 @@ struct wl1271 { | |||
435 | 437 | ||
436 | struct ieee80211_vif *vif; | 438 | struct ieee80211_vif *vif; |
437 | 439 | ||
438 | /* Used for a workaround to send disconnect before rejoining */ | ||
439 | bool joined; | ||
440 | |||
441 | /* Current chipset configuration */ | 440 | /* Current chipset configuration */ |
442 | struct conf_drv_settings conf; | 441 | struct conf_drv_settings conf; |
443 | 442 | ||
@@ -455,7 +454,9 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
455 | 454 | ||
456 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 455 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 |
457 | 456 | ||
458 | /* WL1271 needs a 200ms sleep after power on */ | 457 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
458 | on in case is has been shut down shortly before */ | ||
459 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | ||
459 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 460 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
460 | 461 | ||
461 | static inline bool wl1271_11a_enabled(void) | 462 | static inline bool wl1271_11a_enabled(void) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7a..0b3434843476 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -390,6 +390,35 @@ out: | |||
390 | return ret; | 390 | return ret; |
391 | } | 391 | } |
392 | 392 | ||
393 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl) | ||
394 | { | ||
395 | struct acx_dco_itrim_params *dco; | ||
396 | struct conf_itrim_settings *c = &wl->conf.itrim; | ||
397 | int ret; | ||
398 | |||
399 | wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); | ||
400 | |||
401 | dco = kzalloc(sizeof(*dco), GFP_KERNEL); | ||
402 | if (!dco) { | ||
403 | ret = -ENOMEM; | ||
404 | goto out; | ||
405 | } | ||
406 | |||
407 | dco->enable = c->enable; | ||
408 | dco->timeout = cpu_to_le32(c->timeout); | ||
409 | |||
410 | ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, | ||
411 | dco, sizeof(*dco)); | ||
412 | if (ret < 0) { | ||
413 | wl1271_warning("failed to set dco itrim parameters: %d", ret); | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | out: | ||
418 | kfree(dco); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
393 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) | 422 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) |
394 | { | 423 | { |
395 | struct acx_beacon_filter_option *beacon_filter = NULL; | 424 | struct acx_beacon_filter_option *beacon_filter = NULL; |
@@ -758,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
758 | return 0; | 787 | return 0; |
759 | } | 788 | } |
760 | 789 | ||
761 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | 790 | int wl1271_acx_rate_policies(struct wl1271 *wl) |
762 | { | 791 | { |
763 | struct acx_rate_policy *acx; | 792 | struct acx_rate_policy *acx; |
764 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | 793 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; |
794 | int idx = 0; | ||
765 | int ret = 0; | 795 | int ret = 0; |
766 | 796 | ||
767 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 797 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | |||
773 | goto out; | 803 | goto out; |
774 | } | 804 | } |
775 | 805 | ||
776 | /* configure one default (one-size-fits-all) rate class */ | 806 | /* configure one basic rate class */ |
777 | acx->rate_class_cnt = cpu_to_le32(1); | 807 | idx = ACX_TX_BASIC_RATE; |
778 | acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); | 808 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); |
779 | acx->rate_class[0].short_retry_limit = c->short_retry_limit; | 809 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
780 | acx->rate_class[0].long_retry_limit = c->long_retry_limit; | 810 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
781 | acx->rate_class[0].aflags = c->aflags; | 811 | acx->rate_class[idx].aflags = c->aflags; |
812 | |||
813 | /* configure one AP supported rate class */ | ||
814 | idx = ACX_TX_AP_FULL_RATE; | ||
815 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); | ||
816 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | ||
817 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | ||
818 | acx->rate_class[idx].aflags = c->aflags; | ||
819 | |||
820 | acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); | ||
782 | 821 | ||
783 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 822 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
784 | if (ret < 0) { | 823 | if (ret < 0) { |
@@ -1012,59 +1051,6 @@ out: | |||
1012 | return ret; | 1051 | return ret; |
1013 | } | 1052 | } |
1014 | 1053 | ||
1015 | int wl1271_acx_smart_reflex(struct wl1271 *wl) | ||
1016 | { | ||
1017 | struct acx_smart_reflex_state *sr_state = NULL; | ||
1018 | struct acx_smart_reflex_config_params *sr_param = NULL; | ||
1019 | int i, ret; | ||
1020 | |||
1021 | wl1271_debug(DEBUG_ACX, "acx smart reflex"); | ||
1022 | |||
1023 | sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); | ||
1024 | if (!sr_param) { | ||
1025 | ret = -ENOMEM; | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { | ||
1030 | struct conf_mart_reflex_err_table *e = | ||
1031 | &(wl->conf.init.sr_err_tbl[i]); | ||
1032 | |||
1033 | sr_param->error_table[i].len = e->len; | ||
1034 | sr_param->error_table[i].upper_limit = e->upper_limit; | ||
1035 | memcpy(sr_param->error_table[i].values, e->values, e->len); | ||
1036 | } | ||
1037 | |||
1038 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, | ||
1039 | sr_param, sizeof(*sr_param)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); | ||
1046 | if (!sr_state) { | ||
1047 | ret = -ENOMEM; | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | /* enable smart reflex */ | ||
1052 | sr_state->enable = wl->conf.init.sr_enable; | ||
1053 | |||
1054 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, | ||
1055 | sr_state, sizeof(*sr_state)); | ||
1056 | if (ret < 0) { | ||
1057 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | |||
1061 | out: | ||
1062 | kfree(sr_state); | ||
1063 | kfree(sr_param); | ||
1064 | return ret; | ||
1065 | |||
1066 | } | ||
1067 | |||
1068 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | 1054 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) |
1069 | { | 1055 | { |
1070 | struct wl1271_acx_bet_enable *acx = NULL; | 1056 | struct wl1271_acx_bet_enable *acx = NULL; |
@@ -1132,3 +1118,31 @@ out: | |||
1132 | kfree(acx); | 1118 | kfree(acx); |
1133 | return ret; | 1119 | return ret; |
1134 | } | 1120 | } |
1121 | |||
1122 | int wl1271_acx_pm_config(struct wl1271 *wl) | ||
1123 | { | ||
1124 | struct wl1271_acx_pm_config *acx = NULL; | ||
1125 | struct conf_pm_config_settings *c = &wl->conf.pm_config; | ||
1126 | int ret = 0; | ||
1127 | |||
1128 | wl1271_debug(DEBUG_ACX, "acx pm config"); | ||
1129 | |||
1130 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1131 | if (!acx) { | ||
1132 | ret = -ENOMEM; | ||
1133 | goto out; | ||
1134 | } | ||
1135 | |||
1136 | acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); | ||
1137 | acx->host_fast_wakeup_support = c->host_fast_wakeup_support; | ||
1138 | |||
1139 | ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); | ||
1140 | if (ret < 0) { | ||
1141 | wl1271_warning("acx pm config failed: %d", ret); | ||
1142 | goto out; | ||
1143 | } | ||
1144 | |||
1145 | out: | ||
1146 | kfree(acx); | ||
1147 | return ret; | ||
1148 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 2ce0a8128542..1bb63af64f0e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -415,23 +415,12 @@ struct acx_bt_wlan_coex { | |||
415 | u8 pad[3]; | 415 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
417 | 417 | ||
418 | struct acx_smart_reflex_state { | 418 | struct acx_dco_itrim_params { |
419 | struct acx_header header; | 419 | struct acx_header header; |
420 | 420 | ||
421 | u8 enable; | 421 | u8 enable; |
422 | u8 padding[3]; | 422 | u8 padding[3]; |
423 | } __attribute__ ((packed)); | 423 | __le32 timeout; |
424 | |||
425 | struct smart_reflex_err_table { | ||
426 | u8 len; | ||
427 | s8 upper_limit; | ||
428 | s8 values[14]; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct acx_smart_reflex_config_params { | ||
432 | struct acx_header header; | ||
433 | |||
434 | struct smart_reflex_err_table error_table[3]; | ||
435 | } __attribute__ ((packed)); | 424 | } __attribute__ ((packed)); |
436 | 425 | ||
437 | #define PTA_ANTENNA_TYPE_DEF (0) | 426 | #define PTA_ANTENNA_TYPE_DEF (0) |
@@ -837,6 +826,9 @@ struct acx_rate_class { | |||
837 | u8 reserved; | 826 | u8 reserved; |
838 | }; | 827 | }; |
839 | 828 | ||
829 | #define ACX_TX_BASIC_RATE 0 | ||
830 | #define ACX_TX_AP_FULL_RATE 1 | ||
831 | #define ACX_TX_RATE_POLICY_CNT 2 | ||
840 | struct acx_rate_policy { | 832 | struct acx_rate_policy { |
841 | struct acx_header header; | 833 | struct acx_header header; |
842 | 834 | ||
@@ -877,8 +869,8 @@ struct acx_tx_config_options { | |||
877 | __le16 tx_compl_threshold; /* number of packets */ | 869 | __le16 tx_compl_threshold; /* number of packets */ |
878 | } __attribute__ ((packed)); | 870 | } __attribute__ ((packed)); |
879 | 871 | ||
880 | #define ACX_RX_MEM_BLOCKS 64 | 872 | #define ACX_RX_MEM_BLOCKS 70 |
881 | #define ACX_TX_MIN_MEM_BLOCKS 64 | 873 | #define ACX_TX_MIN_MEM_BLOCKS 40 |
882 | #define ACX_TX_DESCRIPTORS 32 | 874 | #define ACX_TX_DESCRIPTORS 32 |
883 | #define ACX_NUM_SSID_PROFILES 1 | 875 | #define ACX_NUM_SSID_PROFILES 1 |
884 | 876 | ||
@@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter { | |||
969 | used. */ | 961 | used. */ |
970 | } __attribute__((packed)); | 962 | } __attribute__((packed)); |
971 | 963 | ||
964 | struct wl1271_acx_pm_config { | ||
965 | struct acx_header header; | ||
966 | |||
967 | __le32 host_clk_settling_time; | ||
968 | u8 host_fast_wakeup_support; | ||
969 | u8 padding[3]; | ||
970 | } __attribute__ ((packed)); | ||
972 | 971 | ||
973 | enum { | 972 | enum { |
974 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 973 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
@@ -1027,13 +1026,13 @@ enum { | |||
1027 | ACX_HT_BSS_OPERATION = 0x0058, | 1026 | ACX_HT_BSS_OPERATION = 0x0058, |
1028 | ACX_COEX_ACTIVITY = 0x0059, | 1027 | ACX_COEX_ACTIVITY = 0x0059, |
1029 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | 1028 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, |
1030 | ACX_SET_SMART_REFLEX_STATE = 0x005B, | 1029 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1031 | ACX_SET_SMART_REFLEX_PARAMS = 0x005F, | ||
1032 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1030 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1033 | DOT11_CUR_TX_PWR = 0x100D, | 1031 | DOT11_CUR_TX_PWR = 0x100D, |
1034 | DOT11_RX_DOT11_MODE = 0x1012, | 1032 | DOT11_RX_DOT11_MODE = 0x1012, |
1035 | DOT11_RTS_THRESHOLD = 0x1013, | 1033 | DOT11_RTS_THRESHOLD = 0x1013, |
1036 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | 1034 | DOT11_GROUP_ADDRESS_TBL = 0x1014, |
1035 | ACX_PM_CONFIG = 0x1016, | ||
1037 | 1036 | ||
1038 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, | 1037 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, |
1039 | 1038 | ||
@@ -1056,6 +1055,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | |||
1056 | void *mc_list, u32 mc_list_len); | 1055 | void *mc_list, u32 mc_list_len); |
1057 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1056 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1058 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1057 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); |
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | ||
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); |
@@ -1069,7 +1069,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | |||
1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1070 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1072 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); |
1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); |
1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); |
1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
@@ -1081,5 +1081,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl); | |||
1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1083 | u8 version); | 1083 | u8 version); |
1084 | int wl1271_acx_pm_config(struct wl1271 *wl); | ||
1084 | 1085 | ||
1085 | #endif /* __WL1271_ACX_H__ */ | 1086 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca3..e803b876f3f0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
225 | if (nvs == NULL) | 225 | if (nvs == NULL) |
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | if (wl->nvs_len < WL1271_NVS_LEN) | ||
229 | return -EINVAL; | ||
230 | |||
228 | nvs_ptr = nvs; | 231 | nvs_ptr = nvs; |
229 | 232 | ||
230 | nvs_len = wl->nvs_len; | 233 | /* only the first part of the NVS needs to be uploaded */ |
234 | nvs_len = WL1271_NVS_LEN; | ||
235 | |||
236 | /* FIXME: read init settings from the remaining part of the NVS */ | ||
231 | 237 | ||
232 | /* Update the device MAC address into the nvs */ | 238 | /* Update the device MAC address into the nvs */ |
233 | nvs[11] = wl->mac_addr[0]; | 239 | nvs[11] = wl->mac_addr[0]; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index c3385b3d246c..a74259bb596b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -209,6 +209,26 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; | 209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; |
210 | gen_parms->settings = g->settings; | 210 | gen_parms->settings = g->settings; |
211 | 211 | ||
212 | gen_parms->sr_state = g->sr_state; | ||
213 | |||
214 | memcpy(gen_parms->srf1, | ||
215 | g->srf1, | ||
216 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
217 | memcpy(gen_parms->srf2, | ||
218 | g->srf2, | ||
219 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
220 | memcpy(gen_parms->srf3, | ||
221 | g->srf3, | ||
222 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
223 | memcpy(gen_parms->sr_debug_table, | ||
224 | g->sr_debug_table, | ||
225 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
226 | |||
227 | gen_parms->sr_sen_n_p = g->sr_sen_n_p; | ||
228 | gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; | ||
229 | gen_parms->sr_sen_nrn = g->sr_sen_nrn; | ||
230 | gen_parms->sr_sen_prn = g->sr_sen_prn; | ||
231 | |||
212 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 232 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
213 | if (ret < 0) | 233 | if (ret < 0) |
214 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 234 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -253,6 +273,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
253 | CONF_NUMBER_OF_RATE_GROUPS); | 273 | CONF_NUMBER_OF_RATE_GROUPS); |
254 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, | 274 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, |
255 | CONF_NUMBER_OF_RATE_GROUPS); | 275 | CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, | ||
277 | CONF_NUMBER_OF_RATE_GROUPS); | ||
256 | 278 | ||
257 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, | 279 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, |
258 | CONF_NUMBER_OF_CHANNELS_2_4); | 280 | CONF_NUMBER_OF_CHANNELS_2_4); |
@@ -263,6 +285,11 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
263 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); | 285 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); |
264 | 286 | ||
265 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | 287 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; |
288 | radio_parms->degraded_low_to_normal_threshold = | ||
289 | r->degraded_low_to_normal_threshold; | ||
290 | radio_parms->degraded_normal_to_high_threshold = | ||
291 | r->degraded_normal_to_high_threshold; | ||
292 | |||
266 | 293 | ||
267 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | 294 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) |
268 | radio_parms->tx_ref_pd_voltage_5[i] = | 295 | radio_parms->tx_ref_pd_voltage_5[i] = |
@@ -275,6 +302,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
275 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | 302 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_degraded_5, | 303 | memcpy(radio_parms->tx_rate_limits_degraded_5, |
277 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | 304 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); |
305 | memcpy(radio_parms->tx_rate_limits_extreme_5, | ||
306 | r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
278 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | 307 | memcpy(radio_parms->tx_channel_limits_ofdm_5, |
279 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | 308 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); |
280 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | 309 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, |
@@ -283,6 +312,10 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
283 | CONF_NUMBER_OF_RATE_GROUPS); | 312 | CONF_NUMBER_OF_RATE_GROUPS); |
284 | memcpy(radio_parms->rx_fem_insertion_loss_5, | 313 | memcpy(radio_parms->rx_fem_insertion_loss_5, |
285 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | 314 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); |
315 | radio_parms->degraded_low_to_normal_threshold_5 = | ||
316 | r->degraded_low_to_normal_threshold_5; | ||
317 | radio_parms->degraded_normal_to_high_threshold_5 = | ||
318 | r->degraded_normal_to_high_threshold_5; | ||
286 | 319 | ||
287 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 320 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
288 | radio_parms, sizeof(*radio_parms)); | 321 | radio_parms, sizeof(*radio_parms)); |
@@ -311,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
311 | do_cal = false; | 344 | do_cal = false; |
312 | } | 345 | } |
313 | 346 | ||
314 | /* FIXME: This is a workaround, because with the current stack, we | ||
315 | * cannot know when we have disassociated. So, if we have already | ||
316 | * joined, we disconnect before joining again. */ | ||
317 | if (wl->joined) { | ||
318 | ret = wl1271_cmd_disconnect(wl); | ||
319 | if (ret < 0) { | ||
320 | wl1271_error("failed to disconnect before rejoining"); | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | wl->joined = false; | ||
325 | } | ||
326 | |||
327 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 347 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
328 | if (!join) { | 348 | if (!join) { |
329 | ret = -ENOMEM; | 349 | ret = -ENOMEM; |
@@ -388,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
388 | goto out_free; | 408 | goto out_free; |
389 | } | 409 | } |
390 | 410 | ||
391 | wl->joined = true; | ||
392 | |||
393 | /* | 411 | /* |
394 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 412 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to |
395 | * simplify locking we just sleep instead, for now | 413 | * simplify locking we just sleep instead, for now |
@@ -487,7 +505,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
487 | return 0; | 505 | return 0; |
488 | } | 506 | } |
489 | 507 | ||
490 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | 508 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) |
491 | { | 509 | { |
492 | struct cmd_enabledisable_path *cmd; | 510 | struct cmd_enabledisable_path *cmd; |
493 | int ret; | 511 | int ret; |
@@ -501,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
501 | goto out; | 519 | goto out; |
502 | } | 520 | } |
503 | 521 | ||
504 | cmd->channel = channel; | 522 | /* the channel here is only used for calibration, so hardcoded to 1 */ |
523 | cmd->channel = 1; | ||
505 | 524 | ||
506 | if (enable) { | 525 | if (enable) { |
507 | cmd_rx = CMD_ENABLE_RX; | 526 | cmd_rx = CMD_ENABLE_RX; |
@@ -514,22 +533,22 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
514 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); | 533 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); |
515 | if (ret < 0) { | 534 | if (ret < 0) { |
516 | wl1271_error("rx %s cmd for channel %d failed", | 535 | wl1271_error("rx %s cmd for channel %d failed", |
517 | enable ? "start" : "stop", channel); | 536 | enable ? "start" : "stop", cmd->channel); |
518 | goto out; | 537 | goto out; |
519 | } | 538 | } |
520 | 539 | ||
521 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 540 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
522 | enable ? "start" : "stop", channel); | 541 | enable ? "start" : "stop", cmd->channel); |
523 | 542 | ||
524 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); | 543 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); |
525 | if (ret < 0) { | 544 | if (ret < 0) { |
526 | wl1271_error("tx %s cmd for channel %d failed", | 545 | wl1271_error("tx %s cmd for channel %d failed", |
527 | enable ? "start" : "stop", channel); | 546 | enable ? "start" : "stop", cmd->channel); |
528 | return ret; | 547 | return ret; |
529 | } | 548 | } |
530 | 549 | ||
531 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 550 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
532 | enable ? "start" : "stop", channel); | 551 | enable ? "start" : "stop", cmd->channel); |
533 | 552 | ||
534 | out: | 553 | out: |
535 | kfree(cmd); | 554 | kfree(cmd); |
@@ -636,7 +655,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
636 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | 655 | channels = wl->hw->wiphy->bands[ieee_band]->channels; |
637 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | 656 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; |
638 | 657 | ||
639 | if (wl->scanning) | 658 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) |
640 | return -EINVAL; | 659 | return -EINVAL; |
641 | 660 | ||
642 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 661 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
@@ -711,7 +730,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
711 | 730 | ||
712 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 731 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); |
713 | 732 | ||
714 | wl->scanning = true; | 733 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); |
715 | if (wl1271_11a_enabled()) { | 734 | if (wl1271_11a_enabled()) { |
716 | wl->scan.state = band; | 735 | wl->scan.state = band; |
717 | if (band == WL1271_SCAN_BAND_DUAL) { | 736 | if (band == WL1271_SCAN_BAND_DUAL) { |
@@ -729,7 +748,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
729 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | 748 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); |
730 | if (ret < 0) { | 749 | if (ret < 0) { |
731 | wl1271_error("SCAN failed"); | 750 | wl1271_error("SCAN failed"); |
732 | wl->scanning = false; | 751 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
733 | goto out; | 752 | goto out; |
734 | } | 753 | } |
735 | 754 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index b4fa4acb9229..09fe91297acf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -37,7 +37,7 @@ int wl1271_cmd_join(struct wl1271 *wl); | |||
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); | 40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
@@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd { | |||
437 | u8 tx_bip_fem_autodetect; | 437 | u8 tx_bip_fem_autodetect; |
438 | u8 tx_bip_fem_manufacturer; | 438 | u8 tx_bip_fem_manufacturer; |
439 | u8 settings; | 439 | u8 settings; |
440 | |||
441 | u8 sr_state; | ||
442 | |||
443 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
444 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
445 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
446 | |||
447 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
448 | |||
449 | u8 sr_sen_n_p; | ||
450 | u8 sr_sen_n_p_gain; | ||
451 | u8 sr_sen_nrn; | ||
452 | u8 sr_sen_prn; | ||
453 | |||
454 | u8 padding[3]; | ||
440 | } __attribute__ ((packed)); | 455 | } __attribute__ ((packed)); |
441 | 456 | ||
442 | struct wl1271_radio_parms_cmd { | 457 | struct wl1271_radio_parms_cmd { |
@@ -458,11 +473,12 @@ struct wl1271_radio_parms_cmd { | |||
458 | /* Dynamic radio parameters */ | 473 | /* Dynamic radio parameters */ |
459 | /* 2.4GHz */ | 474 | /* 2.4GHz */ |
460 | __le16 tx_ref_pd_voltage; | 475 | __le16 tx_ref_pd_voltage; |
461 | s8 tx_ref_power; | 476 | u8 tx_ref_power; |
462 | s8 tx_offset_db; | 477 | s8 tx_offset_db; |
463 | 478 | ||
464 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 479 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
465 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 480 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
481 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
466 | 482 | ||
467 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 483 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
468 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 484 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -471,15 +487,19 @@ struct wl1271_radio_parms_cmd { | |||
471 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 487 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
472 | u8 rx_fem_insertion_loss; | 488 | u8 rx_fem_insertion_loss; |
473 | 489 | ||
474 | u8 padding2; | 490 | u8 degraded_low_to_normal_threshold; |
491 | u8 degraded_normal_to_high_threshold; | ||
492 | |||
493 | u8 padding1; /* our own padding, not in ref driver */ | ||
475 | 494 | ||
476 | /* 5GHz */ | 495 | /* 5GHz */ |
477 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 496 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
478 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 497 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
479 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 498 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
480 | 499 | ||
481 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 500 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
482 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 501 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
502 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
483 | 503 | ||
484 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 504 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
485 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 505 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -488,7 +508,10 @@ struct wl1271_radio_parms_cmd { | |||
488 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 508 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
489 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 509 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
490 | 510 | ||
491 | u8 padding3[2]; | 511 | u8 degraded_low_to_normal_threshold_5; |
512 | u8 degraded_normal_to_high_threshold_5; | ||
513 | |||
514 | u8 padding2[2]; | ||
492 | } __attribute__ ((packed)); | 515 | } __attribute__ ((packed)); |
493 | 516 | ||
494 | struct wl1271_cmd_cal_channel_tune { | 517 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede265..1993d63c214e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -258,7 +258,8 @@ struct conf_rx_settings { | |||
258 | #define CONF_TX_MAX_RATE_CLASSES 8 | 258 | #define CONF_TX_MAX_RATE_CLASSES 8 |
259 | 259 | ||
260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 | 260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 |
261 | #define CONF_TX_RATE_MASK_ALL 0x1eff | 261 | #define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ |
262 | CONF_HW_BIT_RATE_2MBPS) | ||
262 | #define CONF_TX_RATE_RETRY_LIMIT 10 | 263 | #define CONF_TX_RATE_RETRY_LIMIT 10 |
263 | 264 | ||
264 | struct conf_tx_rate_class { | 265 | struct conf_tx_rate_class { |
@@ -722,31 +723,6 @@ struct conf_conn_settings { | |||
722 | u8 psm_entry_retries; | 723 | u8 psm_entry_retries; |
723 | }; | 724 | }; |
724 | 725 | ||
725 | #define CONF_SR_ERR_TBL_MAX_VALUES 14 | ||
726 | |||
727 | struct conf_mart_reflex_err_table { | ||
728 | /* | ||
729 | * Length of the error table values table. | ||
730 | * | ||
731 | * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES | ||
732 | */ | ||
733 | u8 len; | ||
734 | |||
735 | /* | ||
736 | * Smart Reflex error table upper limit. | ||
737 | * | ||
738 | * Range: s8 | ||
739 | */ | ||
740 | s8 upper_limit; | ||
741 | |||
742 | /* | ||
743 | * Smart Reflex error table values. | ||
744 | * | ||
745 | * Range: s8 | ||
746 | */ | ||
747 | s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; | ||
748 | }; | ||
749 | |||
750 | enum { | 726 | enum { |
751 | CONF_REF_CLK_19_2_E, | 727 | CONF_REF_CLK_19_2_E, |
752 | CONF_REF_CLK_26_E, | 728 | CONF_REF_CLK_26_E, |
@@ -759,6 +735,9 @@ enum single_dual_band_enum { | |||
759 | CONF_DUAL_BAND | 735 | CONF_DUAL_BAND |
760 | }; | 736 | }; |
761 | 737 | ||
738 | |||
739 | #define CONF_MAX_SMART_REFLEX_PARAMS 16 | ||
740 | |||
762 | struct conf_general_parms { | 741 | struct conf_general_parms { |
763 | /* | 742 | /* |
764 | * RF Reference Clock type / speed | 743 | * RF Reference Clock type / speed |
@@ -815,6 +794,20 @@ struct conf_general_parms { | |||
815 | * Range: Unknown | 794 | * Range: Unknown |
816 | */ | 795 | */ |
817 | u8 settings; | 796 | u8 settings; |
797 | |||
798 | /* Smart reflex settings */ | ||
799 | u8 sr_state; | ||
800 | |||
801 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
802 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
803 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
804 | |||
805 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
806 | |||
807 | u8 sr_sen_n_p; | ||
808 | u8 sr_sen_n_p_gain; | ||
809 | u8 sr_sen_nrn; | ||
810 | u8 sr_sen_prn; | ||
818 | }; | 811 | }; |
819 | 812 | ||
820 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | 813 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 |
@@ -847,12 +840,13 @@ struct conf_radio_parms { | |||
847 | * | 840 | * |
848 | * Range: unknown | 841 | * Range: unknown |
849 | */ | 842 | */ |
850 | s16 tx_ref_pd_voltage; | 843 | u16 tx_ref_pd_voltage; |
851 | s8 tx_ref_power; | 844 | u8 tx_ref_power; |
852 | s8 tx_offset_db; | 845 | s8 tx_offset_db; |
853 | 846 | ||
854 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 847 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
855 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 848 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
849 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
856 | 850 | ||
857 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 851 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
858 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 852 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -861,17 +855,22 @@ struct conf_radio_parms { | |||
861 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 855 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
862 | u8 rx_fem_insertion_loss; | 856 | u8 rx_fem_insertion_loss; |
863 | 857 | ||
858 | u8 degraded_low_to_normal_threshold; | ||
859 | u8 degraded_normal_to_high_threshold; | ||
860 | |||
861 | |||
864 | /* | 862 | /* |
865 | * Dynamic radio parameters for 5GHz | 863 | * Dynamic radio parameters for 5GHz |
866 | * | 864 | * |
867 | * Range: unknown | 865 | * Range: unknown |
868 | */ | 866 | */ |
869 | s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 867 | u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
870 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 868 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
871 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 869 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
872 | 870 | ||
873 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 871 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
874 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 872 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
873 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
875 | 874 | ||
876 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 875 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
877 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 876 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -879,33 +878,46 @@ struct conf_radio_parms { | |||
879 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | 878 | /* FIXME: this is inconsistent with the types for 2.4GHz */ |
880 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 879 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
881 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 880 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
882 | }; | ||
883 | 881 | ||
884 | #define CONF_SR_ERR_TBL_COUNT 3 | 882 | u8 degraded_low_to_normal_threshold_5; |
883 | u8 degraded_normal_to_high_threshold_5; | ||
884 | }; | ||
885 | 885 | ||
886 | struct conf_init_settings { | 886 | struct conf_init_settings { |
887 | /* | 887 | /* |
888 | * Configure Smart Reflex error table values. | 888 | * Configure general parameters. |
889 | */ | 889 | */ |
890 | struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; | 890 | struct conf_general_parms genparam; |
891 | 891 | ||
892 | /* | 892 | /* |
893 | * Smart Reflex enable flag. | 893 | * Configure radio parameters. |
894 | * | ||
895 | * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled | ||
896 | */ | 894 | */ |
897 | u8 sr_enable; | 895 | struct conf_radio_parms radioparam; |
898 | 896 | ||
897 | }; | ||
898 | |||
899 | struct conf_itrim_settings { | ||
900 | /* enable dco itrim */ | ||
901 | u8 enable; | ||
902 | |||
903 | /* moderation timeout in microsecs from the last TX */ | ||
904 | u32 timeout; | ||
905 | }; | ||
906 | |||
907 | struct conf_pm_config_settings { | ||
899 | /* | 908 | /* |
900 | * Configure general parameters. | 909 | * Host clock settling time |
910 | * | ||
911 | * Range: 0 - 30000 us | ||
901 | */ | 912 | */ |
902 | struct conf_general_parms genparam; | 913 | u32 host_clk_settling_time; |
903 | 914 | ||
904 | /* | 915 | /* |
905 | * Configure radio parameters. | 916 | * Host fast wakeup support |
917 | * | ||
918 | * Range: true, false | ||
906 | */ | 919 | */ |
907 | struct conf_radio_parms radioparam; | 920 | bool host_fast_wakeup_support; |
908 | |||
909 | }; | 921 | }; |
910 | 922 | ||
911 | struct conf_drv_settings { | 923 | struct conf_drv_settings { |
@@ -914,6 +926,8 @@ struct conf_drv_settings { | |||
914 | struct conf_tx_settings tx; | 926 | struct conf_tx_settings tx; |
915 | struct conf_conn_settings conn; | 927 | struct conf_conn_settings conn; |
916 | struct conf_init_settings init; | 928 | struct conf_init_settings init; |
929 | struct conf_itrim_settings itrim; | ||
930 | struct conf_pm_config_settings pm_config; | ||
917 | }; | 931 | }; |
918 | 932 | ||
919 | #endif | 933 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index c1805e5f8964..8d7588ca68fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1271_open_file_generic, | 237 | .open = wl1271_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1271 *wl = file->private_data; | ||
244 | bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
245 | |||
246 | int res; | ||
247 | char buf[10]; | ||
248 | |||
249 | res = scnprintf(buf, sizeof(buf), "%d\n", state); | ||
250 | |||
251 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
252 | } | ||
253 | |||
254 | static ssize_t gpio_power_write(struct file *file, | ||
255 | const char __user *user_buf, | ||
256 | size_t count, loff_t *ppos) | ||
257 | { | ||
258 | struct wl1271 *wl = file->private_data; | ||
259 | char buf[10]; | ||
260 | size_t len; | ||
261 | unsigned long value; | ||
262 | int ret; | ||
263 | |||
264 | mutex_lock(&wl->mutex); | ||
265 | |||
266 | len = min(count, sizeof(buf) - 1); | ||
267 | if (copy_from_user(buf, user_buf, len)) { | ||
268 | ret = -EFAULT; | ||
269 | goto out; | ||
270 | } | ||
271 | buf[len] = '\0'; | ||
272 | |||
273 | ret = strict_strtoul(buf, 0, &value); | ||
274 | if (ret < 0) { | ||
275 | wl1271_warning("illegal value in gpio_power"); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | if (value) { | ||
280 | wl->set_power(true); | ||
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
282 | } else { | ||
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | |||
287 | out: | ||
288 | mutex_unlock(&wl->mutex); | ||
289 | return count; | ||
290 | } | ||
291 | |||
292 | static const struct file_operations gpio_power_ops = { | ||
293 | .read = gpio_power_read, | ||
294 | .write = gpio_power_write, | ||
295 | .open = wl1271_open_file_generic | ||
296 | }; | ||
297 | |||
240 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) | 298 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) |
241 | { | 299 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 300 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -333,6 +391,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl) | |||
333 | DEBUGFS_DEL(tx_queue_len); | 391 | DEBUGFS_DEL(tx_queue_len); |
334 | DEBUGFS_DEL(retry_count); | 392 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 393 | DEBUGFS_DEL(excessive_retries); |
394 | |||
395 | DEBUGFS_DEL(gpio_power); | ||
336 | } | 396 | } |
337 | 397 | ||
338 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 398 | static int wl1271_debugfs_add_files(struct wl1271 *wl) |
@@ -434,6 +494,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 494 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 495 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 496 | ||
497 | DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); | ||
498 | |||
437 | out: | 499 | out: |
438 | if (ret < 0) | 500 | if (ret < 0) |
439 | wl1271_debugfs_delete_files(wl); | 501 | wl1271_debugfs_delete_files(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index d13fdd99c85c..0a145afc9905 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -35,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 36 | mbox->scheduled_scan_status); |
37 | 37 | ||
38 | if (wl->scanning) { | 38 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
41 | NULL, size); | 41 | NULL, size); |
@@ -43,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
43 | * to the wl1271_cmd_scan function that we are not | 43 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 44 | * scanning as it checks that. |
45 | */ | 45 | */ |
46 | wl->scanning = false; | 46 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
48 | wl->scan.active, | 48 | wl->scan.active, |
49 | wl->scan.high_prio, | 49 | wl->scan.high_prio, |
@@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
62 | mutex_unlock(&wl->mutex); | 62 | mutex_unlock(&wl->mutex); |
63 | ieee80211_scan_completed(wl->hw, false); | 63 | ieee80211_scan_completed(wl->hw, false); |
64 | mutex_lock(&wl->mutex); | 64 | mutex_lock(&wl->mutex); |
65 | wl->scanning = false; | 65 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | return 0; | 68 | return 0; |
@@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
78 | 78 | ||
79 | switch (mbox->ps_status) { | 79 | switch (mbox->ps_status) { |
80 | case EVENT_ENTER_POWER_SAVE_FAIL: | 80 | case EVENT_ENTER_POWER_SAVE_FAIL: |
81 | if (!wl->psm) { | 81 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
82 | wl->psm_entry_retry = 0; | 82 | wl->psm_entry_retry = 0; |
83 | break; | 83 | break; |
84 | } | 84 | } |
@@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
89 | } else { | 89 | } else { |
90 | wl1271_error("PSM entry failed, giving up.\n"); | 90 | wl1271_error("PSM entry failed, giving up.\n"); |
91 | wl->psm_entry_retry = 0; | 91 | wl->psm_entry_retry = 0; |
92 | *beacon_loss = true; | ||
93 | } | 92 | } |
94 | break; | 93 | break; |
95 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 94 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -136,7 +135,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
136 | * filtering) is enabled. Without PSM, the stack will receive all | 135 | * filtering) is enabled. Without PSM, the stack will receive all |
137 | * beacons and can detect beacon loss by itself. | 136 | * beacons and can detect beacon loss by itself. |
138 | */ | 137 | */ |
139 | if (vector & BSS_LOSE_EVENT_ID && wl->psm) { | 138 | if (vector & BSS_LOSE_EVENT_ID && |
139 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | 140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
141 | 141 | ||
142 | /* indicate to the stack, that beacons have been lost */ | 142 | /* indicate to the stack, that beacons have been lost */ |
@@ -150,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
152 | 152 | ||
153 | if (beacon_loss) { | 153 | if (wl->vif && beacon_loss) { |
154 | /* Obviously, it's dangerous to release the mutex while | 154 | /* Obviously, it's dangerous to release the mutex while |
155 | we are holding many of the variables in the wl struct. | 155 | we are holding many of the variables in the wl struct. |
156 | That's why it's done last in the function, and care must | 156 | That's why it's done last in the function, and care must |
@@ -184,7 +184,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl) | |||
184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
185 | } | 185 | } |
186 | 186 | ||
187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | 187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) |
188 | { | 188 | { |
189 | struct event_mailbox mbox; | 189 | struct event_mailbox mbox; |
190 | int ret; | 190 | int ret; |
@@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | |||
204 | return ret; | 204 | return ret; |
205 | 205 | ||
206 | /* then we let the firmware know it can go on...*/ | 206 | /* then we let the firmware know it can go on...*/ |
207 | if (do_ack) | 207 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
208 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, | ||
209 | INTR_TRIG_EVENT_ACK); | ||
210 | 208 | ||
211 | return 0; | 209 | return 0; |
212 | } | 210 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a8..278f9206aa56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -112,6 +112,6 @@ struct event_mailbox { | |||
112 | 112 | ||
113 | int wl1271_event_unmask(struct wl1271 *wl); | 113 | int wl1271_event_unmask(struct wl1271 *wl); |
114 | void wl1271_event_mbox_config(struct wl1271 *wl); | 114 | void wl1271_event_mbox_config(struct wl1271 *wl); |
115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); | 115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
116 | 116 | ||
117 | #endif | 117 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 11249b436cf1..c9848eecb767 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
229 | if (ret < 0) | 229 | if (ret < 0) |
230 | goto out_free_memmap; | 230 | goto out_free_memmap; |
231 | 231 | ||
232 | ret = wl1271_acx_dco_itrim_params(wl); | ||
233 | if (ret < 0) | ||
234 | goto out_free_memmap; | ||
235 | |||
232 | /* Initialize connection monitoring thresholds */ | 236 | /* Initialize connection monitoring thresholds */ |
233 | ret = wl1271_acx_conn_monit_params(wl); | 237 | ret = wl1271_acx_conn_monit_params(wl); |
234 | if (ret < 0) | 238 | if (ret < 0) |
@@ -280,12 +284,12 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
280 | goto out_free_memmap; | 284 | goto out_free_memmap; |
281 | 285 | ||
282 | /* Configure TX rate classes */ | 286 | /* Configure TX rate classes */ |
283 | ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); | 287 | ret = wl1271_acx_rate_policies(wl); |
284 | if (ret < 0) | 288 | if (ret < 0) |
285 | goto out_free_memmap; | 289 | goto out_free_memmap; |
286 | 290 | ||
287 | /* Enable data path */ | 291 | /* Enable data path */ |
288 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 292 | ret = wl1271_cmd_data_path(wl, 1); |
289 | if (ret < 0) | 293 | if (ret < 0) |
290 | goto out_free_memmap; | 294 | goto out_free_memmap; |
291 | 295 | ||
@@ -299,8 +303,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
299 | if (ret < 0) | 303 | if (ret < 0) |
300 | goto out_free_memmap; | 304 | goto out_free_memmap; |
301 | 305 | ||
302 | /* Configure smart reflex */ | 306 | /* configure PM */ |
303 | ret = wl1271_acx_smart_reflex(wl); | 307 | ret = wl1271_acx_pm_config(wl); |
304 | if (ret < 0) | 308 | if (ret < 0) |
305 | goto out_free_memmap; | 309 | goto out_free_memmap; |
306 | 310 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42fe..e4867b895c43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include "wl1271_cmd.h" | 47 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 48 | #include "wl1271_boot.h" |
49 | 49 | ||
50 | #define WL1271_BOOT_RETRIES 3 | ||
51 | |||
50 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
51 | .sg = { | 53 | .sg = { |
52 | .per_threshold = 7500, | 54 | .per_threshold = 7500, |
@@ -67,16 +69,17 @@ static struct conf_drv_settings default_conf = { | |||
67 | .ps_poll_timeout = 15, | 69 | .ps_poll_timeout = 15, |
68 | .upsd_timeout = 15, | 70 | .upsd_timeout = 15, |
69 | .rts_threshold = 2347, | 71 | .rts_threshold = 2347, |
70 | .rx_cca_threshold = 0xFFEF, | 72 | .rx_cca_threshold = 0, |
71 | .irq_blk_threshold = 0, | 73 | .irq_blk_threshold = 0xFFFF, |
72 | .irq_pkt_threshold = USHORT_MAX, | 74 | .irq_pkt_threshold = 0, |
73 | .irq_timeout = 5, | 75 | .irq_timeout = 600, |
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | 76 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
75 | }, | 77 | }, |
76 | .tx = { | 78 | .tx = { |
77 | .tx_energy_detection = 0, | 79 | .tx_energy_detection = 0, |
78 | .rc_conf = { | 80 | .rc_conf = { |
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | 81 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | |
82 | CONF_HW_BIT_RATE_2MBPS, | ||
80 | .short_retry_limit = 10, | 83 | .short_retry_limit = 10, |
81 | .long_retry_limit = 10, | 84 | .long_retry_limit = 10, |
82 | .aflags = 0 | 85 | .aflags = 0 |
@@ -172,8 +175,8 @@ static struct conf_drv_settings default_conf = { | |||
172 | } | 175 | } |
173 | }, | 176 | }, |
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 177 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
175 | .tx_compl_timeout = 5, | 178 | .tx_compl_timeout = 700, |
176 | .tx_compl_threshold = 5 | 179 | .tx_compl_threshold = 4 |
177 | }, | 180 | }, |
178 | .conn = { | 181 | .conn = { |
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 182 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -186,12 +189,12 @@ static struct conf_drv_settings default_conf = { | |||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 189 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
187 | } | 190 | } |
188 | }, | 191 | }, |
189 | .synch_fail_thold = 5, | 192 | .synch_fail_thold = 10, |
190 | .bss_lose_timeout = 100, | 193 | .bss_lose_timeout = 100, |
191 | .beacon_rx_timeout = 10000, | 194 | .beacon_rx_timeout = 10000, |
192 | .broadcast_timeout = 20000, | 195 | .broadcast_timeout = 20000, |
193 | .rx_broadcast_in_ps = 1, | 196 | .rx_broadcast_in_ps = 1, |
194 | .ps_poll_threshold = 4, | 197 | .ps_poll_threshold = 20, |
195 | .sig_trigger_count = 2, | 198 | .sig_trigger_count = 2, |
196 | .sig_trigger = { | 199 | .sig_trigger = { |
197 | [0] = { | 200 | [0] = { |
@@ -226,46 +229,35 @@ static struct conf_drv_settings default_conf = { | |||
226 | .psm_entry_retries = 3 | 229 | .psm_entry_retries = 3 |
227 | }, | 230 | }, |
228 | .init = { | 231 | .init = { |
229 | .sr_err_tbl = { | ||
230 | [0] = { | ||
231 | .len = 7, | ||
232 | .upper_limit = 0x03, | ||
233 | .values = { | ||
234 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
235 | 0x00 } | ||
236 | }, | ||
237 | [1] = { | ||
238 | .len = 7, | ||
239 | .upper_limit = 0x03, | ||
240 | .values = { | ||
241 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
242 | 0x00 } | ||
243 | }, | ||
244 | [2] = { | ||
245 | .len = 7, | ||
246 | .upper_limit = 0x03, | ||
247 | .values = { | ||
248 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
249 | 0x00 } | ||
250 | } | ||
251 | }, | ||
252 | .sr_enable = 1, | ||
253 | .genparam = { | 232 | .genparam = { |
254 | .ref_clk = CONF_REF_CLK_38_4_E, | 233 | .ref_clk = CONF_REF_CLK_38_4_E, |
255 | .settling_time = 5, | 234 | .settling_time = 5, |
256 | .clk_valid_on_wakeup = 0, | 235 | .clk_valid_on_wakeup = 0, |
257 | .dc2dcmode = 0, | 236 | .dc2dcmode = 0, |
258 | .single_dual_band = CONF_SINGLE_BAND, | 237 | .single_dual_band = CONF_SINGLE_BAND, |
259 | .tx_bip_fem_autodetect = 0, | 238 | .tx_bip_fem_autodetect = 1, |
260 | .tx_bip_fem_manufacturer = 1, | 239 | .tx_bip_fem_manufacturer = 1, |
261 | .settings = 1, | 240 | .settings = 1, |
241 | .sr_state = 1, | ||
242 | .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
243 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
244 | .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
245 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
246 | .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
247 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
248 | .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, | ||
249 | 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
250 | .sr_sen_n_p = 0, | ||
251 | .sr_sen_n_p_gain = 0, | ||
252 | .sr_sen_nrn = 0, | ||
253 | .sr_sen_prn = 0, | ||
262 | }, | 254 | }, |
263 | .radioparam = { | 255 | .radioparam = { |
264 | .rx_trace_loss = 10, | 256 | .rx_trace_loss = 0x24, |
265 | .tx_trace_loss = 10, | 257 | .tx_trace_loss = 0x0, |
266 | .rx_rssi_and_proc_compens = { | 258 | .rx_rssi_and_proc_compens = { |
267 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | 259 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, |
268 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | 260 | 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, |
269 | 0x00, 0x0a, 0x14 }, | 261 | 0x00, 0x0a, 0x14 }, |
270 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 262 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
271 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 263 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
@@ -273,13 +265,15 @@ static struct conf_drv_settings default_conf = { | |||
273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
275 | 0x00, 0x00, 0x00 }, | 267 | 0x00, 0x00, 0x00 }, |
276 | .tx_ref_pd_voltage = 0x24e, | 268 | .tx_ref_pd_voltage = 0x1a9, |
277 | .tx_ref_power = 0x78, | 269 | .tx_ref_power = 0x80, |
278 | .tx_offset_db = 0x0, | 270 | .tx_offset_db = 0x0, |
279 | .tx_rate_limits_normal = { | 271 | .tx_rate_limits_normal = { |
280 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | 272 | 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, |
281 | .tx_rate_limits_degraded = { | 273 | .tx_rate_limits_degraded = { |
282 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | 274 | 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, |
275 | .tx_rate_limits_extreme = { | ||
276 | 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
283 | .tx_channel_limits_11b = { | 277 | .tx_channel_limits_11b = { |
284 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | 278 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, |
285 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | 279 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, |
@@ -289,10 +283,12 @@ static struct conf_drv_settings default_conf = { | |||
289 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | 283 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, |
290 | 0x20, 0x50 }, | 284 | 0x20, 0x50 }, |
291 | .tx_pdv_rate_offsets = { | 285 | .tx_pdv_rate_offsets = { |
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | 286 | 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, |
293 | .tx_ibias = { | 287 | .tx_ibias = { |
294 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | 288 | 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, |
295 | .rx_fem_insertion_loss = 0x14, | 289 | .rx_fem_insertion_loss = 0x0e, |
290 | .degraded_low_to_normal_threshold = 0x1e, | ||
291 | .degraded_normal_to_high_threshold = 0x2d, | ||
296 | .tx_ref_pd_voltage_5 = { | 292 | .tx_ref_pd_voltage_5 = { |
297 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | 293 | 0x0190, 0x01a4, 0x01c3, 0x01d8, |
298 | 0x020a, 0x021c }, | 294 | 0x020a, 0x021c }, |
@@ -304,6 +300,8 @@ static struct conf_drv_settings default_conf = { | |||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 300 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
305 | .tx_rate_limits_degraded_5 = { | 301 | .tx_rate_limits_degraded_5 = { |
306 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 302 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
303 | .tx_rate_limits_extreme_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
307 | .tx_channel_limits_ofdm_5 = { | 305 | .tx_channel_limits_ofdm_5 = { |
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 306 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 307 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
@@ -315,8 +313,18 @@ static struct conf_drv_settings default_conf = { | |||
315 | .tx_ibias_5 = { | 313 | .tx_ibias_5 = { |
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | 314 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .rx_fem_insertion_loss_5 = { | 315 | .rx_fem_insertion_loss_5 = { |
318 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | 316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .degraded_low_to_normal_threshold_5 = 0x00, | ||
318 | .degraded_normal_to_high_threshold_5 = 0x00 | ||
319 | } | 319 | } |
320 | }, | ||
321 | .itrim = { | ||
322 | .enable = false, | ||
323 | .timeout = 50000, | ||
324 | }, | ||
325 | .pm_config = { | ||
326 | .host_clk_settling_time = 5000, | ||
327 | .host_fast_wakeup_support = false | ||
320 | } | 328 | } |
321 | }; | 329 | }; |
322 | 330 | ||
@@ -359,7 +367,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
359 | if (ret < 0) | 367 | if (ret < 0) |
360 | return ret; | 368 | return ret; |
361 | 369 | ||
362 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 370 | ret = wl1271_cmd_data_path(wl, 1); |
363 | if (ret < 0) | 371 | if (ret < 0) |
364 | return ret; | 372 | return ret; |
365 | 373 | ||
@@ -374,11 +382,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) | |||
374 | static void wl1271_power_off(struct wl1271 *wl) | 382 | static void wl1271_power_off(struct wl1271 *wl) |
375 | { | 383 | { |
376 | wl->set_power(false); | 384 | wl->set_power(false); |
385 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | 386 | } |
378 | 387 | ||
379 | static void wl1271_power_on(struct wl1271 *wl) | 388 | static void wl1271_power_on(struct wl1271 *wl) |
380 | { | 389 | { |
381 | wl->set_power(true); | 390 | wl->set_power(true); |
391 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | 392 | } |
383 | 393 | ||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 394 | static void wl1271_fw_status(struct wl1271 *wl, |
@@ -447,14 +457,13 @@ static void wl1271_irq_work(struct work_struct *work) | |||
447 | intr &= WL1271_INTR_MASK; | 457 | intr &= WL1271_INTR_MASK; |
448 | 458 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 459 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
450 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; | ||
451 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 460 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
452 | wl1271_event_handle(wl, 0, do_ack); | 461 | wl1271_event_handle(wl, 0); |
453 | } | 462 | } |
454 | 463 | ||
455 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 464 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
456 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 465 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
457 | wl1271_event_handle(wl, 1, true); | 466 | wl1271_event_handle(wl, 1); |
458 | } | 467 | } |
459 | 468 | ||
460 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 469 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -614,6 +623,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
614 | struct wl1271_partition_set partition; | 623 | struct wl1271_partition_set partition; |
615 | int ret = 0; | 624 | int ret = 0; |
616 | 625 | ||
626 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
617 | wl1271_power_on(wl); | 627 | wl1271_power_on(wl); |
618 | msleep(WL1271_POWER_ON_SLEEP); | 628 | msleep(WL1271_POWER_ON_SLEEP); |
619 | wl1271_spi_reset(wl); | 629 | wl1271_spi_reset(wl); |
@@ -643,7 +653,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
643 | 653 | ||
644 | ret = wl1271_setup(wl); | 654 | ret = wl1271_setup(wl); |
645 | if (ret < 0) | 655 | if (ret < 0) |
646 | goto out_power_off; | 656 | goto out; |
647 | break; | 657 | break; |
648 | case CHIP_ID_1271_PG20: | 658 | case CHIP_ID_1271_PG20: |
649 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 659 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -651,38 +661,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
651 | 661 | ||
652 | ret = wl1271_setup(wl); | 662 | ret = wl1271_setup(wl); |
653 | if (ret < 0) | 663 | if (ret < 0) |
654 | goto out_power_off; | 664 | goto out; |
655 | break; | 665 | break; |
656 | default: | 666 | default: |
657 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 667 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
658 | ret = -ENODEV; | 668 | ret = -ENODEV; |
659 | goto out_power_off; | 669 | goto out; |
660 | } | 670 | } |
661 | 671 | ||
662 | if (wl->fw == NULL) { | 672 | if (wl->fw == NULL) { |
663 | ret = wl1271_fetch_firmware(wl); | 673 | ret = wl1271_fetch_firmware(wl); |
664 | if (ret < 0) | 674 | if (ret < 0) |
665 | goto out_power_off; | 675 | goto out; |
666 | } | 676 | } |
667 | 677 | ||
668 | /* No NVS from netlink, try to get it from the filesystem */ | 678 | /* No NVS from netlink, try to get it from the filesystem */ |
669 | if (wl->nvs == NULL) { | 679 | if (wl->nvs == NULL) { |
670 | ret = wl1271_fetch_nvs(wl); | 680 | ret = wl1271_fetch_nvs(wl); |
671 | if (ret < 0) | 681 | if (ret < 0) |
672 | goto out_power_off; | 682 | goto out; |
673 | } | 683 | } |
674 | 684 | ||
675 | goto out; | ||
676 | |||
677 | out_power_off: | ||
678 | wl1271_power_off(wl); | ||
679 | |||
680 | out: | 685 | out: |
681 | return ret; | 686 | return ret; |
682 | } | 687 | } |
683 | 688 | ||
684 | int wl1271_plt_start(struct wl1271 *wl) | 689 | int wl1271_plt_start(struct wl1271 *wl) |
685 | { | 690 | { |
691 | int retries = WL1271_BOOT_RETRIES; | ||
686 | int ret; | 692 | int ret; |
687 | 693 | ||
688 | mutex_lock(&wl->mutex); | 694 | mutex_lock(&wl->mutex); |
@@ -696,35 +702,48 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
696 | goto out; | 702 | goto out; |
697 | } | 703 | } |
698 | 704 | ||
699 | wl->state = WL1271_STATE_PLT; | 705 | while (retries) { |
700 | 706 | retries--; | |
701 | ret = wl1271_chip_wakeup(wl); | 707 | ret = wl1271_chip_wakeup(wl); |
702 | if (ret < 0) | 708 | if (ret < 0) |
703 | goto out; | 709 | goto power_off; |
704 | |||
705 | ret = wl1271_boot(wl); | ||
706 | if (ret < 0) | ||
707 | goto out_power_off; | ||
708 | |||
709 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
710 | 710 | ||
711 | ret = wl1271_plt_init(wl); | 711 | ret = wl1271_boot(wl); |
712 | if (ret < 0) | 712 | if (ret < 0) |
713 | goto out_irq_disable; | 713 | goto power_off; |
714 | 714 | ||
715 | /* Make sure power saving is disabled */ | 715 | ret = wl1271_plt_init(wl); |
716 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 716 | if (ret < 0) |
717 | if (ret < 0) | 717 | goto irq_disable; |
718 | goto out_irq_disable; | ||
719 | 718 | ||
720 | goto out; | 719 | /* Make sure power saving is disabled */ |
720 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
721 | if (ret < 0) | ||
722 | goto irq_disable; | ||
721 | 723 | ||
722 | out_irq_disable: | 724 | wl->state = WL1271_STATE_PLT; |
723 | wl1271_disable_interrupts(wl); | 725 | wl1271_notice("firmware booted in PLT mode (%s)", |
726 | wl->chip.fw_ver); | ||
727 | goto out; | ||
724 | 728 | ||
725 | out_power_off: | 729 | irq_disable: |
726 | wl1271_power_off(wl); | 730 | wl1271_disable_interrupts(wl); |
731 | mutex_unlock(&wl->mutex); | ||
732 | /* Unlocking the mutex in the middle of handling is | ||
733 | inherently unsafe. In this case we deem it safe to do, | ||
734 | because we need to let any possibly pending IRQ out of | ||
735 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
736 | work function will not do anything.) Also, any other | ||
737 | possible concurrent operations will fail due to the | ||
738 | current state, hence the wl1271 struct should be safe. */ | ||
739 | cancel_work_sync(&wl->irq_work); | ||
740 | mutex_lock(&wl->mutex); | ||
741 | power_off: | ||
742 | wl1271_power_off(wl); | ||
743 | } | ||
727 | 744 | ||
745 | wl1271_error("firmware boot in PLT mode failed despite %d retries", | ||
746 | WL1271_BOOT_RETRIES); | ||
728 | out: | 747 | out: |
729 | mutex_unlock(&wl->mutex); | 748 | mutex_unlock(&wl->mutex); |
730 | 749 | ||
@@ -762,7 +781,20 @@ out: | |||
762 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 781 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
763 | { | 782 | { |
764 | struct wl1271 *wl = hw->priv; | 783 | struct wl1271 *wl = hw->priv; |
784 | struct ieee80211_conf *conf = &hw->conf; | ||
785 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
786 | struct ieee80211_sta *sta = txinfo->control.sta; | ||
787 | unsigned long flags; | ||
765 | 788 | ||
789 | /* peek into the rates configured in the STA entry */ | ||
790 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
791 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | ||
792 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | ||
793 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
794 | } | ||
795 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
796 | |||
797 | /* queue the packet */ | ||
766 | skb_queue_tail(&wl->tx_queue, skb); | 798 | skb_queue_tail(&wl->tx_queue, skb); |
767 | 799 | ||
768 | /* | 800 | /* |
@@ -784,7 +816,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | * protected. Maybe fix this by removing the stupid | 816 | * protected. Maybe fix this by removing the stupid |
785 | * variable altogether and checking the real queue state? | 817 | * variable altogether and checking the real queue state? |
786 | */ | 818 | */ |
787 | wl->tx_queue_stopped = true; | 819 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
788 | } | 820 | } |
789 | 821 | ||
790 | return NETDEV_TX_OK; | 822 | return NETDEV_TX_OK; |
@@ -880,6 +912,7 @@ static struct notifier_block wl1271_dev_notifier = { | |||
880 | static int wl1271_op_start(struct ieee80211_hw *hw) | 912 | static int wl1271_op_start(struct ieee80211_hw *hw) |
881 | { | 913 | { |
882 | struct wl1271 *wl = hw->priv; | 914 | struct wl1271 *wl = hw->priv; |
915 | int retries = WL1271_BOOT_RETRIES; | ||
883 | int ret = 0; | 916 | int ret = 0; |
884 | 917 | ||
885 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 918 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -893,30 +926,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
893 | goto out; | 926 | goto out; |
894 | } | 927 | } |
895 | 928 | ||
896 | ret = wl1271_chip_wakeup(wl); | 929 | while (retries) { |
897 | if (ret < 0) | 930 | retries--; |
898 | goto out; | 931 | ret = wl1271_chip_wakeup(wl); |
899 | 932 | if (ret < 0) | |
900 | ret = wl1271_boot(wl); | 933 | goto power_off; |
901 | if (ret < 0) | ||
902 | goto out_power_off; | ||
903 | |||
904 | ret = wl1271_hw_init(wl); | ||
905 | if (ret < 0) | ||
906 | goto out_irq_disable; | ||
907 | |||
908 | wl->state = WL1271_STATE_ON; | ||
909 | 934 | ||
910 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 935 | ret = wl1271_boot(wl); |
936 | if (ret < 0) | ||
937 | goto power_off; | ||
911 | 938 | ||
912 | goto out; | 939 | ret = wl1271_hw_init(wl); |
940 | if (ret < 0) | ||
941 | goto irq_disable; | ||
913 | 942 | ||
914 | out_irq_disable: | 943 | wl->state = WL1271_STATE_ON; |
915 | wl1271_disable_interrupts(wl); | 944 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
945 | goto out; | ||
916 | 946 | ||
917 | out_power_off: | 947 | irq_disable: |
918 | wl1271_power_off(wl); | 948 | wl1271_disable_interrupts(wl); |
949 | mutex_unlock(&wl->mutex); | ||
950 | /* Unlocking the mutex in the middle of handling is | ||
951 | inherently unsafe. In this case we deem it safe to do, | ||
952 | because we need to let any possibly pending IRQ out of | ||
953 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
954 | work function will not do anything.) Also, any other | ||
955 | possible concurrent operations will fail due to the | ||
956 | current state, hence the wl1271 struct should be safe. */ | ||
957 | cancel_work_sync(&wl->irq_work); | ||
958 | mutex_lock(&wl->mutex); | ||
959 | power_off: | ||
960 | wl1271_power_off(wl); | ||
961 | } | ||
919 | 962 | ||
963 | wl1271_error("firmware boot failed despite %d retries", | ||
964 | WL1271_BOOT_RETRIES); | ||
920 | out: | 965 | out: |
921 | mutex_unlock(&wl->mutex); | 966 | mutex_unlock(&wl->mutex); |
922 | 967 | ||
@@ -944,11 +989,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
944 | 989 | ||
945 | WARN_ON(wl->state != WL1271_STATE_ON); | 990 | WARN_ON(wl->state != WL1271_STATE_ON); |
946 | 991 | ||
947 | if (wl->scanning) { | 992 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
948 | mutex_unlock(&wl->mutex); | 993 | mutex_unlock(&wl->mutex); |
949 | ieee80211_scan_completed(wl->hw, true); | 994 | ieee80211_scan_completed(wl->hw, true); |
950 | mutex_lock(&wl->mutex); | 995 | mutex_lock(&wl->mutex); |
951 | wl->scanning = false; | ||
952 | } | 996 | } |
953 | 997 | ||
954 | wl->state = WL1271_STATE_OFF; | 998 | wl->state = WL1271_STATE_OFF; |
@@ -973,10 +1017,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
973 | wl->band = IEEE80211_BAND_2GHZ; | 1017 | wl->band = IEEE80211_BAND_2GHZ; |
974 | 1018 | ||
975 | wl->rx_counter = 0; | 1019 | wl->rx_counter = 0; |
976 | wl->elp = false; | ||
977 | wl->psm = 0; | ||
978 | wl->psm_entry_retry = 0; | 1020 | wl->psm_entry_retry = 0; |
979 | wl->tx_queue_stopped = false; | ||
980 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1021 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
981 | wl->tx_blocks_available = 0; | 1022 | wl->tx_blocks_available = 0; |
982 | wl->tx_results_count = 0; | 1023 | wl->tx_results_count = 0; |
@@ -986,7 +1027,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
986 | wl->tx_security_seq_32 = 0; | 1027 | wl->tx_security_seq_32 = 0; |
987 | wl->time_offset = 0; | 1028 | wl->time_offset = 0; |
988 | wl->session_counter = 0; | 1029 | wl->session_counter = 0; |
989 | wl->joined = false; | 1030 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1031 | wl->sta_rate_set = 0; | ||
1032 | wl->flags = 0; | ||
990 | 1033 | ||
991 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1034 | for (i = 0; i < NUM_TX_QUEUES; i++) |
992 | wl->tx_blocks_freed[i] = 0; | 1035 | wl->tx_blocks_freed[i] = 0; |
@@ -996,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
996 | } | 1039 | } |
997 | 1040 | ||
998 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1041 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
999 | struct ieee80211_if_init_conf *conf) | 1042 | struct ieee80211_vif *vif) |
1000 | { | 1043 | { |
1001 | struct wl1271 *wl = hw->priv; | 1044 | struct wl1271 *wl = hw->priv; |
1002 | int ret = 0; | 1045 | int ret = 0; |
1003 | 1046 | ||
1004 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1047 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1005 | conf->type, conf->mac_addr); | 1048 | vif->type, vif->addr); |
1006 | 1049 | ||
1007 | mutex_lock(&wl->mutex); | 1050 | mutex_lock(&wl->mutex); |
1008 | if (wl->vif) { | 1051 | if (wl->vif) { |
@@ -1010,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1010 | goto out; | 1053 | goto out; |
1011 | } | 1054 | } |
1012 | 1055 | ||
1013 | wl->vif = conf->vif; | 1056 | wl->vif = vif; |
1014 | 1057 | ||
1015 | switch (conf->type) { | 1058 | switch (vif->type) { |
1016 | case NL80211_IFTYPE_STATION: | 1059 | case NL80211_IFTYPE_STATION: |
1017 | wl->bss_type = BSS_TYPE_STA_BSS; | 1060 | wl->bss_type = BSS_TYPE_STA_BSS; |
1018 | break; | 1061 | break; |
@@ -1032,7 +1075,7 @@ out: | |||
1032 | } | 1075 | } |
1033 | 1076 | ||
1034 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1077 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_if_init_conf *conf) | 1078 | struct ieee80211_vif *vif) |
1036 | { | 1079 | { |
1037 | struct wl1271 *wl = hw->priv; | 1080 | struct wl1271 *wl = hw->priv; |
1038 | 1081 | ||
@@ -1109,6 +1152,51 @@ out: | |||
1109 | } | 1152 | } |
1110 | #endif | 1153 | #endif |
1111 | 1154 | ||
1155 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1156 | { | ||
1157 | int ret = 0; | ||
1158 | /* we need to use a dummy BSSID for now */ | ||
1159 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1160 | 0xad, 0xbe, 0xef }; | ||
1161 | |||
1162 | /* the dummy join is not required for ad-hoc */ | ||
1163 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1164 | goto out; | ||
1165 | |||
1166 | /* disable mac filter, so we hear everything */ | ||
1167 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1168 | |||
1169 | wl->channel = channel; | ||
1170 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1171 | |||
1172 | ret = wl1271_cmd_join(wl); | ||
1173 | if (ret < 0) | ||
1174 | goto out; | ||
1175 | |||
1176 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1177 | |||
1178 | out: | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1183 | { | ||
1184 | int ret; | ||
1185 | |||
1186 | /* to stop listening to a channel, we disconnect */ | ||
1187 | ret = wl1271_cmd_disconnect(wl); | ||
1188 | if (ret < 0) | ||
1189 | goto out; | ||
1190 | |||
1191 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1192 | wl->channel = 0; | ||
1193 | memset(wl->bssid, 0, ETH_ALEN); | ||
1194 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1195 | |||
1196 | out: | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1112 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1200 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1113 | { | 1201 | { |
1114 | struct wl1271 *wl = hw->priv; | 1202 | struct wl1271 *wl = hw->priv; |
@@ -1117,10 +1205,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1117 | 1205 | ||
1118 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1206 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1119 | 1207 | ||
1120 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1208 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1121 | channel, | 1209 | channel, |
1122 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1210 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1123 | conf->power_level); | 1211 | conf->power_level, |
1212 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1124 | 1213 | ||
1125 | mutex_lock(&wl->mutex); | 1214 | mutex_lock(&wl->mutex); |
1126 | 1215 | ||
@@ -1130,34 +1219,44 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1130 | if (ret < 0) | 1219 | if (ret < 0) |
1131 | goto out; | 1220 | goto out; |
1132 | 1221 | ||
1133 | if (channel != wl->channel) { | 1222 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1134 | /* | 1223 | if (conf->flags & IEEE80211_CONF_IDLE && |
1135 | * We assume that the stack will configure the right channel | 1224 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1136 | * before associating, so we don't need to send a join | 1225 | wl1271_unjoin_channel(wl); |
1137 | * command here. We will join the right channel when the | 1226 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1138 | * BSSID changes | 1227 | wl1271_join_channel(wl, channel); |
1139 | */ | 1228 | |
1140 | wl->channel = channel; | 1229 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1230 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1231 | wl->sta_rate_set = 0; | ||
1232 | wl1271_acx_rate_policies(wl); | ||
1233 | } | ||
1141 | } | 1234 | } |
1142 | 1235 | ||
1143 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1236 | /* if the channel changes while joined, join again */ |
1144 | wl1271_info("psm enabled"); | 1237 | if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1238 | wl1271_join_channel(wl, channel); | ||
1145 | 1239 | ||
1146 | wl->psm_requested = true; | 1240 | if (conf->flags & IEEE80211_CONF_PS && |
1241 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | ||
1242 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | ||
1147 | 1243 | ||
1148 | /* | 1244 | /* |
1149 | * We enter PSM only if we're already associated. | 1245 | * We enter PSM only if we're already associated. |
1150 | * If we're not, we'll enter it when joining an SSID, | 1246 | * If we're not, we'll enter it when joining an SSID, |
1151 | * through the bss_info_changed() hook. | 1247 | * through the bss_info_changed() hook. |
1152 | */ | 1248 | */ |
1153 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1249 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1250 | wl1271_info("psm enabled"); | ||
1251 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
1252 | } | ||
1154 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1253 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1155 | wl->psm_requested) { | 1254 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1156 | wl1271_info("psm disabled"); | 1255 | wl1271_info("psm disabled"); |
1157 | 1256 | ||
1158 | wl->psm_requested = false; | 1257 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1159 | 1258 | ||
1160 | if (wl->psm) | 1259 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1161 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1260 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); |
1162 | } | 1261 | } |
1163 | 1262 | ||
@@ -1440,22 +1539,6 @@ out: | |||
1440 | return ret; | 1539 | return ret; |
1441 | } | 1540 | } |
1442 | 1541 | ||
1443 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | ||
1444 | { | ||
1445 | struct ieee80211_supported_band *band; | ||
1446 | u32 enabled_rates = 0; | ||
1447 | int bit; | ||
1448 | |||
1449 | band = wl->hw->wiphy->bands[wl->band]; | ||
1450 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1451 | if (basic_rate_set & 0x1) | ||
1452 | enabled_rates |= band->bitrates[bit].hw_value; | ||
1453 | basic_rate_set >>= 1; | ||
1454 | } | ||
1455 | |||
1456 | return enabled_rates; | ||
1457 | } | ||
1458 | |||
1459 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1542 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
1460 | struct ieee80211_vif *vif, | 1543 | struct ieee80211_vif *vif, |
1461 | struct ieee80211_bss_conf *bss_conf, | 1544 | struct ieee80211_bss_conf *bss_conf, |
@@ -1473,9 +1556,68 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1473 | if (ret < 0) | 1556 | if (ret < 0) |
1474 | goto out; | 1557 | goto out; |
1475 | 1558 | ||
1559 | if ((changed & BSS_CHANGED_BSSID) && | ||
1560 | /* | ||
1561 | * Now we know the correct bssid, so we send a new join command | ||
1562 | * and enable the BSSID filter | ||
1563 | */ | ||
1564 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1565 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1566 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1567 | ret = wl1271_cmd_build_null_data(wl); | ||
1568 | if (ret < 0) { | ||
1569 | wl1271_warning("cmd buld null data failed %d", | ||
1570 | ret); | ||
1571 | goto out_sleep; | ||
1572 | } | ||
1573 | ret = wl1271_cmd_join(wl); | ||
1574 | if (ret < 0) { | ||
1575 | wl1271_warning("cmd join failed %d", ret); | ||
1576 | goto out_sleep; | ||
1577 | } | ||
1578 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1579 | } | ||
1580 | |||
1581 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
1582 | /* FIXME: This implements rudimentary ad-hoc support - | ||
1583 | proper templates are on the wish list and notification | ||
1584 | on when they change. This patch will update the templates | ||
1585 | on every call to this function. Also, the firmware will not | ||
1586 | answer to probe-requests as it does not have the proper | ||
1587 | SSID set in the JOIN command. The probe-response template | ||
1588 | is set nevertheless, as the FW will ASSERT without it */ | ||
1589 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
1590 | |||
1591 | if (beacon) { | ||
1592 | struct ieee80211_hdr *hdr; | ||
1593 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1594 | beacon->data, | ||
1595 | beacon->len); | ||
1596 | |||
1597 | if (ret < 0) { | ||
1598 | dev_kfree_skb(beacon); | ||
1599 | goto out_sleep; | ||
1600 | } | ||
1601 | |||
1602 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
1603 | hdr->frame_control = cpu_to_le16( | ||
1604 | IEEE80211_FTYPE_MGMT | | ||
1605 | IEEE80211_STYPE_PROBE_RESP); | ||
1606 | |||
1607 | ret = wl1271_cmd_template_set(wl, | ||
1608 | CMD_TEMPL_PROBE_RESPONSE, | ||
1609 | beacon->data, | ||
1610 | beacon->len); | ||
1611 | dev_kfree_skb(beacon); | ||
1612 | if (ret < 0) | ||
1613 | goto out_sleep; | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1476 | if (changed & BSS_CHANGED_ASSOC) { | 1617 | if (changed & BSS_CHANGED_ASSOC) { |
1477 | if (bss_conf->assoc) { | 1618 | if (bss_conf->assoc) { |
1478 | wl->aid = bss_conf->aid; | 1619 | wl->aid = bss_conf->aid; |
1620 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1479 | 1621 | ||
1480 | /* | 1622 | /* |
1481 | * with wl1271, we don't need to update the | 1623 | * with wl1271, we don't need to update the |
@@ -1492,7 +1634,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1492 | goto out_sleep; | 1634 | goto out_sleep; |
1493 | 1635 | ||
1494 | /* If we want to go in PSM but we're not there yet */ | 1636 | /* If we want to go in PSM but we're not there yet */ |
1495 | if (wl->psm_requested && !wl->psm) { | 1637 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1638 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1496 | mode = STATION_POWER_SAVE_MODE; | 1639 | mode = STATION_POWER_SAVE_MODE; |
1497 | ret = wl1271_ps_set_mode(wl, mode); | 1640 | ret = wl1271_ps_set_mode(wl, mode); |
1498 | if (ret < 0) | 1641 | if (ret < 0) |
@@ -1500,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1500 | } | 1643 | } |
1501 | } else { | 1644 | } else { |
1502 | /* use defaults when not associated */ | 1645 | /* use defaults when not associated */ |
1503 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1646 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1504 | wl->aid = 0; | 1647 | wl->aid = 0; |
1505 | } | 1648 | } |
1506 | 1649 | ||
@@ -1535,17 +1678,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1535 | } | 1678 | } |
1536 | } | 1679 | } |
1537 | 1680 | ||
1538 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1539 | wl->basic_rate_set = wl1271_enabled_rates_get( | ||
1540 | wl, bss_conf->basic_rates); | ||
1541 | |||
1542 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1543 | if (ret < 0) { | ||
1544 | wl1271_warning("Set rate policies failed %d", ret); | ||
1545 | goto out_sleep; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | out_sleep: | 1681 | out_sleep: |
1550 | wl1271_ps_elp_sleep(wl); | 1682 | wl1271_ps_elp_sleep(wl); |
1551 | 1683 | ||
@@ -1599,19 +1731,19 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1599 | 1731 | ||
1600 | /* can't be const, mac80211 writes to this */ | 1732 | /* can't be const, mac80211 writes to this */ |
1601 | static struct ieee80211_channel wl1271_channels[] = { | 1733 | static struct ieee80211_channel wl1271_channels[] = { |
1602 | { .hw_value = 1, .center_freq = 2412}, | 1734 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1603 | { .hw_value = 2, .center_freq = 2417}, | 1735 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, |
1604 | { .hw_value = 3, .center_freq = 2422}, | 1736 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, |
1605 | { .hw_value = 4, .center_freq = 2427}, | 1737 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, |
1606 | { .hw_value = 5, .center_freq = 2432}, | 1738 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
1607 | { .hw_value = 6, .center_freq = 2437}, | 1739 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, |
1608 | { .hw_value = 7, .center_freq = 2442}, | 1740 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, |
1609 | { .hw_value = 8, .center_freq = 2447}, | 1741 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, |
1610 | { .hw_value = 9, .center_freq = 2452}, | 1742 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
1611 | { .hw_value = 10, .center_freq = 2457}, | 1743 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, |
1612 | { .hw_value = 11, .center_freq = 2462}, | 1744 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
1613 | { .hw_value = 12, .center_freq = 2467}, | 1745 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
1614 | { .hw_value = 13, .center_freq = 2472}, | 1746 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1615 | }; | 1747 | }; |
1616 | 1748 | ||
1617 | /* can't be const, mac80211 writes to this */ | 1749 | /* can't be const, mac80211 writes to this */ |
@@ -1757,7 +1889,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1757 | IEEE80211_HW_BEACON_FILTER | | 1889 | IEEE80211_HW_BEACON_FILTER | |
1758 | IEEE80211_HW_SUPPORTS_PS; | 1890 | IEEE80211_HW_SUPPORTS_PS; |
1759 | 1891 | ||
1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1892 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1893 | BIT(NL80211_IFTYPE_ADHOC); | ||
1761 | wl->hw->wiphy->max_scan_ssids = 1; | 1894 | wl->hw->wiphy->max_scan_ssids = 1; |
1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 1895 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1763 | 1896 | ||
@@ -1818,21 +1951,18 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1818 | 1951 | ||
1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 1952 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1820 | wl->channel = WL1271_DEFAULT_CHANNEL; | 1953 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1821 | wl->scanning = false; | ||
1822 | wl->default_key = 0; | 1954 | wl->default_key = 0; |
1823 | wl->rx_counter = 0; | 1955 | wl->rx_counter = 0; |
1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1956 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 1957 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1826 | wl->elp = false; | ||
1827 | wl->psm = 0; | ||
1828 | wl->psm_requested = false; | ||
1829 | wl->psm_entry_retry = 0; | 1958 | wl->psm_entry_retry = 0; |
1830 | wl->tx_queue_stopped = false; | ||
1831 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1959 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1832 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1960 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
1961 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1962 | wl->sta_rate_set = 0; | ||
1833 | wl->band = IEEE80211_BAND_2GHZ; | 1963 | wl->band = IEEE80211_BAND_2GHZ; |
1834 | wl->vif = NULL; | 1964 | wl->vif = NULL; |
1835 | wl->joined = false; | 1965 | wl->flags = 0; |
1836 | 1966 | ||
1837 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 1967 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1838 | wl->tx_frames[i] = NULL; | 1968 | wl->tx_frames[i] = NULL; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 507cd91d7eed..e407790f6771 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 39 | ||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (wl->elp || !wl->psm) | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | ||
43 | goto out; | 44 | goto out; |
44 | 45 | ||
45 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 46 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
46 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 47 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
47 | wl->elp = true; | 48 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
48 | 49 | ||
49 | out: | 50 | out: |
50 | mutex_unlock(&wl->mutex); | 51 | mutex_unlock(&wl->mutex); |
@@ -55,7 +56,7 @@ out: | |||
55 | /* Routines to toggle sleep mode while in ELP */ | 56 | /* Routines to toggle sleep mode while in ELP */ |
56 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 57 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
57 | { | 58 | { |
58 | if (wl->psm) { | 59 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
59 | cancel_delayed_work(&wl->elp_work); | 60 | cancel_delayed_work(&wl->elp_work); |
60 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 61 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
61 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 62 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
@@ -70,7 +71,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
70 | u32 start_time = jiffies; | 71 | u32 start_time = jiffies; |
71 | bool pending = false; | 72 | bool pending = false; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
74 | return 0; | 75 | return 0; |
75 | 76 | ||
76 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); |
@@ -101,7 +102,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
101 | } | 102 | } |
102 | } | 103 | } |
103 | 104 | ||
104 | wl->elp = false; | 105 | clear_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
105 | 106 | ||
106 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", | 107 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", |
107 | jiffies_to_msecs(jiffies - start_time)); | 108 | jiffies_to_msecs(jiffies - start_time)); |
@@ -143,7 +144,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
143 | if (ret < 0) | 144 | if (ret < 0) |
144 | return ret; | 145 | return ret; |
145 | 146 | ||
146 | wl->psm = 1; | 147 | set_bit(WL1271_FLAG_PSM, &wl->flags); |
147 | break; | 148 | break; |
148 | case STATION_ACTIVE_MODE: | 149 | case STATION_ACTIVE_MODE: |
149 | default: | 150 | default: |
@@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
166 | if (ret < 0) | 167 | if (ret < 0) |
167 | return ret; | 168 | return ret; |
168 | 169 | ||
169 | wl->psm = 0; | 170 | clear_bit(WL1271_FLAG_PSM, &wl->flags); |
170 | break; | 171 | break; |
171 | } | 172 | } |
172 | 173 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 02978a16e732..ee9564aa6ecc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -397,8 +397,7 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | |||
397 | /* poll for data ready */ | 397 | /* poll for data ready */ |
398 | do { | 398 | do { |
399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | 399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); |
400 | timeout--; | 400 | } while (!(val & OCP_READY_MASK) && --timeout); |
401 | } while (!(val & OCP_READY_MASK) && timeout); | ||
402 | 401 | ||
403 | if (!timeout) { | 402 | if (!timeout) { |
404 | wl1271_warning("Top register access timed out."); | 403 | wl1271_warning("Top register access timed out."); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 00af065c77c2..a288cc317d7b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
121 | pad = pad - skb->len; | 121 | pad = pad - skb->len; |
122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
123 | 123 | ||
124 | /* if the packets are destined for AP (have a STA entry) send them | ||
125 | with AP rate policies, otherwise use default basic rates */ | ||
126 | if (control->control.sta) | ||
127 | tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; | ||
128 | |||
124 | desc->tx_attr = cpu_to_le16(tx_attr); | 129 | desc->tx_attr = cpu_to_le16(tx_attr); |
125 | 130 | ||
126 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 131 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
@@ -214,18 +219,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
214 | return ret; | 219 | return ret; |
215 | } | 220 | } |
216 | 221 | ||
222 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | ||
223 | { | ||
224 | struct ieee80211_supported_band *band; | ||
225 | u32 enabled_rates = 0; | ||
226 | int bit; | ||
227 | |||
228 | band = wl->hw->wiphy->bands[wl->band]; | ||
229 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
230 | if (rate_set & 0x1) | ||
231 | enabled_rates |= band->bitrates[bit].hw_value; | ||
232 | rate_set >>= 1; | ||
233 | } | ||
234 | |||
235 | return enabled_rates; | ||
236 | } | ||
237 | |||
217 | void wl1271_tx_work(struct work_struct *work) | 238 | void wl1271_tx_work(struct work_struct *work) |
218 | { | 239 | { |
219 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); | 240 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); |
220 | struct sk_buff *skb; | 241 | struct sk_buff *skb; |
221 | bool woken_up = false; | 242 | bool woken_up = false; |
243 | u32 sta_rates = 0; | ||
222 | int ret; | 244 | int ret; |
223 | 245 | ||
246 | /* check if the rates supported by the AP have changed */ | ||
247 | if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, | ||
248 | &wl->flags))) { | ||
249 | unsigned long flags; | ||
250 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
251 | sta_rates = wl->sta_rate_set; | ||
252 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
253 | } | ||
254 | |||
224 | mutex_lock(&wl->mutex); | 255 | mutex_lock(&wl->mutex); |
225 | 256 | ||
226 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 257 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
227 | goto out; | 258 | goto out; |
228 | 259 | ||
260 | /* if rates have changed, re-configure the rate policy */ | ||
261 | if (unlikely(sta_rates)) { | ||
262 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | ||
263 | wl1271_acx_rate_policies(wl); | ||
264 | } | ||
265 | |||
229 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 266 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
230 | if (!woken_up) { | 267 | if (!woken_up) { |
231 | ret = wl1271_ps_elp_wakeup(wl, false); | 268 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -240,18 +277,18 @@ void wl1271_tx_work(struct work_struct *work) | |||
240 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | 277 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " |
241 | "stop queues"); | 278 | "stop queues"); |
242 | ieee80211_stop_queues(wl->hw); | 279 | ieee80211_stop_queues(wl->hw); |
243 | wl->tx_queue_stopped = true; | 280 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
244 | skb_queue_head(&wl->tx_queue, skb); | 281 | skb_queue_head(&wl->tx_queue, skb); |
245 | goto out; | 282 | goto out; |
246 | } else if (ret < 0) { | 283 | } else if (ret < 0) { |
247 | dev_kfree_skb(skb); | 284 | dev_kfree_skb(skb); |
248 | goto out; | 285 | goto out; |
249 | } else if (wl->tx_queue_stopped) { | 286 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, |
287 | &wl->flags)) { | ||
250 | /* firmware buffer has space, restart queues */ | 288 | /* firmware buffer has space, restart queues */ |
251 | wl1271_debug(DEBUG_TX, | 289 | wl1271_debug(DEBUG_TX, |
252 | "complete_packet: waking queues"); | 290 | "complete_packet: waking queues"); |
253 | ieee80211_wake_queues(wl->hw); | 291 | ieee80211_wake_queues(wl->hw); |
254 | wl->tx_queue_stopped = false; | ||
255 | } | 292 | } |
256 | } | 293 | } |
257 | 294 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 9d9b263733e6..d90f0a25b9cf 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -869,7 +869,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
869 | } | 869 | } |
870 | 870 | ||
871 | static int zd_op_add_interface(struct ieee80211_hw *hw, | 871 | static int zd_op_add_interface(struct ieee80211_hw *hw, |
872 | struct ieee80211_if_init_conf *conf) | 872 | struct ieee80211_vif *vif) |
873 | { | 873 | { |
874 | struct zd_mac *mac = zd_hw_mac(hw); | 874 | struct zd_mac *mac = zd_hw_mac(hw); |
875 | 875 | ||
@@ -877,22 +877,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
877 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) | 877 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) |
878 | return -EOPNOTSUPP; | 878 | return -EOPNOTSUPP; |
879 | 879 | ||
880 | switch (conf->type) { | 880 | switch (vif->type) { |
881 | case NL80211_IFTYPE_MONITOR: | 881 | case NL80211_IFTYPE_MONITOR: |
882 | case NL80211_IFTYPE_MESH_POINT: | 882 | case NL80211_IFTYPE_MESH_POINT: |
883 | case NL80211_IFTYPE_STATION: | 883 | case NL80211_IFTYPE_STATION: |
884 | case NL80211_IFTYPE_ADHOC: | 884 | case NL80211_IFTYPE_ADHOC: |
885 | mac->type = conf->type; | 885 | mac->type = vif->type; |
886 | break; | 886 | break; |
887 | default: | 887 | default: |
888 | return -EOPNOTSUPP; | 888 | return -EOPNOTSUPP; |
889 | } | 889 | } |
890 | 890 | ||
891 | return zd_write_mac_addr(&mac->chip, conf->mac_addr); | 891 | return zd_write_mac_addr(&mac->chip, vif->addr); |
892 | } | 892 | } |
893 | 893 | ||
894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, | 894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, |
895 | struct ieee80211_if_init_conf *conf) | 895 | struct ieee80211_vif *vif) |
896 | { | 896 | { |
897 | struct zd_mac *mac = zd_hw_mac(hw); | 897 | struct zd_mac *mac = zd_hw_mac(hw); |
898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; | 898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; |
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; |