diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hif_usb.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 64 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_hst.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 27 |
17 files changed, 184 insertions, 188 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index f2eec388693b..73a8014cacb2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -57,10 +57,11 @@ | |||
57 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ | 57 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ |
58 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ | 58 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ |
59 | 59 | ||
60 | #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6)) | ||
61 | |||
60 | static int ar9003_hw_power_interpolate(int32_t x, | 62 | static int ar9003_hw_power_interpolate(int32_t x, |
61 | int32_t *px, int32_t *py, u_int16_t np); | 63 | int32_t *px, int32_t *py, u_int16_t np); |
62 | 64 | ||
63 | #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6)) | ||
64 | 65 | ||
65 | static const struct ar9300_eeprom ar9300_default = { | 66 | static const struct ar9300_eeprom ar9300_default = { |
66 | .eepromVersion = 2, | 67 | .eepromVersion = 2, |
@@ -3032,6 +3033,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
3032 | return le32_to_cpu(pBase->swreg); | 3033 | return le32_to_cpu(pBase->swreg); |
3033 | case EEP_PAPRD: | 3034 | case EEP_PAPRD: |
3034 | return !!(pBase->featureEnable & BIT(5)); | 3035 | return !!(pBase->featureEnable & BIT(5)); |
3036 | case EEP_CHAIN_MASK_REDUCE: | ||
3037 | return (pBase->miscConfiguration >> 0x3) & 0x1; | ||
3035 | default: | 3038 | default: |
3036 | return 0; | 3039 | return 0; |
3037 | } | 3040 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 656d8ce251a7..b34a9e91edd8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -487,7 +487,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | |||
487 | break; | 487 | break; |
488 | } | 488 | } |
489 | 489 | ||
490 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | 490 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
491 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | ||
492 | else | ||
493 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | ||
494 | |||
491 | if (tx == 0x5) { | 495 | if (tx == 0x5) { |
492 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 496 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
493 | AR_PHY_SWAP_ALT_CHAIN); | 497 | AR_PHY_SWAP_ALT_CHAIN); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0b4b4704b1f0..4210a9306955 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -545,6 +545,7 @@ struct ath_ant_comb { | |||
545 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) | 545 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
546 | #define SC_OP_BT_SCAN BIT(13) | 546 | #define SC_OP_BT_SCAN BIT(13) |
547 | #define SC_OP_ANI_RUN BIT(14) | 547 | #define SC_OP_ANI_RUN BIT(14) |
548 | #define SC_OP_ENABLE_APM BIT(15) | ||
548 | 549 | ||
549 | /* Powersave flags */ | 550 | /* Powersave flags */ |
550 | #define PS_WAIT_FOR_BEACON BIT(0) | 551 | #define PS_WAIT_FOR_BEACON BIT(0) |
@@ -697,6 +698,8 @@ static inline void ath_ahb_exit(void) {}; | |||
697 | void ath9k_ps_wakeup(struct ath_softc *sc); | 698 | void ath9k_ps_wakeup(struct ath_softc *sc); |
698 | void ath9k_ps_restore(struct ath_softc *sc); | 699 | void ath9k_ps_restore(struct ath_softc *sc); |
699 | 700 | ||
701 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); | ||
702 | |||
700 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 703 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
701 | int ath9k_wiphy_add(struct ath_softc *sc); | 704 | int ath9k_wiphy_add(struct ath_softc *sc); |
702 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | 705 | int ath9k_wiphy_del(struct ath_wiphy *aphy); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 30724a4e8bb2..47bedd82e9a9 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -103,7 +103,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
103 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 103 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
104 | series[0].Tries = 1; | 104 | series[0].Tries = 1; |
105 | series[0].Rate = rate; | 105 | series[0].Rate = rate; |
106 | series[0].ChSel = common->tx_chainmask; | 106 | series[0].ChSel = ath_txchainmask_reduction(sc, |
107 | common->tx_chainmask, series[0].Rate); | ||
107 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | 108 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; |
108 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, | 109 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, |
109 | series, 4, 0); | 110 | series, 4, 0); |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 6a92e57fddf0..d33bf204c995 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -35,29 +35,6 @@ struct ath_btcoex_config { | |||
35 | bool bt_hold_rx_clear; | 35 | bool bt_hold_rx_clear; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static const u16 ath_subsysid_tbl[] = { | ||
39 | AR9280_COEX2WIRE_SUBSYSID, | ||
40 | AT9285_COEX3WIRE_SA_SUBSYSID, | ||
41 | AT9285_COEX3WIRE_DA_SUBSYSID | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * Checks the subsystem id of the device to see if it | ||
46 | * supports btcoex | ||
47 | */ | ||
48 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | if (!ah->hw_version.subsysid) | ||
53 | return false; | ||
54 | |||
55 | for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) | ||
56 | if (ah->hw_version.subsysid == ath_subsysid_tbl[i]) | ||
57 | return true; | ||
58 | |||
59 | return false; | ||
60 | } | ||
61 | 38 | ||
62 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | 39 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) |
63 | { | 40 | { |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 1ee5a15ccbb1..588dfd464dd1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -49,7 +49,6 @@ struct ath_btcoex_hw { | |||
49 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | 49 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
50 | }; | 50 | }; |
51 | 51 | ||
52 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah); | ||
53 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); | 52 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); |
54 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); | 53 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); |
55 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); | 54 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 0c3c74c157fb..3586c43077a7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #define REG_READ_D(_ah, _reg) \ | 24 | #define REG_READ_D(_ah, _reg) \ |
25 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | 25 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) |
26 | 26 | ||
27 | static struct dentry *ath9k_debugfs_root; | ||
28 | |||
29 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | 27 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) |
30 | { | 28 | { |
31 | file->private_data = inode->i_private; | 29 | file->private_data = inode->i_private; |
@@ -878,11 +876,8 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
878 | struct ath_common *common = ath9k_hw_common(ah); | 876 | struct ath_common *common = ath9k_hw_common(ah); |
879 | struct ath_softc *sc = (struct ath_softc *) common->priv; | 877 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
880 | 878 | ||
881 | if (!ath9k_debugfs_root) | 879 | sc->debug.debugfs_phy = debugfs_create_dir("ath9k", |
882 | return -ENOENT; | 880 | sc->hw->wiphy->debugfsdir); |
883 | |||
884 | sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | ||
885 | ath9k_debugfs_root); | ||
886 | if (!sc->debug.debugfs_phy) | 881 | if (!sc->debug.debugfs_phy) |
887 | return -ENOMEM; | 882 | return -ENOMEM; |
888 | 883 | ||
@@ -935,29 +930,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
935 | sc->debug.regidx = 0; | 930 | sc->debug.regidx = 0; |
936 | return 0; | 931 | return 0; |
937 | err: | 932 | err: |
938 | ath9k_exit_debug(ah); | ||
939 | return -ENOMEM; | ||
940 | } | ||
941 | |||
942 | void ath9k_exit_debug(struct ath_hw *ah) | ||
943 | { | ||
944 | struct ath_common *common = ath9k_hw_common(ah); | ||
945 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
946 | |||
947 | debugfs_remove_recursive(sc->debug.debugfs_phy); | 933 | debugfs_remove_recursive(sc->debug.debugfs_phy); |
948 | } | 934 | sc->debug.debugfs_phy = NULL; |
949 | 935 | return -ENOMEM; | |
950 | int ath9k_debug_create_root(void) | ||
951 | { | ||
952 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
953 | if (!ath9k_debugfs_root) | ||
954 | return -ENOENT; | ||
955 | |||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | void ath9k_debug_remove_root(void) | ||
960 | { | ||
961 | debugfs_remove(ath9k_debugfs_root); | ||
962 | ath9k_debugfs_root = NULL; | ||
963 | } | 936 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 646ff7e04c88..1e5078bd0344 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -164,10 +164,7 @@ struct ath9k_debug { | |||
164 | }; | 164 | }; |
165 | 165 | ||
166 | int ath9k_init_debug(struct ath_hw *ah); | 166 | int ath9k_init_debug(struct ath_hw *ah); |
167 | void ath9k_exit_debug(struct ath_hw *ah); | ||
168 | 167 | ||
169 | int ath9k_debug_create_root(void); | ||
170 | void ath9k_debug_remove_root(void); | ||
171 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 168 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
172 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | 169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, |
173 | struct ath_tx_status *ts); | 170 | struct ath_tx_status *ts); |
@@ -180,19 +177,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah) | |||
180 | return 0; | 177 | return 0; |
181 | } | 178 | } |
182 | 179 | ||
183 | static inline void ath9k_exit_debug(struct ath_hw *ah) | ||
184 | { | ||
185 | } | ||
186 | |||
187 | static inline int ath9k_debug_create_root(void) | ||
188 | { | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static inline void ath9k_debug_remove_root(void) | ||
193 | { | ||
194 | } | ||
195 | |||
196 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | 180 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, |
197 | enum ath9k_int status) | 181 | enum ath9k_int status) |
198 | { | 182 | { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 8a644fced5c9..8b9885b5243f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -280,6 +280,7 @@ enum eeprom_param { | |||
280 | EEP_PAPRD, | 280 | EEP_PAPRD, |
281 | EEP_MODAL_VER, | 281 | EEP_MODAL_VER, |
282 | EEP_ANT_DIV_CTL1, | 282 | EEP_ANT_DIV_CTL1, |
283 | EEP_CHAIN_MASK_REDUCE | ||
283 | }; | 284 | }; |
284 | 285 | ||
285 | enum ar5416_rates { | 286 | enum ar5416_rates { |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index ae842dbf9b50..8946e8ad1b85 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -363,9 +363,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
363 | struct sk_buff *skb) | 363 | struct sk_buff *skb) |
364 | { | 364 | { |
365 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; | 365 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; |
366 | int index = 0, i = 0, chk_idx, len = skb->len; | 366 | int index = 0, i = 0, len = skb->len; |
367 | int rx_remain_len = 0, rx_pkt_len = 0; | 367 | int rx_remain_len, rx_pkt_len; |
368 | u16 pkt_len, pkt_tag, pool_index = 0; | 368 | u16 pool_index = 0; |
369 | u8 *ptr; | 369 | u8 *ptr; |
370 | 370 | ||
371 | spin_lock(&hif_dev->rx_lock); | 371 | spin_lock(&hif_dev->rx_lock); |
@@ -399,64 +399,64 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
399 | spin_unlock(&hif_dev->rx_lock); | 399 | spin_unlock(&hif_dev->rx_lock); |
400 | 400 | ||
401 | while (index < len) { | 401 | while (index < len) { |
402 | u16 pkt_len; | ||
403 | u16 pkt_tag; | ||
404 | u16 pad_len; | ||
405 | int chk_idx; | ||
406 | |||
402 | ptr = (u8 *) skb->data; | 407 | ptr = (u8 *) skb->data; |
403 | 408 | ||
404 | pkt_len = ptr[index] + (ptr[index+1] << 8); | 409 | pkt_len = ptr[index] + (ptr[index+1] << 8); |
405 | pkt_tag = ptr[index+2] + (ptr[index+3] << 8); | 410 | pkt_tag = ptr[index+2] + (ptr[index+3] << 8); |
406 | 411 | ||
407 | if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { | 412 | if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { |
408 | u16 pad_len; | 413 | RX_STAT_INC(skb_dropped); |
409 | 414 | return; | |
410 | pad_len = 4 - (pkt_len & 0x3); | 415 | } |
411 | if (pad_len == 4) | 416 | |
412 | pad_len = 0; | 417 | pad_len = 4 - (pkt_len & 0x3); |
413 | 418 | if (pad_len == 4) | |
414 | chk_idx = index; | 419 | pad_len = 0; |
415 | index = index + 4 + pkt_len + pad_len; | 420 | |
416 | 421 | chk_idx = index; | |
417 | if (index > MAX_RX_BUF_SIZE) { | 422 | index = index + 4 + pkt_len + pad_len; |
418 | spin_lock(&hif_dev->rx_lock); | 423 | |
419 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; | 424 | if (index > MAX_RX_BUF_SIZE) { |
420 | hif_dev->rx_transfer_len = | 425 | spin_lock(&hif_dev->rx_lock); |
421 | MAX_RX_BUF_SIZE - chk_idx - 4; | 426 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; |
422 | hif_dev->rx_pad_len = pad_len; | 427 | hif_dev->rx_transfer_len = |
423 | 428 | MAX_RX_BUF_SIZE - chk_idx - 4; | |
424 | nskb = __dev_alloc_skb(pkt_len + 32, | 429 | hif_dev->rx_pad_len = pad_len; |
425 | GFP_ATOMIC); | 430 | |
426 | if (!nskb) { | 431 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
427 | dev_err(&hif_dev->udev->dev, | 432 | if (!nskb) { |
428 | "ath9k_htc: RX memory allocation" | 433 | dev_err(&hif_dev->udev->dev, |
429 | " error\n"); | 434 | "ath9k_htc: RX memory allocation error\n"); |
430 | spin_unlock(&hif_dev->rx_lock); | ||
431 | goto err; | ||
432 | } | ||
433 | skb_reserve(nskb, 32); | ||
434 | RX_STAT_INC(skb_allocated); | ||
435 | |||
436 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | ||
437 | hif_dev->rx_transfer_len); | ||
438 | |||
439 | /* Record the buffer pointer */ | ||
440 | hif_dev->remain_skb = nskb; | ||
441 | spin_unlock(&hif_dev->rx_lock); | 435 | spin_unlock(&hif_dev->rx_lock); |
442 | } else { | 436 | goto err; |
443 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); | ||
444 | if (!nskb) { | ||
445 | dev_err(&hif_dev->udev->dev, | ||
446 | "ath9k_htc: RX memory allocation" | ||
447 | " error\n"); | ||
448 | goto err; | ||
449 | } | ||
450 | skb_reserve(nskb, 32); | ||
451 | RX_STAT_INC(skb_allocated); | ||
452 | |||
453 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | ||
454 | skb_put(nskb, pkt_len); | ||
455 | skb_pool[pool_index++] = nskb; | ||
456 | } | 437 | } |
438 | skb_reserve(nskb, 32); | ||
439 | RX_STAT_INC(skb_allocated); | ||
440 | |||
441 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | ||
442 | hif_dev->rx_transfer_len); | ||
443 | |||
444 | /* Record the buffer pointer */ | ||
445 | hif_dev->remain_skb = nskb; | ||
446 | spin_unlock(&hif_dev->rx_lock); | ||
457 | } else { | 447 | } else { |
458 | RX_STAT_INC(skb_dropped); | 448 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
459 | return; | 449 | if (!nskb) { |
450 | dev_err(&hif_dev->udev->dev, | ||
451 | "ath9k_htc: RX memory allocation error\n"); | ||
452 | goto err; | ||
453 | } | ||
454 | skb_reserve(nskb, 32); | ||
455 | RX_STAT_INC(skb_allocated); | ||
456 | |||
457 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | ||
458 | skb_put(nskb, pkt_len); | ||
459 | skb_pool[pool_index++] = nskb; | ||
460 | } | 460 | } |
461 | } | 461 | } |
462 | 462 | ||
@@ -471,7 +471,7 @@ err: | |||
471 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | 471 | static void ath9k_hif_usb_rx_cb(struct urb *urb) |
472 | { | 472 | { |
473 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 473 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
474 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | 474 | struct hif_device_usb *hif_dev = |
475 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 475 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
476 | int ret; | 476 | int ret; |
477 | 477 | ||
@@ -518,7 +518,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
518 | { | 518 | { |
519 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 519 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
520 | struct sk_buff *nskb; | 520 | struct sk_buff *nskb; |
521 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | 521 | struct hif_device_usb *hif_dev = |
522 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 522 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
523 | int ret; | 523 | int ret; |
524 | 524 | ||
@@ -993,8 +993,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) | |||
993 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | 993 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) |
994 | { | 994 | { |
995 | struct usb_device *udev = interface_to_usbdev(interface); | 995 | struct usb_device *udev = interface_to_usbdev(interface); |
996 | struct hif_device_usb *hif_dev = | 996 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
997 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
998 | 997 | ||
999 | if (hif_dev) { | 998 | if (hif_dev) { |
1000 | ath9k_htc_hw_deinit(hif_dev->htc_handle, | 999 | ath9k_htc_hw_deinit(hif_dev->htc_handle, |
@@ -1016,8 +1015,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | |||
1016 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, | 1015 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, |
1017 | pm_message_t message) | 1016 | pm_message_t message) |
1018 | { | 1017 | { |
1019 | struct hif_device_usb *hif_dev = | 1018 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
1020 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
1021 | 1019 | ||
1022 | ath9k_hif_usb_dealloc_urbs(hif_dev); | 1020 | ath9k_hif_usb_dealloc_urbs(hif_dev); |
1023 | 1021 | ||
@@ -1026,8 +1024,7 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, | |||
1026 | 1024 | ||
1027 | static int ath9k_hif_usb_resume(struct usb_interface *interface) | 1025 | static int ath9k_hif_usb_resume(struct usb_interface *interface) |
1028 | { | 1026 | { |
1029 | struct hif_device_usb *hif_dev = | 1027 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
1030 | (struct hif_device_usb *) usb_get_intfdata(interface); | ||
1031 | struct htc_target *htc_handle = hif_dev->htc_handle; | 1028 | struct htc_target *htc_handle = hif_dev->htc_handle; |
1032 | int ret; | 1029 | int ret; |
1033 | 1030 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e9761c2c8700..8266ce1f02e3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -184,6 +184,47 @@ err: | |||
184 | return ret; | 184 | return ret; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | ||
188 | { | ||
189 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
190 | struct ath9k_htc_target_vif hvif; | ||
191 | int ret = 0; | ||
192 | u8 cmd_rsp; | ||
193 | |||
194 | if (priv->nvifs > 0) | ||
195 | return -ENOBUFS; | ||
196 | |||
197 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
198 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | ||
199 | |||
200 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | ||
201 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | ||
202 | hvif.index = priv->nvifs; | ||
203 | |||
204 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | ||
205 | if (ret) | ||
206 | return ret; | ||
207 | |||
208 | priv->nvifs++; | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | ||
213 | { | ||
214 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
215 | struct ath9k_htc_target_vif hvif; | ||
216 | int ret = 0; | ||
217 | u8 cmd_rsp; | ||
218 | |||
219 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | ||
220 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | ||
221 | hvif.index = 0; /* Should do for now */ | ||
222 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
223 | priv->nvifs--; | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
187 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | 228 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, |
188 | struct ieee80211_vif *vif, | 229 | struct ieee80211_vif *vif, |
189 | struct ieee80211_sta *sta) | 230 | struct ieee80211_sta *sta) |
@@ -1199,6 +1240,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1199 | WMI_CMD(WMI_STOP_RECV_CMDID); | 1240 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1200 | skb_queue_purge(&priv->tx_queue); | 1241 | skb_queue_purge(&priv->tx_queue); |
1201 | 1242 | ||
1243 | /* Remove monitor interface here */ | ||
1244 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
1245 | if (ath9k_htc_remove_monitor_interface(priv)) | ||
1246 | ath_print(common, ATH_DBG_FATAL, | ||
1247 | "Unable to remove monitor interface\n"); | ||
1248 | else | ||
1249 | ath_print(common, ATH_DBG_CONFIG, | ||
1250 | "Monitor interface removed\n"); | ||
1251 | } | ||
1252 | |||
1202 | if (ah->btcoex_hw.enabled) { | 1253 | if (ah->btcoex_hw.enabled) { |
1203 | ath9k_hw_btcoex_disable(ah); | 1254 | ath9k_hw_btcoex_disable(ah); |
1204 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 1255 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
@@ -1372,13 +1423,16 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1372 | } | 1423 | } |
1373 | } | 1424 | } |
1374 | 1425 | ||
1375 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) | 1426 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
1376 | if (conf->flags & IEEE80211_CONF_MONITOR) { | 1427 | if (conf->flags & IEEE80211_CONF_MONITOR) { |
1377 | ath_print(common, ATH_DBG_CONFIG, | 1428 | if (ath9k_htc_add_monitor_interface(priv)) |
1378 | "HW opmode set to Monitor mode\n"); | 1429 | ath_print(common, ATH_DBG_FATAL, |
1379 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | 1430 | "Failed to set monitor mode\n"); |
1431 | else | ||
1432 | ath_print(common, ATH_DBG_CONFIG, | ||
1433 | "HW opmode set to Monitor mode\n"); | ||
1380 | } | 1434 | } |
1381 | 1435 | } | |
1382 | 1436 | ||
1383 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1437 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1384 | mutex_lock(&priv->htc_pm_lock); | 1438 | mutex_lock(&priv->htc_pm_lock); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index 6fc1b21faa5d..ecd018798c47 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -77,20 +77,6 @@ struct htc_config_pipe_msg { | |||
77 | u8 credits; | 77 | u8 credits; |
78 | } __packed; | 78 | } __packed; |
79 | 79 | ||
80 | struct htc_packet { | ||
81 | void *pktcontext; | ||
82 | u8 *buf; | ||
83 | u8 *buf_payload; | ||
84 | u32 buflen; | ||
85 | u32 payload_len; | ||
86 | |||
87 | int endpoint; | ||
88 | int status; | ||
89 | |||
90 | void *context; | ||
91 | u32 reserved; | ||
92 | }; | ||
93 | |||
94 | struct htc_ep_callbacks { | 80 | struct htc_ep_callbacks { |
95 | void *priv; | 81 | void *priv; |
96 | void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); | 82 | void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); |
@@ -123,11 +109,6 @@ struct htc_endpoint { | |||
123 | #define HTC_CONTROL_BUFFER_SIZE \ | 109 | #define HTC_CONTROL_BUFFER_SIZE \ |
124 | (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) | 110 | (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) |
125 | 111 | ||
126 | struct htc_control_buf { | ||
127 | struct htc_packet htc_pkt; | ||
128 | u8 buf[HTC_CONTROL_BUFFER_SIZE]; | ||
129 | }; | ||
130 | |||
131 | #define HTC_OP_START_WAIT BIT(0) | 112 | #define HTC_OP_START_WAIT BIT(0) |
132 | #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) | 113 | #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) |
133 | 114 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 380d0c651137..9b1ee7fc05c1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1925,8 +1925,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
1925 | pCap->num_antcfg_2ghz = | 1925 | pCap->num_antcfg_2ghz = |
1926 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); | 1926 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); |
1927 | 1927 | ||
1928 | if (AR_SREV_9280_20_OR_LATER(ah) && | 1928 | if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) { |
1929 | ath9k_hw_btcoex_supported(ah)) { | ||
1930 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; | 1929 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; |
1931 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; | 1930 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; |
1932 | 1931 | ||
@@ -1975,6 +1974,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
1975 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | 1974 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) |
1976 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | 1975 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; |
1977 | } | 1976 | } |
1977 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
1978 | if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) | ||
1979 | pCap->hw_caps |= ATH9K_HW_CAP_APM; | ||
1980 | } | ||
1981 | |||
1982 | |||
1978 | 1983 | ||
1979 | return 0; | 1984 | return 0; |
1980 | } | 1985 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index cc8f3b9af71f..5fcfa48a45df 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -187,6 +187,7 @@ enum ath9k_hw_caps { | |||
187 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), | 187 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), |
188 | ATH9K_HW_CAP_2GHZ = BIT(13), | 188 | ATH9K_HW_CAP_2GHZ = BIT(13), |
189 | ATH9K_HW_CAP_5GHZ = BIT(14), | 189 | ATH9K_HW_CAP_5GHZ = BIT(14), |
190 | ATH9K_HW_CAP_APM = BIT(15), | ||
190 | }; | 191 | }; |
191 | 192 | ||
192 | struct ath9k_hw_capabilities { | 193 | struct ath9k_hw_capabilities { |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 84e19e504dd0..918308a28410 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -37,6 +37,10 @@ int led_blink; | |||
37 | module_param_named(blink, led_blink, int, 0444); | 37 | module_param_named(blink, led_blink, int, 0444); |
38 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 38 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
39 | 39 | ||
40 | static int ath9k_btcoex_enable; | ||
41 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); | ||
42 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); | ||
43 | |||
40 | /* We use the hw_value as an index into our private channel structure */ | 44 | /* We use the hw_value as an index into our private channel structure */ |
41 | 45 | ||
42 | #define CHAN2G(_freq, _idx) { \ | 46 | #define CHAN2G(_freq, _idx) { \ |
@@ -540,6 +544,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
540 | common->hw = sc->hw; | 544 | common->hw = sc->hw; |
541 | common->priv = sc; | 545 | common->priv = sc; |
542 | common->debug_mask = ath9k_debug; | 546 | common->debug_mask = ath9k_debug; |
547 | common->btcoex_enabled = ath9k_btcoex_enable == 1; | ||
543 | spin_lock_init(&common->cc_lock); | 548 | spin_lock_init(&common->cc_lock); |
544 | 549 | ||
545 | spin_lock_init(&sc->wiphy_lock); | 550 | spin_lock_init(&sc->wiphy_lock); |
@@ -562,13 +567,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
562 | if (ret) | 567 | if (ret) |
563 | goto err_hw; | 568 | goto err_hw; |
564 | 569 | ||
565 | ret = ath9k_init_debug(ah); | ||
566 | if (ret) { | ||
567 | ath_print(common, ATH_DBG_FATAL, | ||
568 | "Unable to create debugfs files\n"); | ||
569 | goto err_debug; | ||
570 | } | ||
571 | |||
572 | ret = ath9k_init_queues(sc); | 570 | ret = ath9k_init_queues(sc); |
573 | if (ret) | 571 | if (ret) |
574 | goto err_queues; | 572 | goto err_queues; |
@@ -591,8 +589,6 @@ err_btcoex: | |||
591 | if (ATH_TXQ_SETUP(sc, i)) | 589 | if (ATH_TXQ_SETUP(sc, i)) |
592 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 590 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
593 | err_queues: | 591 | err_queues: |
594 | ath9k_exit_debug(ah); | ||
595 | err_debug: | ||
596 | ath9k_hw_deinit(ah); | 592 | ath9k_hw_deinit(ah); |
597 | err_hw: | 593 | err_hw: |
598 | tasklet_kill(&sc->intr_tq); | 594 | tasklet_kill(&sc->intr_tq); |
@@ -738,6 +734,13 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
738 | if (error) | 734 | if (error) |
739 | goto error_register; | 735 | goto error_register; |
740 | 736 | ||
737 | error = ath9k_init_debug(ah); | ||
738 | if (error) { | ||
739 | ath_print(common, ATH_DBG_FATAL, | ||
740 | "Unable to create debugfs files\n"); | ||
741 | goto error_world; | ||
742 | } | ||
743 | |||
741 | /* Handle world regulatory */ | 744 | /* Handle world regulatory */ |
742 | if (!ath_is_world_regd(reg)) { | 745 | if (!ath_is_world_regd(reg)) { |
743 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 746 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
@@ -796,7 +799,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
796 | if (ATH_TXQ_SETUP(sc, i)) | 799 | if (ATH_TXQ_SETUP(sc, i)) |
797 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 800 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
798 | 801 | ||
799 | ath9k_exit_debug(sc->sc_ah); | ||
800 | ath9k_hw_deinit(sc->sc_ah); | 802 | ath9k_hw_deinit(sc->sc_ah); |
801 | 803 | ||
802 | tasklet_kill(&sc->intr_tq); | 804 | tasklet_kill(&sc->intr_tq); |
@@ -863,20 +865,12 @@ static int __init ath9k_init(void) | |||
863 | goto err_out; | 865 | goto err_out; |
864 | } | 866 | } |
865 | 867 | ||
866 | error = ath9k_debug_create_root(); | ||
867 | if (error) { | ||
868 | printk(KERN_ERR | ||
869 | "ath9k: Unable to create debugfs root: %d\n", | ||
870 | error); | ||
871 | goto err_rate_unregister; | ||
872 | } | ||
873 | |||
874 | error = ath_pci_init(); | 868 | error = ath_pci_init(); |
875 | if (error < 0) { | 869 | if (error < 0) { |
876 | printk(KERN_ERR | 870 | printk(KERN_ERR |
877 | "ath9k: No PCI devices found, driver not installed.\n"); | 871 | "ath9k: No PCI devices found, driver not installed.\n"); |
878 | error = -ENODEV; | 872 | error = -ENODEV; |
879 | goto err_remove_root; | 873 | goto err_rate_unregister; |
880 | } | 874 | } |
881 | 875 | ||
882 | error = ath_ahb_init(); | 876 | error = ath_ahb_init(); |
@@ -890,8 +884,6 @@ static int __init ath9k_init(void) | |||
890 | err_pci_exit: | 884 | err_pci_exit: |
891 | ath_pci_exit(); | 885 | ath_pci_exit(); |
892 | 886 | ||
893 | err_remove_root: | ||
894 | ath9k_debug_remove_root(); | ||
895 | err_rate_unregister: | 887 | err_rate_unregister: |
896 | ath_rate_control_unregister(); | 888 | ath_rate_control_unregister(); |
897 | err_out: | 889 | err_out: |
@@ -903,7 +895,6 @@ static void __exit ath9k_exit(void) | |||
903 | { | 895 | { |
904 | ath_ahb_exit(); | 896 | ath_ahb_exit(); |
905 | ath_pci_exit(); | 897 | ath_pci_exit(); |
906 | ath9k_debug_remove_root(); | ||
907 | ath_rate_control_unregister(); | 898 | ath_rate_control_unregister(); |
908 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | 899 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); |
909 | } | 900 | } |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 7acd6b0ca011..f026a031713b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -553,9 +553,12 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
553 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | 553 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) |
554 | { | 554 | { |
555 | struct ath_node *an; | 555 | struct ath_node *an; |
556 | 556 | struct ath_hw *ah = sc->sc_ah; | |
557 | an = (struct ath_node *)sta->drv_priv; | 557 | an = (struct ath_node *)sta->drv_priv; |
558 | 558 | ||
559 | if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) | ||
560 | sc->sc_flags |= SC_OP_ENABLE_APM; | ||
561 | |||
559 | if (sc->sc_flags & SC_OP_TXAGGR) { | 562 | if (sc->sc_flags & SC_OP_TXAGGR) { |
560 | ath_tx_node_init(sc, an); | 563 | ath_tx_node_init(sc, an); |
561 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 564 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 495432ec85a9..821d3679c6ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -250,11 +250,11 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
250 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 250 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
251 | struct sk_buff *skb) | 251 | struct sk_buff *skb) |
252 | { | 252 | { |
253 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 253 | struct ath_frame_info *fi = get_frame_info(skb); |
254 | struct ieee80211_hdr *hdr; | 254 | struct ieee80211_hdr *hdr; |
255 | 255 | ||
256 | TX_STAT_INC(txq->axq_qnum, a_retries); | 256 | TX_STAT_INC(txq->axq_qnum, a_retries); |
257 | if (tx_info->control.rates[4].count++ > 0) | 257 | if (fi->retries++ > 0) |
258 | return; | 258 | return; |
259 | 259 | ||
260 | hdr = (struct ieee80211_hdr *)skb->data; | 260 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -1506,6 +1506,18 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, | |||
1506 | return duration; | 1506 | return duration; |
1507 | } | 1507 | } |
1508 | 1508 | ||
1509 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) | ||
1510 | { | ||
1511 | struct ath_hw *ah = sc->sc_ah; | ||
1512 | struct ath9k_channel *curchan = ah->curchan; | ||
1513 | if ((sc->sc_flags & SC_OP_ENABLE_APM) && | ||
1514 | (curchan->channelFlags & CHANNEL_5GHZ) && | ||
1515 | (chainmask == 0x7) && (rate < 0x90)) | ||
1516 | return 0x3; | ||
1517 | else | ||
1518 | return chainmask; | ||
1519 | } | ||
1520 | |||
1509 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | 1521 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) |
1510 | { | 1522 | { |
1511 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1523 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -1546,7 +1558,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1546 | 1558 | ||
1547 | rix = rates[i].idx; | 1559 | rix = rates[i].idx; |
1548 | series[i].Tries = rates[i].count; | 1560 | series[i].Tries = rates[i].count; |
1549 | series[i].ChSel = common->tx_chainmask; | ||
1550 | 1561 | ||
1551 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || | 1562 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || |
1552 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { | 1563 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { |
@@ -1569,6 +1580,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1569 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { | 1580 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { |
1570 | /* MCS rates */ | 1581 | /* MCS rates */ |
1571 | series[i].Rate = rix | 0x80; | 1582 | series[i].Rate = rix | 0x80; |
1583 | series[i].ChSel = ath_txchainmask_reduction(sc, | ||
1584 | common->tx_chainmask, series[i].Rate); | ||
1572 | series[i].PktDuration = ath_pkt_duration(sc, rix, len, | 1585 | series[i].PktDuration = ath_pkt_duration(sc, rix, len, |
1573 | is_40, is_sgi, is_sp); | 1586 | is_40, is_sgi, is_sp); |
1574 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) | 1587 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) |
@@ -1576,7 +1589,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1576 | continue; | 1589 | continue; |
1577 | } | 1590 | } |
1578 | 1591 | ||
1579 | /* legcay rates */ | 1592 | /* legacy rates */ |
1580 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && | 1593 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && |
1581 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 1594 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
1582 | phy = WLAN_RC_PHY_CCK; | 1595 | phy = WLAN_RC_PHY_CCK; |
@@ -1592,6 +1605,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1592 | is_sp = false; | 1605 | is_sp = false; |
1593 | } | 1606 | } |
1594 | 1607 | ||
1608 | if (bf->bf_state.bfs_paprd) | ||
1609 | series[i].ChSel = common->tx_chainmask; | ||
1610 | else | ||
1611 | series[i].ChSel = ath_txchainmask_reduction(sc, | ||
1612 | common->tx_chainmask, series[i].Rate); | ||
1613 | |||
1595 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, | 1614 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, |
1596 | phy, rate->bitrate * 100, len, rix, is_sp); | 1615 | phy, rate->bitrate * 100, len, rix, is_sp); |
1597 | } | 1616 | } |