diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 256 |
1 files changed, 125 insertions, 131 deletions
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c1f8c69db165..c53692980990 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -38,6 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/slab.h> | ||
41 | #include <linux/module.h> | 42 | #include <linux/module.h> |
42 | #include <linux/etherdevice.h> | 43 | #include <linux/etherdevice.h> |
43 | #include <net/mac80211.h> | 44 | #include <net/mac80211.h> |
@@ -194,12 +195,15 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) | |||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | 195 | return ar9170_get_seq_h((void *) txc->frame_data); |
195 | } | 196 | } |
196 | 197 | ||
198 | static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) | ||
199 | { | ||
200 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
201 | } | ||
202 | |||
197 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | 203 | static inline u16 ar9170_get_tid(struct sk_buff *skb) |
198 | { | 204 | { |
199 | struct ar9170_tx_control *txc = (void *) skb->data; | 205 | struct ar9170_tx_control *txc = (void *) skb->data; |
200 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 206 | 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 | } | 207 | } |
204 | 208 | ||
205 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | 209 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) |
@@ -213,10 +217,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | |||
213 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | 217 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; |
214 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 218 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; |
215 | 219 | ||
216 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " | 220 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " |
217 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | 221 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", |
218 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), | 222 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), |
219 | ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), | 223 | ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), |
220 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | 224 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), |
221 | jiffies_to_msecs(arinfo->timeout - jiffies)); | 225 | jiffies_to_msecs(arinfo->timeout - jiffies)); |
222 | } | 226 | } |
@@ -391,7 +395,7 @@ static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) | |||
391 | ieee80211_tx_status_irqsafe(ar->hw, skb); | 395 | ieee80211_tx_status_irqsafe(ar->hw, skb); |
392 | } | 396 | } |
393 | 397 | ||
394 | for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { | 398 | for_each_set_bit(i, &queue_bitmap, BITS_PER_BYTE) { |
395 | #ifdef AR9170_QUEUE_STOP_DEBUG | 399 | #ifdef AR9170_QUEUE_STOP_DEBUG |
396 | printk(KERN_DEBUG "%s: wake queue %d\n", | 400 | printk(KERN_DEBUG "%s: wake queue %d\n", |
397 | wiphy_name(ar->hw->wiphy), i); | 401 | wiphy_name(ar->hw->wiphy), i); |
@@ -414,9 +418,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
414 | 418 | ||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | 419 | skb_queue_tail(&ar->tx_status_ampdu, skb); |
416 | ar9170_tx_fake_ampdu_status(ar); | 420 | ar9170_tx_fake_ampdu_status(ar); |
417 | ar->tx_ampdu_pending--; | ||
418 | 421 | ||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | 422 | if (atomic_dec_and_test(&ar->tx_ampdu_pending) && |
423 | !list_empty(&ar->tx_ampdu_list)) | ||
420 | ar9170_tx_ampdu(ar); | 424 | ar9170_tx_ampdu(ar); |
421 | } | 425 | } |
422 | 426 | ||
@@ -430,7 +434,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
430 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 434 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
431 | ar->tx_stats[queue].len--; | 435 | ar->tx_stats[queue].len--; |
432 | 436 | ||
433 | if (skb_queue_empty(&ar->tx_pending[queue])) { | 437 | if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { |
434 | #ifdef AR9170_QUEUE_STOP_DEBUG | 438 | #ifdef AR9170_QUEUE_STOP_DEBUG |
435 | printk(KERN_DEBUG "%s: wake queue %d\n", | 439 | printk(KERN_DEBUG "%s: wake queue %d\n", |
436 | wiphy_name(ar->hw->wiphy), queue); | 440 | wiphy_name(ar->hw->wiphy), queue); |
@@ -440,22 +444,17 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
440 | } | 444 | } |
441 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 445 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
442 | 446 | ||
443 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { | 447 | 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); | 448 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); |
452 | } else { | 449 | } else { |
453 | #ifdef AR9170_QUEUE_DEBUG | 450 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
454 | printk(KERN_DEBUG "%s: unsupported frame flags!\n", | 451 | ar9170_tx_ampdu_callback(ar, skb); |
455 | wiphy_name(ar->hw->wiphy)); | 452 | } else { |
456 | ar9170_print_txheader(ar, skb); | 453 | arinfo->timeout = jiffies + |
457 | #endif /* AR9170_QUEUE_DEBUG */ | 454 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
458 | dev_kfree_skb_any(skb); | 455 | |
456 | skb_queue_tail(&ar->tx_status[queue], skb); | ||
457 | } | ||
459 | } | 458 | } |
460 | 459 | ||
461 | if (!ar->tx_stats[queue].len && | 460 | if (!ar->tx_stats[queue].len && |
@@ -850,6 +849,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
850 | } | 849 | } |
851 | break; | 850 | break; |
852 | 851 | ||
852 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
853 | case AR9170_RX_STATUS_MODULATION_OFDM: | 853 | case AR9170_RX_STATUS_MODULATION_OFDM: |
854 | switch (head->plcp[0] & 0xf) { | 854 | switch (head->plcp[0] & 0xf) { |
855 | case 0xb: | 855 | case 0xb: |
@@ -897,8 +897,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
897 | status->flag |= RX_FLAG_HT; | 897 | status->flag |= RX_FLAG_HT; |
898 | break; | 898 | break; |
899 | 899 | ||
900 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | 900 | default: |
901 | /* XXX */ | ||
902 | if (ar9170_nag_limiter(ar)) | 901 | if (ar9170_nag_limiter(ar)) |
903 | printk(KERN_ERR "%s: invalid modulation\n", | 902 | printk(KERN_ERR "%s: invalid modulation\n", |
904 | wiphy_name(ar->hw->wiphy)); | 903 | wiphy_name(ar->hw->wiphy)); |
@@ -1248,6 +1247,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1248 | ar->global_ampdu_density = 6; | 1247 | ar->global_ampdu_density = 6; |
1249 | ar->global_ampdu_factor = 3; | 1248 | ar->global_ampdu_factor = 3; |
1250 | 1249 | ||
1250 | atomic_set(&ar->tx_ampdu_pending, 0); | ||
1251 | ar->bad_hw_nagger = jiffies; | 1251 | ar->bad_hw_nagger = jiffies; |
1252 | 1252 | ||
1253 | err = ar->open(ar); | 1253 | err = ar->open(ar); |
@@ -1406,17 +1406,6 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1406 | 1406 | ||
1407 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 1407 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
1408 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { | 1408 | (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { |
1409 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1410 | if (unlikely(!info->control.sta)) | ||
1411 | goto err_out; | ||
1412 | |||
1413 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1414 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; | ||
1415 | |||
1416 | goto out; | ||
1417 | } | ||
1418 | |||
1419 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1420 | /* | 1409 | /* |
1421 | * WARNING: | 1410 | * WARNING: |
1422 | * Putting the QoS queue bits into an unexplored territory is | 1411 | * Putting the QoS queue bits into an unexplored territory is |
@@ -1430,12 +1419,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1430 | 1419 | ||
1431 | txc->phy_control |= | 1420 | txc->phy_control |= |
1432 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); | 1421 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); |
1433 | arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; | 1422 | |
1434 | } else { | 1423 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1435 | arinfo->flags = AR9170_TX_FLAG_NO_ACK; | 1424 | if (unlikely(!info->control.sta)) |
1425 | goto err_out; | ||
1426 | |||
1427 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1428 | } else { | ||
1429 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1430 | } | ||
1436 | } | 1431 | } |
1437 | 1432 | ||
1438 | out: | ||
1439 | return 0; | 1433 | return 0; |
1440 | 1434 | ||
1441 | err_out: | 1435 | err_out: |
@@ -1670,8 +1664,7 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar) | |||
1670 | * tell the FW/HW that this is the last frame, | 1664 | * tell the FW/HW that this is the last frame, |
1671 | * that way it will wait for the immediate block ack. | 1665 | * that way it will wait for the immediate block ack. |
1672 | */ | 1666 | */ |
1673 | if (likely(skb_peek_tail(&agg))) | 1667 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); |
1674 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1675 | 1668 | ||
1676 | #ifdef AR9170_TXAGG_DEBUG | 1669 | #ifdef AR9170_TXAGG_DEBUG |
1677 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | 1670 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", |
@@ -1715,6 +1708,21 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1715 | 1708 | ||
1716 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 1709 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
1717 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 1710 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
1711 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1712 | skb_queue_len(&ar->tx_pending[i])); | ||
1713 | |||
1714 | if (remaining_space < frames) { | ||
1715 | #ifdef AR9170_QUEUE_DEBUG | ||
1716 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1717 | "remaining slots:%d, needed:%d\n", | ||
1718 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1719 | frames); | ||
1720 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1721 | frames = remaining_space; | ||
1722 | } | ||
1723 | |||
1724 | ar->tx_stats[i].len += frames; | ||
1725 | ar->tx_stats[i].count += frames; | ||
1718 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { | 1726 | if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { |
1719 | #ifdef AR9170_QUEUE_DEBUG | 1727 | #ifdef AR9170_QUEUE_DEBUG |
1720 | printk(KERN_DEBUG "%s: queue %d full\n", | 1728 | printk(KERN_DEBUG "%s: queue %d full\n", |
@@ -1732,25 +1740,8 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1732 | __ar9170_dump_txstats(ar); | 1740 | __ar9170_dump_txstats(ar); |
1733 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | 1741 | #endif /* AR9170_QUEUE_STOP_DEBUG */ |
1734 | ieee80211_stop_queue(ar->hw, i); | 1742 | ieee80211_stop_queue(ar->hw, i); |
1735 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | ||
1736 | continue; | ||
1737 | } | 1743 | } |
1738 | 1744 | ||
1739 | frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, | ||
1740 | skb_queue_len(&ar->tx_pending[i])); | ||
1741 | |||
1742 | if (remaining_space < frames) { | ||
1743 | #ifdef AR9170_QUEUE_DEBUG | ||
1744 | printk(KERN_DEBUG "%s: tx quota reached queue:%d, " | ||
1745 | "remaining slots:%d, needed:%d\n", | ||
1746 | wiphy_name(ar->hw->wiphy), i, remaining_space, | ||
1747 | frames); | ||
1748 | #endif /* AR9170_QUEUE_DEBUG */ | ||
1749 | frames = remaining_space; | ||
1750 | } | ||
1751 | |||
1752 | ar->tx_stats[i].len += frames; | ||
1753 | ar->tx_stats[i].count += frames; | ||
1754 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1745 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1755 | 1746 | ||
1756 | if (!frames) | 1747 | if (!frames) |
@@ -1772,8 +1763,8 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1772 | arinfo->timeout = jiffies + | 1763 | arinfo->timeout = jiffies + |
1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1764 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1774 | 1765 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1766 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1776 | ar->tx_ampdu_pending++; | 1767 | atomic_inc(&ar->tx_ampdu_pending); |
1777 | 1768 | ||
1778 | #ifdef AR9170_QUEUE_DEBUG | 1769 | #ifdef AR9170_QUEUE_DEBUG |
1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1770 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
@@ -1783,8 +1774,8 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1783 | 1774 | ||
1784 | err = ar->tx(ar, skb); | 1775 | err = ar->tx(ar, skb); |
1785 | if (unlikely(err)) { | 1776 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1777 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
1787 | ar->tx_ampdu_pending--; | 1778 | atomic_dec(&ar->tx_ampdu_pending); |
1788 | 1779 | ||
1789 | frames_failed++; | 1780 | frames_failed++; |
1790 | dev_kfree_skb_any(skb); | 1781 | dev_kfree_skb_any(skb); |
@@ -1931,7 +1922,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1931 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1922 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1932 | bool run = ar9170_tx_ampdu_queue(ar, skb); | 1923 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1933 | 1924 | ||
1934 | if (run || !ar->tx_ampdu_pending) | 1925 | if (run || !atomic_read(&ar->tx_ampdu_pending)) |
1935 | ar9170_tx_ampdu(ar); | 1926 | ar9170_tx_ampdu(ar); |
1936 | } else { | 1927 | } else { |
1937 | unsigned int queue = skb_get_queue_mapping(skb); | 1928 | unsigned int queue = skb_get_queue_mapping(skb); |
@@ -1949,9 +1940,10 @@ err_free: | |||
1949 | } | 1940 | } |
1950 | 1941 | ||
1951 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | 1942 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, |
1952 | struct ieee80211_if_init_conf *conf) | 1943 | struct ieee80211_vif *vif) |
1953 | { | 1944 | { |
1954 | struct ar9170 *ar = hw->priv; | 1945 | struct ar9170 *ar = hw->priv; |
1946 | struct ath_common *common = &ar->common; | ||
1955 | int err = 0; | 1947 | int err = 0; |
1956 | 1948 | ||
1957 | mutex_lock(&ar->mutex); | 1949 | mutex_lock(&ar->mutex); |
@@ -1961,8 +1953,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1961 | goto unlock; | 1953 | goto unlock; |
1962 | } | 1954 | } |
1963 | 1955 | ||
1964 | ar->vif = conf->vif; | 1956 | ar->vif = vif; |
1965 | memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); | 1957 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1966 | 1958 | ||
1967 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1959 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1968 | ar->rx_software_decryption = true; | 1960 | ar->rx_software_decryption = true; |
@@ -1982,7 +1974,7 @@ unlock: | |||
1982 | } | 1974 | } |
1983 | 1975 | ||
1984 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | 1976 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, |
1985 | struct ieee80211_if_init_conf *conf) | 1977 | struct ieee80211_vif *vif) |
1986 | { | 1978 | { |
1987 | struct ar9170 *ar = hw->priv; | 1979 | struct ar9170 *ar = hw->priv; |
1988 | 1980 | ||
@@ -2131,12 +2123,13 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2131 | u32 changed) | 2123 | u32 changed) |
2132 | { | 2124 | { |
2133 | struct ar9170 *ar = hw->priv; | 2125 | struct ar9170 *ar = hw->priv; |
2126 | struct ath_common *common = &ar->common; | ||
2134 | int err = 0; | 2127 | int err = 0; |
2135 | 2128 | ||
2136 | mutex_lock(&ar->mutex); | 2129 | mutex_lock(&ar->mutex); |
2137 | 2130 | ||
2138 | if (changed & BSS_CHANGED_BSSID) { | 2131 | if (changed & BSS_CHANGED_BSSID) { |
2139 | memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); | 2132 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
2140 | err = ar9170_set_operating_mode(ar); | 2133 | err = ar9170_set_operating_mode(ar); |
2141 | if (err) | 2134 | if (err) |
2142 | goto out; | 2135 | goto out; |
@@ -2190,22 +2183,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) | |||
2190 | { | 2183 | { |
2191 | struct ar9170 *ar = hw->priv; | 2184 | struct ar9170 *ar = hw->priv; |
2192 | int err; | 2185 | int err; |
2193 | u32 tsf_low; | ||
2194 | u32 tsf_high; | ||
2195 | u64 tsf; | 2186 | u64 tsf; |
2187 | #define NR 3 | ||
2188 | static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, | ||
2189 | AR9170_MAC_REG_TSF_L, | ||
2190 | AR9170_MAC_REG_TSF_H }; | ||
2191 | u32 val[NR]; | ||
2192 | int loops = 0; | ||
2196 | 2193 | ||
2197 | mutex_lock(&ar->mutex); | 2194 | mutex_lock(&ar->mutex); |
2198 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); | 2195 | |
2199 | if (!err) | 2196 | while (loops++ < 10) { |
2200 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); | 2197 | err = ar9170_read_mreg(ar, NR, addr, val); |
2198 | if (err || val[0] == val[2]) | ||
2199 | break; | ||
2200 | } | ||
2201 | |||
2201 | mutex_unlock(&ar->mutex); | 2202 | mutex_unlock(&ar->mutex); |
2202 | 2203 | ||
2203 | if (WARN_ON(err)) | 2204 | if (WARN_ON(err)) |
2204 | return 0; | 2205 | return 0; |
2205 | 2206 | tsf = val[0]; | |
2206 | tsf = tsf_high; | 2207 | tsf = (tsf << 32) | val[1]; |
2207 | tsf = (tsf << 32) | tsf_low; | ||
2208 | return tsf; | 2208 | return tsf; |
2209 | #undef NR | ||
2209 | } | 2210 | } |
2210 | 2211 | ||
2211 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2212 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -2329,55 +2330,55 @@ out: | |||
2329 | return err; | 2330 | return err; |
2330 | } | 2331 | } |
2331 | 2332 | ||
2332 | static void ar9170_sta_notify(struct ieee80211_hw *hw, | 2333 | static int ar9170_sta_add(struct ieee80211_hw *hw, |
2333 | struct ieee80211_vif *vif, | 2334 | struct ieee80211_vif *vif, |
2334 | enum sta_notify_cmd cmd, | 2335 | struct ieee80211_sta *sta) |
2335 | struct ieee80211_sta *sta) | ||
2336 | { | 2336 | { |
2337 | struct ar9170 *ar = hw->priv; | 2337 | struct ar9170 *ar = hw->priv; |
2338 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | 2338 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; |
2339 | unsigned int i; | 2339 | unsigned int i; |
2340 | 2340 | ||
2341 | switch (cmd) { | 2341 | memset(sta_info, 0, sizeof(*sta_info)); |
2342 | case STA_NOTIFY_ADD: | ||
2343 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2344 | 2342 | ||
2345 | if (!sta->ht_cap.ht_supported) | 2343 | if (!sta->ht_cap.ht_supported) |
2346 | break; | 2344 | return 0; |
2347 | 2345 | ||
2348 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | 2346 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) |
2349 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | 2347 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; |
2350 | 2348 | ||
2351 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | 2349 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) |
2352 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | 2350 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; |
2353 | 2351 | ||
2354 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2352 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2355 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | 2353 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; |
2356 | sta_info->agg[i].active = false; | 2354 | sta_info->agg[i].active = false; |
2357 | sta_info->agg[i].ssn = 0; | 2355 | sta_info->agg[i].ssn = 0; |
2358 | sta_info->agg[i].retry = 0; | 2356 | sta_info->agg[i].tid = i; |
2359 | sta_info->agg[i].tid = i; | 2357 | INIT_LIST_HEAD(&sta_info->agg[i].list); |
2360 | INIT_LIST_HEAD(&sta_info->agg[i].list); | 2358 | skb_queue_head_init(&sta_info->agg[i].queue); |
2361 | skb_queue_head_init(&sta_info->agg[i].queue); | 2359 | } |
2362 | } | ||
2363 | 2360 | ||
2364 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | 2361 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); |
2365 | break; | ||
2366 | 2362 | ||
2367 | case STA_NOTIFY_REMOVE: | 2363 | return 0; |
2368 | if (!sta->ht_cap.ht_supported) | 2364 | } |
2369 | break; | ||
2370 | 2365 | ||
2371 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2366 | static int ar9170_sta_remove(struct ieee80211_hw *hw, |
2372 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | 2367 | struct ieee80211_vif *vif, |
2373 | skb_queue_purge(&sta_info->agg[i].queue); | 2368 | struct ieee80211_sta *sta) |
2374 | } | 2369 | { |
2370 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2371 | unsigned int i; | ||
2375 | 2372 | ||
2376 | break; | 2373 | if (!sta->ht_cap.ht_supported) |
2374 | return 0; | ||
2377 | 2375 | ||
2378 | default: | 2376 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2379 | break; | 2377 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; |
2378 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2380 | } | 2379 | } |
2380 | |||
2381 | return 0; | ||
2381 | } | 2382 | } |
2382 | 2383 | ||
2383 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2384 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -2397,18 +2398,6 @@ static int ar9170_get_stats(struct ieee80211_hw *hw, | |||
2397 | return 0; | 2398 | return 0; |
2398 | } | 2399 | } |
2399 | 2400 | ||
2400 | static int ar9170_get_tx_stats(struct ieee80211_hw *hw, | ||
2401 | struct ieee80211_tx_queue_stats *tx_stats) | ||
2402 | { | ||
2403 | struct ar9170 *ar = hw->priv; | ||
2404 | |||
2405 | spin_lock_bh(&ar->tx_stats_lock); | ||
2406 | memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); | ||
2407 | spin_unlock_bh(&ar->tx_stats_lock); | ||
2408 | |||
2409 | return 0; | ||
2410 | } | ||
2411 | |||
2412 | static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2401 | static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, |
2413 | const struct ieee80211_tx_queue_params *param) | 2402 | const struct ieee80211_tx_queue_params *param) |
2414 | { | 2403 | { |
@@ -2430,6 +2419,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2430 | } | 2419 | } |
2431 | 2420 | ||
2432 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, | 2421 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, |
2422 | struct ieee80211_vif *vif, | ||
2433 | enum ieee80211_ampdu_mlme_action action, | 2423 | enum ieee80211_ampdu_mlme_action action, |
2434 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2424 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2435 | { | 2425 | { |
@@ -2459,7 +2449,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2459 | tid_info->state = AR9170_TID_STATE_PROGRESS; | 2449 | tid_info->state = AR9170_TID_STATE_PROGRESS; |
2460 | tid_info->active = false; | 2450 | tid_info->active = false; |
2461 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2451 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2462 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2452 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2463 | break; | 2453 | break; |
2464 | 2454 | ||
2465 | case IEEE80211_AMPDU_TX_STOP: | 2455 | case IEEE80211_AMPDU_TX_STOP: |
@@ -2469,7 +2459,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2469 | tid_info->active = false; | 2459 | tid_info->active = false; |
2470 | skb_queue_purge(&tid_info->queue); | 2460 | skb_queue_purge(&tid_info->queue); |
2471 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2461 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2472 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2462 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2473 | break; | 2463 | break; |
2474 | 2464 | ||
2475 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 2465 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
@@ -2507,9 +2497,9 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2507 | .bss_info_changed = ar9170_op_bss_info_changed, | 2497 | .bss_info_changed = ar9170_op_bss_info_changed, |
2508 | .get_tsf = ar9170_op_get_tsf, | 2498 | .get_tsf = ar9170_op_get_tsf, |
2509 | .set_key = ar9170_set_key, | 2499 | .set_key = ar9170_set_key, |
2510 | .sta_notify = ar9170_sta_notify, | 2500 | .sta_add = ar9170_sta_add, |
2501 | .sta_remove = ar9170_sta_remove, | ||
2511 | .get_stats = ar9170_get_stats, | 2502 | .get_stats = ar9170_get_stats, |
2512 | .get_tx_stats = ar9170_get_tx_stats, | ||
2513 | .ampdu_action = ar9170_ampdu_action, | 2503 | .ampdu_action = ar9170_ampdu_action, |
2514 | }; | 2504 | }; |
2515 | 2505 | ||
@@ -2523,7 +2513,7 @@ void *ar9170_alloc(size_t priv_size) | |||
2523 | /* | 2513 | /* |
2524 | * this buffer is used for rx stream reconstruction. | 2514 | * this buffer is used for rx stream reconstruction. |
2525 | * Under heavy load this device (or the transport layer?) | 2515 | * Under heavy load this device (or the transport layer?) |
2526 | * tends to split the streams into seperate rx descriptors. | 2516 | * tends to split the streams into separate rx descriptors. |
2527 | */ | 2517 | */ |
2528 | 2518 | ||
2529 | skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); | 2519 | skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); |
@@ -2712,7 +2702,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) | |||
2712 | dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", | 2702 | dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", |
2713 | wiphy_name(ar->hw->wiphy)); | 2703 | wiphy_name(ar->hw->wiphy)); |
2714 | 2704 | ||
2715 | return err; | 2705 | ar->registered = true; |
2706 | return 0; | ||
2716 | 2707 | ||
2717 | err_unreg: | 2708 | err_unreg: |
2718 | ieee80211_unregister_hw(ar->hw); | 2709 | ieee80211_unregister_hw(ar->hw); |
@@ -2723,11 +2714,14 @@ err_out: | |||
2723 | 2714 | ||
2724 | void ar9170_unregister(struct ar9170 *ar) | 2715 | void ar9170_unregister(struct ar9170 *ar) |
2725 | { | 2716 | { |
2717 | if (ar->registered) { | ||
2726 | #ifdef CONFIG_AR9170_LEDS | 2718 | #ifdef CONFIG_AR9170_LEDS |
2727 | ar9170_unregister_leds(ar); | 2719 | ar9170_unregister_leds(ar); |
2728 | #endif /* CONFIG_AR9170_LEDS */ | 2720 | #endif /* CONFIG_AR9170_LEDS */ |
2729 | 2721 | ||
2730 | kfree_skb(ar->rx_failover); | ||
2731 | ieee80211_unregister_hw(ar->hw); | 2722 | ieee80211_unregister_hw(ar->hw); |
2723 | } | ||
2724 | |||
2725 | kfree_skb(ar->rx_failover); | ||
2732 | mutex_destroy(&ar->mutex); | 2726 | mutex_destroy(&ar->mutex); |
2733 | } | 2727 | } |