aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ar9170
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ar9170')
-rw-r--r--drivers/net/wireless/ath/ar9170/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ar9170/ar9170.h6
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.c3
-rw-r--r--drivers/net/wireless/ath/ar9170/cmd.h1
-rw-r--r--drivers/net/wireless/ath/ar9170/hw.h6
-rw-r--r--drivers/net/wireless/ath/ar9170/mac.c15
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c50
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c99
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c16
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.h2
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 @@
1config AR9170_USB 1config 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
75static int ar9170_read_mreg(struct ar9170 *ar, int nregs, 75int 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 @@
44int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); 44int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len);
45int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); 45int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val);
46int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); 46int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val);
47int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out);
47int ar9170_echo_test(struct ar9170 *ar, u32 v); 48int 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
314struct ar9170_rx_head { 316struct 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
312int ar9170_set_operating_mode(struct ar9170 *ar) 312int 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
2211static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 2222static 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
2432static int ar9170_ampdu_action(struct ieee80211_hw *hw, 2443static 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* 1281static 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 */
1286static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) 1314static 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;