diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/ar9170.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/cmd.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/cmd.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/hw.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/mac.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/phy.c | 99 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.h | 2 |
10 files changed, 141 insertions, 59 deletions
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig index 05918f1e685a..d7a4799d20fb 100644 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ b/drivers/net/wireless/ath/ar9170/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config AR9170_USB | 1 | config AR9170_USB |
2 | tristate "Atheros AR9170 802.11n USB support" | 2 | tristate "Atheros AR9170 802.11n USB support" |
3 | depends on USB && MAC80211 && WLAN_80211 | 3 | depends on USB && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | help | 5 | help |
6 | This is a driver for the Atheros "otus" 802.11n USB devices. | 6 | This is a driver for the Atheros "otus" 802.11n USB devices. |
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 914e4718a9a8..9f9459860d82 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -172,8 +172,6 @@ struct ar9170 { | |||
172 | 172 | ||
173 | /* interface mode settings */ | 173 | /* interface mode settings */ |
174 | struct ieee80211_vif *vif; | 174 | struct ieee80211_vif *vif; |
175 | u8 mac_addr[ETH_ALEN]; | ||
176 | u8 bssid[ETH_ALEN]; | ||
177 | 175 | ||
178 | /* beaconing */ | 176 | /* beaconing */ |
179 | struct sk_buff *beacon; | 177 | struct sk_buff *beacon; |
@@ -204,6 +202,8 @@ struct ar9170 { | |||
204 | u8 power_2G_ht20[8]; | 202 | u8 power_2G_ht20[8]; |
205 | u8 power_2G_ht40[8]; | 203 | u8 power_2G_ht40[8]; |
206 | 204 | ||
205 | u8 phy_heavy_clip; | ||
206 | |||
207 | #ifdef CONFIG_AR9170_LEDS | 207 | #ifdef CONFIG_AR9170_LEDS |
208 | struct delayed_work led_work; | 208 | struct delayed_work led_work; |
209 | struct ar9170_led leds[AR9170_NUM_LEDS]; | 209 | struct ar9170_led leds[AR9170_NUM_LEDS]; |
@@ -231,7 +231,7 @@ struct ar9170 { | |||
231 | struct sk_buff_head tx_status_ampdu; | 231 | struct sk_buff_head tx_status_ampdu; |
232 | spinlock_t tx_ampdu_list_lock; | 232 | spinlock_t tx_ampdu_list_lock; |
233 | struct list_head tx_ampdu_list; | 233 | struct list_head tx_ampdu_list; |
234 | unsigned int tx_ampdu_pending; | 234 | atomic_t tx_ampdu_pending; |
235 | 235 | ||
236 | /* rxstream mpdu merge */ | 236 | /* rxstream mpdu merge */ |
237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | 237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; |
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index f57a6200167b..cf6f5c4174a6 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c | |||
@@ -72,8 +72,7 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) | |||
72 | return err; | 72 | return err; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int ar9170_read_mreg(struct ar9170 *ar, int nregs, | 75 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) |
76 | const u32 *regs, u32 *out) | ||
77 | { | 76 | { |
78 | int i, err; | 77 | int i, err; |
79 | __le32 *offs, *res; | 78 | __le32 *offs, *res; |
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index a4f0e50e52b4..826c45e6b274 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h | |||
@@ -44,6 +44,7 @@ | |||
44 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); | 44 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); |
45 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); | 45 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); |
46 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); | 46 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); |
47 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); | ||
47 | int ar9170_echo_test(struct ar9170 *ar, u32 v); | 48 | int ar9170_echo_test(struct ar9170 *ar, u32 v); |
48 | 49 | ||
49 | /* | 50 | /* |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 6cbfb2f83391..701ddb7d8400 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -152,14 +152,14 @@ enum ar9170_cmd { | |||
152 | #define AR9170_MAC_REG_FTF_BIT14 BIT(14) | 152 | #define AR9170_MAC_REG_FTF_BIT14 BIT(14) |
153 | #define AR9170_MAC_REG_FTF_BIT15 BIT(15) | 153 | #define AR9170_MAC_REG_FTF_BIT15 BIT(15) |
154 | #define AR9170_MAC_REG_FTF_BAR BIT(24) | 154 | #define AR9170_MAC_REG_FTF_BAR BIT(24) |
155 | #define AR9170_MAC_REG_FTF_BIT25 BIT(25) | 155 | #define AR9170_MAC_REG_FTF_BA BIT(25) |
156 | #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) | 156 | #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) |
157 | #define AR9170_MAC_REG_FTF_RTS BIT(27) | 157 | #define AR9170_MAC_REG_FTF_RTS BIT(27) |
158 | #define AR9170_MAC_REG_FTF_CTS BIT(28) | 158 | #define AR9170_MAC_REG_FTF_CTS BIT(28) |
159 | #define AR9170_MAC_REG_FTF_ACK BIT(29) | 159 | #define AR9170_MAC_REG_FTF_ACK BIT(29) |
160 | #define AR9170_MAC_REG_FTF_CFE BIT(30) | 160 | #define AR9170_MAC_REG_FTF_CFE BIT(30) |
161 | #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) | 161 | #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) |
162 | #define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff | 162 | #define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff |
163 | #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff | 163 | #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff |
164 | 164 | ||
165 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) | 165 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) |
@@ -311,6 +311,8 @@ struct ar9170_tx_control { | |||
311 | 311 | ||
312 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 | 312 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 |
313 | 313 | ||
314 | #define AR5416_MAX_RATE_POWER 63 | ||
315 | |||
314 | struct ar9170_rx_head { | 316 | struct ar9170_rx_head { |
315 | u8 plcp[12]; | 317 | u8 plcp[12]; |
316 | } __packed; | 318 | } __packed; |
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 614e3218a2bc..ddc8c09dc79e 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c | |||
@@ -35,6 +35,9 @@ | |||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
37 | */ | 37 | */ |
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
38 | #include "ar9170.h" | 41 | #include "ar9170.h" |
39 | #include "cmd.h" | 42 | #include "cmd.h" |
40 | 43 | ||
@@ -227,11 +230,8 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) | |||
227 | 230 | ||
228 | ar9170_regwrite_begin(ar); | 231 | ar9170_regwrite_begin(ar); |
229 | 232 | ||
230 | ar9170_regwrite(reg, | 233 | ar9170_regwrite(reg, get_unaligned_le32(mac)); |
231 | (mac[3] << 24) | (mac[2] << 16) | | 234 | ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); |
232 | (mac[1] << 8) | mac[0]); | ||
233 | |||
234 | ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); | ||
235 | 235 | ||
236 | ar9170_regwrite_finish(); | 236 | ar9170_regwrite_finish(); |
237 | 237 | ||
@@ -311,13 +311,14 @@ static int ar9170_set_promiscouous(struct ar9170 *ar) | |||
311 | 311 | ||
312 | int ar9170_set_operating_mode(struct ar9170 *ar) | 312 | int ar9170_set_operating_mode(struct ar9170 *ar) |
313 | { | 313 | { |
314 | struct ath_common *common = &ar->common; | ||
314 | u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; | 315 | u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; |
315 | u8 *mac_addr, *bssid; | 316 | u8 *mac_addr, *bssid; |
316 | int err; | 317 | int err; |
317 | 318 | ||
318 | if (ar->vif) { | 319 | if (ar->vif) { |
319 | mac_addr = ar->mac_addr; | 320 | mac_addr = common->macaddr; |
320 | bssid = ar->bssid; | 321 | bssid = common->curbssid; |
321 | 322 | ||
322 | switch (ar->vif->type) { | 323 | switch (ar->vif->type) { |
323 | case NL80211_IFTYPE_MESH_POINT: | 324 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c1f8c69db165..f9d6db8d013e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
414 | 414 | ||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | 415 | skb_queue_tail(&ar->tx_status_ampdu, skb); |
416 | ar9170_tx_fake_ampdu_status(ar); | 416 | ar9170_tx_fake_ampdu_status(ar); |
417 | ar->tx_ampdu_pending--; | ||
418 | 417 | ||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | 418 | if (atomic_dec_and_test(&ar->tx_ampdu_pending) && |
419 | !list_empty(&ar->tx_ampdu_list)) | ||
420 | ar9170_tx_ampdu(ar); | 420 | ar9170_tx_ampdu(ar); |
421 | } | 421 | } |
422 | 422 | ||
@@ -850,6 +850,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
850 | } | 850 | } |
851 | break; | 851 | break; |
852 | 852 | ||
853 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
853 | case AR9170_RX_STATUS_MODULATION_OFDM: | 854 | case AR9170_RX_STATUS_MODULATION_OFDM: |
854 | switch (head->plcp[0] & 0xf) { | 855 | switch (head->plcp[0] & 0xf) { |
855 | case 0xb: | 856 | case 0xb: |
@@ -897,8 +898,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
897 | status->flag |= RX_FLAG_HT; | 898 | status->flag |= RX_FLAG_HT; |
898 | break; | 899 | break; |
899 | 900 | ||
900 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | 901 | default: |
901 | /* XXX */ | ||
902 | if (ar9170_nag_limiter(ar)) | 902 | if (ar9170_nag_limiter(ar)) |
903 | printk(KERN_ERR "%s: invalid modulation\n", | 903 | printk(KERN_ERR "%s: invalid modulation\n", |
904 | wiphy_name(ar->hw->wiphy)); | 904 | wiphy_name(ar->hw->wiphy)); |
@@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1248 | ar->global_ampdu_density = 6; | 1248 | ar->global_ampdu_density = 6; |
1249 | ar->global_ampdu_factor = 3; | 1249 | ar->global_ampdu_factor = 3; |
1250 | 1250 | ||
1251 | atomic_set(&ar->tx_ampdu_pending, 0); | ||
1251 | ar->bad_hw_nagger = jiffies; | 1252 | ar->bad_hw_nagger = jiffies; |
1252 | 1253 | ||
1253 | err = ar->open(ar); | 1254 | err = ar->open(ar); |
@@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1774 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1774 | 1775 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1776 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1776 | ar->tx_ampdu_pending++; | 1777 | atomic_inc(&ar->tx_ampdu_pending); |
1777 | 1778 | ||
1778 | #ifdef AR9170_QUEUE_DEBUG | 1779 | #ifdef AR9170_QUEUE_DEBUG |
1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1780 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
@@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1784 | err = ar->tx(ar, skb); | 1785 | err = ar->tx(ar, skb); |
1785 | if (unlikely(err)) { | 1786 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1787 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1787 | ar->tx_ampdu_pending--; | 1788 | atomic_dec(&ar->tx_ampdu_pending); |
1788 | 1789 | ||
1789 | frames_failed++; | 1790 | frames_failed++; |
1790 | dev_kfree_skb_any(skb); | 1791 | dev_kfree_skb_any(skb); |
@@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1931 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1932 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1932 | bool run = ar9170_tx_ampdu_queue(ar, skb); | 1933 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1933 | 1934 | ||
1934 | if (run || !ar->tx_ampdu_pending) | 1935 | if (run || !atomic_read(&ar->tx_ampdu_pending)) |
1935 | ar9170_tx_ampdu(ar); | 1936 | ar9170_tx_ampdu(ar); |
1936 | } else { | 1937 | } else { |
1937 | unsigned int queue = skb_get_queue_mapping(skb); | 1938 | unsigned int queue = skb_get_queue_mapping(skb); |
@@ -1952,6 +1953,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1952 | struct ieee80211_if_init_conf *conf) | 1953 | struct ieee80211_if_init_conf *conf) |
1953 | { | 1954 | { |
1954 | struct ar9170 *ar = hw->priv; | 1955 | struct ar9170 *ar = hw->priv; |
1956 | struct ath_common *common = &ar->common; | ||
1955 | int err = 0; | 1957 | int err = 0; |
1956 | 1958 | ||
1957 | mutex_lock(&ar->mutex); | 1959 | mutex_lock(&ar->mutex); |
@@ -1962,7 +1964,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1962 | } | 1964 | } |
1963 | 1965 | ||
1964 | ar->vif = conf->vif; | 1966 | ar->vif = conf->vif; |
1965 | memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); | 1967 | memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); |
1966 | 1968 | ||
1967 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1969 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1968 | ar->rx_software_decryption = true; | 1970 | ar->rx_software_decryption = true; |
@@ -2131,12 +2133,13 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2131 | u32 changed) | 2133 | u32 changed) |
2132 | { | 2134 | { |
2133 | struct ar9170 *ar = hw->priv; | 2135 | struct ar9170 *ar = hw->priv; |
2136 | struct ath_common *common = &ar->common; | ||
2134 | int err = 0; | 2137 | int err = 0; |
2135 | 2138 | ||
2136 | mutex_lock(&ar->mutex); | 2139 | mutex_lock(&ar->mutex); |
2137 | 2140 | ||
2138 | if (changed & BSS_CHANGED_BSSID) { | 2141 | if (changed & BSS_CHANGED_BSSID) { |
2139 | memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); | 2142 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
2140 | err = ar9170_set_operating_mode(ar); | 2143 | err = ar9170_set_operating_mode(ar); |
2141 | if (err) | 2144 | if (err) |
2142 | goto out; | 2145 | goto out; |
@@ -2190,22 +2193,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) | |||
2190 | { | 2193 | { |
2191 | struct ar9170 *ar = hw->priv; | 2194 | struct ar9170 *ar = hw->priv; |
2192 | int err; | 2195 | int err; |
2193 | u32 tsf_low; | ||
2194 | u32 tsf_high; | ||
2195 | u64 tsf; | 2196 | u64 tsf; |
2197 | #define NR 3 | ||
2198 | static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, | ||
2199 | AR9170_MAC_REG_TSF_L, | ||
2200 | AR9170_MAC_REG_TSF_H }; | ||
2201 | u32 val[NR]; | ||
2202 | int loops = 0; | ||
2196 | 2203 | ||
2197 | mutex_lock(&ar->mutex); | 2204 | mutex_lock(&ar->mutex); |
2198 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); | 2205 | |
2199 | if (!err) | 2206 | while (loops++ < 10) { |
2200 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); | 2207 | err = ar9170_read_mreg(ar, NR, addr, val); |
2208 | if (err || val[0] == val[2]) | ||
2209 | break; | ||
2210 | } | ||
2211 | |||
2201 | mutex_unlock(&ar->mutex); | 2212 | mutex_unlock(&ar->mutex); |
2202 | 2213 | ||
2203 | if (WARN_ON(err)) | 2214 | if (WARN_ON(err)) |
2204 | return 0; | 2215 | return 0; |
2205 | 2216 | tsf = val[0]; | |
2206 | tsf = tsf_high; | 2217 | tsf = (tsf << 32) | val[1]; |
2207 | tsf = (tsf << 32) | tsf_low; | ||
2208 | return tsf; | 2218 | return tsf; |
2219 | #undef NR | ||
2209 | } | 2220 | } |
2210 | 2221 | ||
2211 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2222 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -2430,6 +2441,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2430 | } | 2441 | } |
2431 | 2442 | ||
2432 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, | 2443 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, |
2444 | struct ieee80211_vif *vif, | ||
2433 | enum ieee80211_ampdu_mlme_action action, | 2445 | enum ieee80211_ampdu_mlme_action action, |
2434 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2446 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2435 | { | 2447 | { |
@@ -2459,7 +2471,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2459 | tid_info->state = AR9170_TID_STATE_PROGRESS; | 2471 | tid_info->state = AR9170_TID_STATE_PROGRESS; |
2460 | tid_info->active = false; | 2472 | tid_info->active = false; |
2461 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2473 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2462 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2474 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2463 | break; | 2475 | break; |
2464 | 2476 | ||
2465 | case IEEE80211_AMPDU_TX_STOP: | 2477 | case IEEE80211_AMPDU_TX_STOP: |
@@ -2469,7 +2481,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2469 | tid_info->active = false; | 2481 | tid_info->active = false; |
2470 | skb_queue_purge(&tid_info->queue); | 2482 | skb_queue_purge(&tid_info->queue); |
2471 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2483 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2472 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2484 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2473 | break; | 2485 | break; |
2474 | 2486 | ||
2475 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 2487 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index dbd488da18b1..45a415ea809a 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c | |||
@@ -1239,9 +1239,6 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1239 | struct ar9170_calctl_edges edges[], | 1239 | struct ar9170_calctl_edges edges[], |
1240 | u32 freq) | 1240 | u32 freq) |
1241 | { | 1241 | { |
1242 | /* TODO: move somewhere else */ | ||
1243 | #define AR5416_MAX_RATE_POWER 63 | ||
1244 | |||
1245 | int i; | 1242 | int i; |
1246 | u8 rc = AR5416_MAX_RATE_POWER; | 1243 | u8 rc = AR5416_MAX_RATE_POWER; |
1247 | u8 f; | 1244 | u8 f; |
@@ -1259,10 +1256,11 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1259 | break; | 1256 | break; |
1260 | } | 1257 | } |
1261 | if (i > 0 && f < edges[i].channel) { | 1258 | if (i > 0 && f < edges[i].channel) { |
1262 | if (f > edges[i-1].channel && | 1259 | if (f > edges[i - 1].channel && |
1263 | edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | 1260 | edges[i - 1].power_flags & |
1261 | AR9170_CALCTL_EDGE_FLAGS) { | ||
1264 | /* lower channel has the inband flag set */ | 1262 | /* lower channel has the inband flag set */ |
1265 | rc = edges[i-1].power_flags & | 1263 | rc = edges[i - 1].power_flags & |
1266 | ~AR9170_CALCTL_EDGE_FLAGS; | 1264 | ~AR9170_CALCTL_EDGE_FLAGS; |
1267 | } | 1265 | } |
1268 | break; | 1266 | break; |
@@ -1270,18 +1268,48 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1270 | } | 1268 | } |
1271 | 1269 | ||
1272 | if (i == AR5416_NUM_BAND_EDGES) { | 1270 | if (i == AR5416_NUM_BAND_EDGES) { |
1273 | if (f > edges[i-1].channel && | 1271 | if (f > edges[i - 1].channel && |
1274 | edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | 1272 | edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { |
1275 | /* lower channel has the inband flag set */ | 1273 | /* lower channel has the inband flag set */ |
1276 | rc = edges[i-1].power_flags & | 1274 | rc = edges[i - 1].power_flags & |
1277 | ~AR9170_CALCTL_EDGE_FLAGS; | 1275 | ~AR9170_CALCTL_EDGE_FLAGS; |
1278 | } | 1276 | } |
1279 | } | 1277 | } |
1280 | return rc; | 1278 | return rc; |
1281 | } | 1279 | } |
1282 | 1280 | ||
1283 | /* calculate the conformance test limits and apply them to ar->power* | 1281 | static u8 ar9170_get_heavy_clip(struct ar9170 *ar, |
1284 | * (derived from otus hal/hpmain.c, line 3706 ff.) | 1282 | struct ar9170_calctl_edges edges[], |
1283 | u32 freq, enum ar9170_bw bw) | ||
1284 | { | ||
1285 | u8 f; | ||
1286 | int i; | ||
1287 | u8 rc = 0; | ||
1288 | |||
1289 | if (freq < 3000) | ||
1290 | f = freq - 2300; | ||
1291 | else | ||
1292 | f = (freq - 4800) / 5; | ||
1293 | |||
1294 | if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) | ||
1295 | rc |= 0xf0; | ||
1296 | |||
1297 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1298 | if (edges[i].channel == 0xff) | ||
1299 | break; | ||
1300 | if (f == edges[i].channel) { | ||
1301 | if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) | ||
1302 | rc |= 0x0f; | ||
1303 | break; | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | return rc; | ||
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * calculate the conformance test limits and the heavy clip parameter | ||
1312 | * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) | ||
1285 | */ | 1313 | */ |
1286 | static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | 1314 | static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) |
1287 | { | 1315 | { |
@@ -1295,7 +1323,8 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1295 | int pwr_cal_len; | 1323 | int pwr_cal_len; |
1296 | } *modes; | 1324 | } *modes; |
1297 | 1325 | ||
1298 | /* order is relevant in the mode_list_*: we fall back to the | 1326 | /* |
1327 | * order is relevant in the mode_list_*: we fall back to the | ||
1299 | * lower indices if any mode is missed in the EEPROM. | 1328 | * lower indices if any mode is missed in the EEPROM. |
1300 | */ | 1329 | */ |
1301 | struct ctl_modes mode_list_2ghz[] = { | 1330 | struct ctl_modes mode_list_2ghz[] = { |
@@ -1313,7 +1342,10 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1313 | 1342 | ||
1314 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) | 1343 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) |
1315 | 1344 | ||
1316 | /* TODO: investigate the differences between OTUS' | 1345 | ar->phy_heavy_clip = 0; |
1346 | |||
1347 | /* | ||
1348 | * TODO: investigate the differences between OTUS' | ||
1317 | * hpreg.c::zfHpGetRegulatoryDomain() and | 1349 | * hpreg.c::zfHpGetRegulatoryDomain() and |
1318 | * ath/regd.c::ath_regd_get_band_ctl() - | 1350 | * ath/regd.c::ath_regd_get_band_ctl() - |
1319 | * e.g. for FCC3_WORLD the OTUS procedure | 1351 | * e.g. for FCC3_WORLD the OTUS procedure |
@@ -1347,6 +1379,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1347 | if (ctl_idx < AR5416_NUM_CTLS) { | 1379 | if (ctl_idx < AR5416_NUM_CTLS) { |
1348 | int f_off = 0; | 1380 | int f_off = 0; |
1349 | 1381 | ||
1382 | /* determine heav clip parameter from | ||
1383 | the 11G edges array */ | ||
1384 | if (modes[i].ctl_mode == CTL_11G) { | ||
1385 | ar->phy_heavy_clip = | ||
1386 | ar9170_get_heavy_clip(ar, | ||
1387 | EDGES(ctl_idx, 1), | ||
1388 | freq, bw); | ||
1389 | } | ||
1390 | |||
1350 | /* adjust freq for 40MHz */ | 1391 | /* adjust freq for 40MHz */ |
1351 | if (modes[i].ctl_mode == CTL_2GHT40 || | 1392 | if (modes[i].ctl_mode == CTL_2GHT40 || |
1352 | modes[i].ctl_mode == CTL_5GHT40) { | 1393 | modes[i].ctl_mode == CTL_5GHT40) { |
@@ -1360,13 +1401,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1360 | ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), | 1401 | ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), |
1361 | freq+f_off); | 1402 | freq+f_off); |
1362 | 1403 | ||
1363 | /* TODO: check if the regulatory max. power is | 1404 | /* |
1405 | * TODO: check if the regulatory max. power is | ||
1364 | * controlled by cfg80211 for DFS | 1406 | * controlled by cfg80211 for DFS |
1365 | * (hpmain applies it to max_power itself for DFS freq) | 1407 | * (hpmain applies it to max_power itself for DFS freq) |
1366 | */ | 1408 | */ |
1367 | 1409 | ||
1368 | } else { | 1410 | } else { |
1369 | /* Workaround in otus driver, hpmain.c, line 3906: | 1411 | /* |
1412 | * Workaround in otus driver, hpmain.c, line 3906: | ||
1370 | * if no data for 5GHT20 are found, take the | 1413 | * if no data for 5GHT20 are found, take the |
1371 | * legacy 5G value. | 1414 | * legacy 5G value. |
1372 | * We extend this here to fallback from any other *HT or | 1415 | * We extend this here to fallback from any other *HT or |
@@ -1390,6 +1433,19 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1390 | modes[i].max_power); | 1433 | modes[i].max_power); |
1391 | } | 1434 | } |
1392 | } | 1435 | } |
1436 | |||
1437 | if (ar->phy_heavy_clip & 0xf0) { | ||
1438 | ar->power_2G_ht40[0]--; | ||
1439 | ar->power_2G_ht40[1]--; | ||
1440 | ar->power_2G_ht40[2]--; | ||
1441 | } | ||
1442 | if (ar->phy_heavy_clip & 0xf) { | ||
1443 | ar->power_2G_ht20[0]++; | ||
1444 | ar->power_2G_ht20[1]++; | ||
1445 | ar->power_2G_ht20[2]++; | ||
1446 | } | ||
1447 | |||
1448 | |||
1393 | #undef EDGES | 1449 | #undef EDGES |
1394 | } | 1450 | } |
1395 | 1451 | ||
@@ -1499,8 +1555,6 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1499 | /* calc. conformance test limits and apply to ar->power*[] */ | 1555 | /* calc. conformance test limits and apply to ar->power*[] */ |
1500 | ar9170_calc_ctl(ar, freq, bw); | 1556 | ar9170_calc_ctl(ar, freq, bw); |
1501 | 1557 | ||
1502 | /* TODO: (heavy clip) regulatory domain power level fine-tuning. */ | ||
1503 | |||
1504 | /* set ACK/CTS TX power */ | 1558 | /* set ACK/CTS TX power */ |
1505 | ar9170_regwrite_begin(ar); | 1559 | ar9170_regwrite_begin(ar); |
1506 | 1560 | ||
@@ -1643,6 +1697,17 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1643 | if (err) | 1697 | if (err) |
1644 | return err; | 1698 | return err; |
1645 | 1699 | ||
1700 | if (ar->phy_heavy_clip) { | ||
1701 | err = ar9170_write_reg(ar, 0x1c59e0, | ||
1702 | 0x200 | ar->phy_heavy_clip); | ||
1703 | if (err) { | ||
1704 | if (ar9170_nag_limiter(ar)) | ||
1705 | printk(KERN_ERR "%s: failed to set " | ||
1706 | "heavy clip\n", | ||
1707 | wiphy_name(ar->hw->wiphy)); | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1646 | for (i = 0; i < 2; i++) { | 1711 | for (i = 0; i < 2; i++) { |
1647 | ar->noise[i] = ar9170_calc_noise_dbm( | 1712 | ar->noise[i] = ar9170_calc_noise_dbm( |
1648 | (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); | 1713 | (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..e0799d924057 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -68,8 +68,10 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
68 | { USB_DEVICE(0x0cf3, 0x1002) }, | 68 | { USB_DEVICE(0x0cf3, 0x1002) }, |
69 | /* Cace Airpcap NX */ | 69 | /* Cace Airpcap NX */ |
70 | { USB_DEVICE(0xcace, 0x0300) }, | 70 | { USB_DEVICE(0xcace, 0x0300) }, |
71 | /* D-Link DWA 160A */ | 71 | /* D-Link DWA 160 A1 */ |
72 | { USB_DEVICE(0x07d1, 0x3c10) }, | 72 | { USB_DEVICE(0x07d1, 0x3c10) }, |
73 | /* D-Link DWA 160 A2 */ | ||
74 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
73 | /* Netgear WNDA3100 */ | 75 | /* Netgear WNDA3100 */ |
74 | { USB_DEVICE(0x0846, 0x9010) }, | 76 | { USB_DEVICE(0x0846, 0x9010) }, |
75 | /* Netgear WN111 v2 */ | 77 | /* Netgear WN111 v2 */ |
@@ -108,15 +110,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
108 | return ; | 110 | return ; |
109 | 111 | ||
110 | spin_lock_irqsave(&aru->tx_urb_lock, flags); | 112 | spin_lock_irqsave(&aru->tx_urb_lock, flags); |
111 | if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { | 113 | if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { |
112 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 114 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
113 | return ; | 115 | return ; |
114 | } | 116 | } |
115 | aru->tx_submitted_urbs++; | 117 | atomic_inc(&aru->tx_submitted_urbs); |
116 | 118 | ||
117 | urb = usb_get_from_anchor(&aru->tx_pending); | 119 | urb = usb_get_from_anchor(&aru->tx_pending); |
118 | if (!urb) { | 120 | if (!urb) { |
119 | aru->tx_submitted_urbs--; | 121 | atomic_dec(&aru->tx_submitted_urbs); |
120 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 122 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
121 | 123 | ||
122 | return ; | 124 | return ; |
@@ -133,7 +135,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
133 | err); | 135 | err); |
134 | 136 | ||
135 | usb_unanchor_urb(urb); | 137 | usb_unanchor_urb(urb); |
136 | aru->tx_submitted_urbs--; | 138 | atomic_dec(&aru->tx_submitted_urbs); |
137 | ar9170_tx_callback(&aru->common, urb->context); | 139 | ar9170_tx_callback(&aru->common, urb->context); |
138 | } | 140 | } |
139 | 141 | ||
@@ -151,7 +153,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) | |||
151 | return ; | 153 | return ; |
152 | } | 154 | } |
153 | 155 | ||
154 | aru->tx_submitted_urbs--; | 156 | atomic_dec(&aru->tx_submitted_urbs); |
155 | 157 | ||
156 | ar9170_tx_callback(&aru->common, skb); | 158 | ar9170_tx_callback(&aru->common, skb); |
157 | 159 | ||
@@ -794,7 +796,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
794 | spin_lock_init(&aru->tx_urb_lock); | 796 | spin_lock_init(&aru->tx_urb_lock); |
795 | 797 | ||
796 | aru->tx_pending_urbs = 0; | 798 | aru->tx_pending_urbs = 0; |
797 | aru->tx_submitted_urbs = 0; | 799 | atomic_set(&aru->tx_submitted_urbs, 0); |
798 | 800 | ||
799 | aru->common.stop = ar9170_usb_stop; | 801 | aru->common.stop = ar9170_usb_stop; |
800 | aru->common.flush = ar9170_usb_flush; | 802 | aru->common.flush = ar9170_usb_flush; |
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index d098f4d5d2f2..a2ce3b169ceb 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h | |||
@@ -67,7 +67,7 @@ struct ar9170_usb { | |||
67 | bool req_one_stage_fw; | 67 | bool req_one_stage_fw; |
68 | 68 | ||
69 | spinlock_t tx_urb_lock; | 69 | spinlock_t tx_urb_lock; |
70 | unsigned int tx_submitted_urbs; | 70 | atomic_t tx_submitted_urbs; |
71 | unsigned int tx_pending_urbs; | 71 | unsigned int tx_pending_urbs; |
72 | 72 | ||
73 | struct completion cmd_wait; | 73 | struct completion cmd_wait; |