diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-04-25 14:34:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-25 14:34:25 -0400 |
commit | cfef6047c4027a8448ec8dafeaf2bb362cc882e4 (patch) | |
tree | c254bd25aa8b4b0696b5b5cc45d8e30c7c1bb9dd /drivers/net/wireless/ath | |
parent | b71d1d426d263b0b6cb5760322efebbfc89d4463 (diff) | |
parent | 73b48099cc265f88fa1255f3f43e52fe6a94fd5c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt2x00queue.h
Diffstat (limited to 'drivers/net/wireless/ath')
57 files changed, 2962 insertions, 1249 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 6d7105b7e8f1..7cf4317a2a84 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -123,14 +123,7 @@ struct ath_ops { | |||
123 | }; | 123 | }; |
124 | 124 | ||
125 | struct ath_common; | 125 | struct ath_common; |
126 | 126 | struct ath_bus_ops; | |
127 | struct ath_bus_ops { | ||
128 | enum ath_bus_type ath_bus_type; | ||
129 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
130 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
131 | void (*bt_coex_prep)(struct ath_common *common); | ||
132 | void (*extn_synch_en)(struct ath_common *common); | ||
133 | }; | ||
134 | 127 | ||
135 | struct ath_common { | 128 | struct ath_common { |
136 | void *ah; | 129 | void *ah; |
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 82324e98efef..ea9982781559 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/nl80211.h> | 19 | #include <linux/nl80211.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/etherdevice.h> | ||
21 | #include <ar231x_platform.h> | 22 | #include <ar231x_platform.h> |
22 | #include "ath5k.h" | 23 | #include "ath5k.h" |
23 | #include "debug.h" | 24 | #include "debug.h" |
@@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) | |||
62 | return 0; | 63 | return 0; |
63 | } | 64 | } |
64 | 65 | ||
66 | static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
67 | { | ||
68 | struct ath5k_softc *sc = ah->ah_sc; | ||
69 | struct platform_device *pdev = to_platform_device(sc->dev); | ||
70 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
71 | u8 *cfg_mac; | ||
72 | |||
73 | if (to_platform_device(sc->dev)->id == 0) | ||
74 | cfg_mac = bcfg->config->wlan0_mac; | ||
75 | else | ||
76 | cfg_mac = bcfg->config->wlan1_mac; | ||
77 | |||
78 | memcpy(mac, cfg_mac, ETH_ALEN); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
65 | static const struct ath_bus_ops ath_ahb_bus_ops = { | 82 | static const struct ath_bus_ops ath_ahb_bus_ops = { |
66 | .ath_bus_type = ATH_AHB, | 83 | .ath_bus_type = ATH_AHB, |
67 | .read_cachesize = ath5k_ahb_read_cachesize, | 84 | .read_cachesize = ath5k_ahb_read_cachesize, |
68 | .eeprom_read = ath5k_ahb_eeprom_read, | 85 | .eeprom_read = ath5k_ahb_eeprom_read, |
86 | .eeprom_read_mac = ath5k_ahb_eeprom_read_mac, | ||
69 | }; | 87 | }; |
70 | 88 | ||
71 | /*Initialization*/ | 89 | /*Initialization*/ |
@@ -142,6 +160,16 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
142 | else | 160 | else |
143 | reg |= AR5K_AR5312_ENABLE_WLAN1; | 161 | reg |= AR5K_AR5312_ENABLE_WLAN1; |
144 | __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); | 162 | __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); |
163 | |||
164 | /* | ||
165 | * On a dual-band AR5312, the multiband radio is only | ||
166 | * used as pass-through. Disable 2 GHz support in the | ||
167 | * driver for it | ||
168 | */ | ||
169 | if (to_platform_device(sc->dev)->id == 0 && | ||
170 | (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == | ||
171 | (BD_WLAN1|BD_WLAN0)) | ||
172 | __set_bit(ATH_STAT_2G_DISABLED, sc->status); | ||
145 | } | 173 | } |
146 | 174 | ||
147 | ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); | 175 | ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8a06dbd39629..bb50700436fe 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -224,8 +224,7 @@ | |||
224 | 224 | ||
225 | /* SIFS */ | 225 | /* SIFS */ |
226 | #define AR5K_INIT_SIFS_TURBO 6 | 226 | #define AR5K_INIT_SIFS_TURBO 6 |
227 | /* XXX: 8 from initvals 10 from standard */ | 227 | #define AR5K_INIT_SIFS_DEFAULT_BG 10 |
228 | #define AR5K_INIT_SIFS_DEFAULT_BG 8 | ||
229 | #define AR5K_INIT_SIFS_DEFAULT_A 16 | 228 | #define AR5K_INIT_SIFS_DEFAULT_A 16 |
230 | #define AR5K_INIT_SIFS_HALF_RATE 32 | 229 | #define AR5K_INIT_SIFS_HALF_RATE 32 |
231 | #define AR5K_INIT_SIFS_QUARTER_RATE 64 | 230 | #define AR5K_INIT_SIFS_QUARTER_RATE 64 |
@@ -453,12 +452,10 @@ struct ath5k_tx_status { | |||
453 | u16 ts_seqnum; | 452 | u16 ts_seqnum; |
454 | u16 ts_tstamp; | 453 | u16 ts_tstamp; |
455 | u8 ts_status; | 454 | u8 ts_status; |
456 | u8 ts_rate[4]; | ||
457 | u8 ts_retry[4]; | ||
458 | u8 ts_final_idx; | 455 | u8 ts_final_idx; |
456 | u8 ts_final_retry; | ||
459 | s8 ts_rssi; | 457 | s8 ts_rssi; |
460 | u8 ts_shortretry; | 458 | u8 ts_shortretry; |
461 | u8 ts_longretry; | ||
462 | u8 ts_virtcol; | 459 | u8 ts_virtcol; |
463 | u8 ts_antenna; | 460 | u8 ts_antenna; |
464 | }; | 461 | }; |
@@ -875,6 +872,19 @@ enum ath5k_int { | |||
875 | AR5K_INT_QTRIG = 0x40000000, /* Non common */ | 872 | AR5K_INT_QTRIG = 0x40000000, /* Non common */ |
876 | AR5K_INT_GLOBAL = 0x80000000, | 873 | AR5K_INT_GLOBAL = 0x80000000, |
877 | 874 | ||
875 | AR5K_INT_TX_ALL = AR5K_INT_TXOK | ||
876 | | AR5K_INT_TXDESC | ||
877 | | AR5K_INT_TXERR | ||
878 | | AR5K_INT_TXEOL | ||
879 | | AR5K_INT_TXURN, | ||
880 | |||
881 | AR5K_INT_RX_ALL = AR5K_INT_RXOK | ||
882 | | AR5K_INT_RXDESC | ||
883 | | AR5K_INT_RXERR | ||
884 | | AR5K_INT_RXNOFRM | ||
885 | | AR5K_INT_RXEOL | ||
886 | | AR5K_INT_RXORN, | ||
887 | |||
878 | AR5K_INT_COMMON = AR5K_INT_RXOK | 888 | AR5K_INT_COMMON = AR5K_INT_RXOK |
879 | | AR5K_INT_RXDESC | 889 | | AR5K_INT_RXDESC |
880 | | AR5K_INT_RXERR | 890 | | AR5K_INT_RXERR |
@@ -1058,6 +1068,7 @@ struct ath5k_hw { | |||
1058 | u8 ah_coverage_class; | 1068 | u8 ah_coverage_class; |
1059 | bool ah_ack_bitrate_high; | 1069 | bool ah_ack_bitrate_high; |
1060 | u8 ah_bwmode; | 1070 | u8 ah_bwmode; |
1071 | bool ah_short_slot; | ||
1061 | 1072 | ||
1062 | /* Antenna Control */ | 1073 | /* Antenna Control */ |
1063 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1074 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
@@ -1144,6 +1155,13 @@ struct ath5k_hw { | |||
1144 | struct ath5k_rx_status *); | 1155 | struct ath5k_rx_status *); |
1145 | }; | 1156 | }; |
1146 | 1157 | ||
1158 | struct ath_bus_ops { | ||
1159 | enum ath_bus_type ath_bus_type; | ||
1160 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
1161 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
1162 | int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); | ||
1163 | }; | ||
1164 | |||
1147 | /* | 1165 | /* |
1148 | * Prototypes | 1166 | * Prototypes |
1149 | */ | 1167 | */ |
@@ -1227,13 +1245,12 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah); | |||
1227 | /* EEPROM access functions */ | 1245 | /* EEPROM access functions */ |
1228 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1246 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1229 | void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1247 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1230 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | ||
1231 | 1248 | ||
1232 | 1249 | ||
1233 | /* Protocol Control Unit Functions */ | 1250 | /* Protocol Control Unit Functions */ |
1234 | /* Helpers */ | 1251 | /* Helpers */ |
1235 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | 1252 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, |
1236 | int len, struct ieee80211_rate *rate); | 1253 | int len, struct ieee80211_rate *rate, bool shortpre); |
1237 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); | 1254 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); |
1238 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); | 1255 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); |
1239 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); | 1256 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index bc8240560488..1588401de3c4 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -313,12 +313,17 @@ int ath5k_hw_init(struct ath5k_softc *sc) | |||
313 | goto err; | 313 | goto err; |
314 | } | 314 | } |
315 | 315 | ||
316 | if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { | ||
317 | __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); | ||
318 | __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); | ||
319 | } | ||
320 | |||
316 | /* Crypto settings */ | 321 | /* Crypto settings */ |
317 | common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? | 322 | common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? |
318 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); | 323 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); |
319 | 324 | ||
320 | if (srev >= AR5K_SREV_AR5212_V4 && | 325 | if (srev >= AR5K_SREV_AR5212_V4 && |
321 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 326 | (ee->ee_version < AR5K_EEPROM_VERSION_5_0 || |
322 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) | 327 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) |
323 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; | 328 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; |
324 | 329 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 349a5963931b..203243bacc89 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | |||
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | static void | 1446 | static void |
1447 | ath5k_set_current_imask(struct ath5k_softc *sc) | ||
1448 | { | ||
1449 | enum ath5k_int imask = sc->imask; | ||
1450 | unsigned long flags; | ||
1451 | |||
1452 | spin_lock_irqsave(&sc->irqlock, flags); | ||
1453 | if (sc->rx_pending) | ||
1454 | imask &= ~AR5K_INT_RX_ALL; | ||
1455 | if (sc->tx_pending) | ||
1456 | imask &= ~AR5K_INT_TX_ALL; | ||
1457 | ath5k_hw_set_imr(sc->ah, imask); | ||
1458 | spin_unlock_irqrestore(&sc->irqlock, flags); | ||
1459 | } | ||
1460 | |||
1461 | static void | ||
1447 | ath5k_tasklet_rx(unsigned long data) | 1462 | ath5k_tasklet_rx(unsigned long data) |
1448 | { | 1463 | { |
1449 | struct ath5k_rx_status rs = {}; | 1464 | struct ath5k_rx_status rs = {}; |
@@ -1506,6 +1521,8 @@ next: | |||
1506 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1521 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
1507 | unlock: | 1522 | unlock: |
1508 | spin_unlock(&sc->rxbuflock); | 1523 | spin_unlock(&sc->rxbuflock); |
1524 | sc->rx_pending = false; | ||
1525 | ath5k_set_current_imask(sc); | ||
1509 | } | 1526 | } |
1510 | 1527 | ||
1511 | 1528 | ||
@@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1573 | struct ath5k_txq *txq, struct ath5k_tx_status *ts) | 1590 | struct ath5k_txq *txq, struct ath5k_tx_status *ts) |
1574 | { | 1591 | { |
1575 | struct ieee80211_tx_info *info; | 1592 | struct ieee80211_tx_info *info; |
1593 | u8 tries[3]; | ||
1576 | int i; | 1594 | int i; |
1577 | 1595 | ||
1578 | sc->stats.tx_all_count++; | 1596 | sc->stats.tx_all_count++; |
1579 | sc->stats.tx_bytes_count += skb->len; | 1597 | sc->stats.tx_bytes_count += skb->len; |
1580 | info = IEEE80211_SKB_CB(skb); | 1598 | info = IEEE80211_SKB_CB(skb); |
1581 | 1599 | ||
1600 | tries[0] = info->status.rates[0].count; | ||
1601 | tries[1] = info->status.rates[1].count; | ||
1602 | tries[2] = info->status.rates[2].count; | ||
1603 | |||
1582 | ieee80211_tx_info_clear_status(info); | 1604 | ieee80211_tx_info_clear_status(info); |
1583 | for (i = 0; i < 4; i++) { | 1605 | |
1606 | for (i = 0; i < ts->ts_final_idx; i++) { | ||
1584 | struct ieee80211_tx_rate *r = | 1607 | struct ieee80211_tx_rate *r = |
1585 | &info->status.rates[i]; | 1608 | &info->status.rates[i]; |
1586 | 1609 | ||
1587 | if (ts->ts_rate[i]) { | 1610 | r->count = tries[i]; |
1588 | r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]); | ||
1589 | r->count = ts->ts_retry[i]; | ||
1590 | } else { | ||
1591 | r->idx = -1; | ||
1592 | r->count = 0; | ||
1593 | } | ||
1594 | } | 1611 | } |
1595 | 1612 | ||
1596 | /* count the successful attempt as well */ | 1613 | info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; |
1597 | info->status.rates[ts->ts_final_idx].count++; | 1614 | info->status.rates[ts->ts_final_idx + 1].idx = -1; |
1598 | 1615 | ||
1599 | if (unlikely(ts->ts_status)) { | 1616 | if (unlikely(ts->ts_status)) { |
1600 | sc->stats.ack_fail++; | 1617 | sc->stats.ack_fail++; |
@@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1609 | } else { | 1626 | } else { |
1610 | info->flags |= IEEE80211_TX_STAT_ACK; | 1627 | info->flags |= IEEE80211_TX_STAT_ACK; |
1611 | info->status.ack_signal = ts->ts_rssi; | 1628 | info->status.ack_signal = ts->ts_rssi; |
1629 | |||
1630 | /* count the successful attempt as well */ | ||
1631 | info->status.rates[ts->ts_final_idx].count++; | ||
1612 | } | 1632 | } |
1613 | 1633 | ||
1614 | /* | 1634 | /* |
@@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data) | |||
1690 | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) | 1710 | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) |
1691 | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) | 1711 | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) |
1692 | ath5k_tx_processq(sc, &sc->txqs[i]); | 1712 | ath5k_tx_processq(sc, &sc->txqs[i]); |
1713 | |||
1714 | sc->tx_pending = false; | ||
1715 | ath5k_set_current_imask(sc); | ||
1693 | } | 1716 | } |
1694 | 1717 | ||
1695 | 1718 | ||
@@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) | |||
2119 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | 2142 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ |
2120 | } | 2143 | } |
2121 | 2144 | ||
2145 | static void | ||
2146 | ath5k_schedule_rx(struct ath5k_softc *sc) | ||
2147 | { | ||
2148 | sc->rx_pending = true; | ||
2149 | tasklet_schedule(&sc->rxtq); | ||
2150 | } | ||
2151 | |||
2152 | static void | ||
2153 | ath5k_schedule_tx(struct ath5k_softc *sc) | ||
2154 | { | ||
2155 | sc->tx_pending = true; | ||
2156 | tasklet_schedule(&sc->txtq); | ||
2157 | } | ||
2158 | |||
2122 | irqreturn_t | 2159 | irqreturn_t |
2123 | ath5k_intr(int irq, void *dev_id) | 2160 | ath5k_intr(int irq, void *dev_id) |
2124 | { | 2161 | { |
@@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2161 | ieee80211_queue_work(sc->hw, &sc->reset_work); | 2198 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2162 | } | 2199 | } |
2163 | else | 2200 | else |
2164 | tasklet_schedule(&sc->rxtq); | 2201 | ath5k_schedule_rx(sc); |
2165 | } else { | 2202 | } else { |
2166 | if (status & AR5K_INT_SWBA) { | 2203 | if (status & AR5K_INT_SWBA) { |
2167 | tasklet_hi_schedule(&sc->beacontq); | 2204 | tasklet_hi_schedule(&sc->beacontq); |
@@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2179 | ath5k_hw_update_tx_triglevel(ah, true); | 2216 | ath5k_hw_update_tx_triglevel(ah, true); |
2180 | } | 2217 | } |
2181 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) | 2218 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) |
2182 | tasklet_schedule(&sc->rxtq); | 2219 | ath5k_schedule_rx(sc); |
2183 | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | 2220 | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC |
2184 | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) | 2221 | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) |
2185 | tasklet_schedule(&sc->txtq); | 2222 | ath5k_schedule_tx(sc); |
2186 | if (status & AR5K_INT_BMISS) { | 2223 | if (status & AR5K_INT_BMISS) { |
2187 | /* TODO */ | 2224 | /* TODO */ |
2188 | } | 2225 | } |
@@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id) | |||
2201 | 2238 | ||
2202 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); | 2239 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); |
2203 | 2240 | ||
2241 | if (sc->rx_pending || sc->tx_pending) | ||
2242 | ath5k_set_current_imask(sc); | ||
2243 | |||
2204 | if (unlikely(!counter)) | 2244 | if (unlikely(!counter)) |
2205 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2245 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2206 | 2246 | ||
@@ -2572,6 +2612,8 @@ done: | |||
2572 | 2612 | ||
2573 | static void stop_tasklets(struct ath5k_softc *sc) | 2613 | static void stop_tasklets(struct ath5k_softc *sc) |
2574 | { | 2614 | { |
2615 | sc->rx_pending = false; | ||
2616 | sc->tx_pending = false; | ||
2575 | tasklet_kill(&sc->rxtq); | 2617 | tasklet_kill(&sc->rxtq); |
2576 | tasklet_kill(&sc->txtq); | 2618 | tasklet_kill(&sc->txtq); |
2577 | tasklet_kill(&sc->calib); | 2619 | tasklet_kill(&sc->calib); |
@@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw) | |||
2838 | INIT_WORK(&sc->reset_work, ath5k_reset_work); | 2880 | INIT_WORK(&sc->reset_work, ath5k_reset_work); |
2839 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); | 2881 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); |
2840 | 2882 | ||
2841 | ret = ath5k_eeprom_read_mac(ah, mac); | 2883 | ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); |
2842 | if (ret) { | 2884 | if (ret) { |
2843 | ATH5K_ERR(sc, "unable to read address from EEPROM\n"); | 2885 | ATH5K_ERR(sc, "unable to read address from EEPROM\n"); |
2844 | goto err_queues; | 2886 | goto err_queues; |
@@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc) | |||
2898 | * XXX: ??? detach ath5k_hw ??? | 2940 | * XXX: ??? detach ath5k_hw ??? |
2899 | * Other than that, it's straightforward... | 2941 | * Other than that, it's straightforward... |
2900 | */ | 2942 | */ |
2901 | ath5k_debug_finish_device(sc); | ||
2902 | ieee80211_unregister_hw(hw); | 2943 | ieee80211_unregister_hw(hw); |
2903 | ath5k_desc_free(sc); | 2944 | ath5k_desc_free(sc); |
2904 | ath5k_txq_release(sc); | 2945 | ath5k_txq_release(sc); |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 978f1f4ac2f3..b294f3305011 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -193,12 +193,13 @@ struct ath5k_softc { | |||
193 | dma_addr_t desc_daddr; /* DMA (physical) address */ | 193 | dma_addr_t desc_daddr; /* DMA (physical) address */ |
194 | size_t desc_len; /* size of TX/RX descriptors */ | 194 | size_t desc_len; /* size of TX/RX descriptors */ |
195 | 195 | ||
196 | DECLARE_BITMAP(status, 5); | 196 | DECLARE_BITMAP(status, 6); |
197 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ | 197 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ |
198 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ | 198 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ |
199 | #define ATH_STAT_PROMISC 2 | 199 | #define ATH_STAT_PROMISC 2 |
200 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ | 200 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ |
201 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ | 201 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ |
202 | #define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ | ||
202 | 203 | ||
203 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 204 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
204 | struct ieee80211_channel *curchan; /* current h/w channel */ | 205 | struct ieee80211_channel *curchan; /* current h/w channel */ |
@@ -207,6 +208,10 @@ struct ath5k_softc { | |||
207 | 208 | ||
208 | enum ath5k_int imask; /* interrupt mask copy */ | 209 | enum ath5k_int imask; /* interrupt mask copy */ |
209 | 210 | ||
211 | spinlock_t irqlock; | ||
212 | bool rx_pending; /* rx tasklet pending */ | ||
213 | bool tx_pending; /* tx tasklet pending */ | ||
214 | |||
210 | u8 lladdr[ETH_ALEN]; | 215 | u8 lladdr[ETH_ALEN]; |
211 | u8 bssidmask[ETH_ALEN]; | 216 | u8 bssidmask[ETH_ALEN]; |
212 | 217 | ||
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index f77e8a703c5c..7dd88e1c3ff8 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -94,6 +94,9 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112) | ||
98 | __clear_bit(AR5K_MODE_11A, caps->cap_mode); | ||
99 | |||
97 | /* Set number of supported TX queues */ | 100 | /* Set number of supported TX queues */ |
98 | if (ah->ah_version == AR5K_AR5210) | 101 | if (ah->ah_version == AR5K_AR5210) |
99 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; | 102 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0230f30e9e9a..0bf7313b8a17 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -888,65 +888,38 @@ static const struct file_operations fops_queue = { | |||
888 | void | 888 | void |
889 | ath5k_debug_init_device(struct ath5k_softc *sc) | 889 | ath5k_debug_init_device(struct ath5k_softc *sc) |
890 | { | 890 | { |
891 | sc->debug.level = ath5k_debug; | 891 | struct dentry *phydir; |
892 | 892 | ||
893 | sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", | 893 | sc->debug.level = ath5k_debug; |
894 | sc->hw->wiphy->debugfsdir); | ||
895 | 894 | ||
896 | sc->debug.debugfs_debug = debugfs_create_file("debug", | 895 | phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); |
897 | S_IWUSR | S_IRUSR, | 896 | if (!phydir) |
898 | sc->debug.debugfs_phydir, sc, &fops_debug); | 897 | return; |
899 | 898 | ||
900 | sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, | 899 | debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, |
901 | sc->debug.debugfs_phydir, sc, &fops_registers); | 900 | &fops_debug); |
902 | 901 | ||
903 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", | 902 | debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); |
904 | S_IWUSR | S_IRUSR, | ||
905 | sc->debug.debugfs_phydir, sc, &fops_beacon); | ||
906 | 903 | ||
907 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, | 904 | debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, |
908 | sc->debug.debugfs_phydir, sc, &fops_reset); | 905 | &fops_beacon); |
909 | 906 | ||
910 | sc->debug.debugfs_antenna = debugfs_create_file("antenna", | 907 | debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); |
911 | S_IWUSR | S_IRUSR, | ||
912 | sc->debug.debugfs_phydir, sc, &fops_antenna); | ||
913 | 908 | ||
914 | sc->debug.debugfs_misc = debugfs_create_file("misc", | 909 | debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, |
915 | S_IRUSR, | 910 | &fops_antenna); |
916 | sc->debug.debugfs_phydir, sc, &fops_misc); | ||
917 | 911 | ||
918 | sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", | 912 | debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); |
919 | S_IWUSR | S_IRUSR, | ||
920 | sc->debug.debugfs_phydir, sc, | ||
921 | &fops_frameerrors); | ||
922 | 913 | ||
923 | sc->debug.debugfs_ani = debugfs_create_file("ani", | 914 | debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, |
924 | S_IWUSR | S_IRUSR, | 915 | &fops_frameerrors); |
925 | sc->debug.debugfs_phydir, sc, | ||
926 | &fops_ani); | ||
927 | 916 | ||
928 | sc->debug.debugfs_queue = debugfs_create_file("queue", | 917 | debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); |
929 | S_IWUSR | S_IRUSR, | ||
930 | sc->debug.debugfs_phydir, sc, | ||
931 | &fops_queue); | ||
932 | } | ||
933 | 918 | ||
934 | void | 919 | debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, |
935 | ath5k_debug_finish_device(struct ath5k_softc *sc) | 920 | &fops_queue); |
936 | { | ||
937 | debugfs_remove(sc->debug.debugfs_debug); | ||
938 | debugfs_remove(sc->debug.debugfs_registers); | ||
939 | debugfs_remove(sc->debug.debugfs_beacon); | ||
940 | debugfs_remove(sc->debug.debugfs_reset); | ||
941 | debugfs_remove(sc->debug.debugfs_antenna); | ||
942 | debugfs_remove(sc->debug.debugfs_misc); | ||
943 | debugfs_remove(sc->debug.debugfs_frameerrors); | ||
944 | debugfs_remove(sc->debug.debugfs_ani); | ||
945 | debugfs_remove(sc->debug.debugfs_queue); | ||
946 | debugfs_remove(sc->debug.debugfs_phydir); | ||
947 | } | 921 | } |
948 | 922 | ||
949 | |||
950 | /* functions used in other places */ | 923 | /* functions used in other places */ |
951 | 924 | ||
952 | void | 925 | void |
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index b0355aef68d3..193dd2d4ea3c 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -68,17 +68,6 @@ struct ath5k_buf; | |||
68 | 68 | ||
69 | struct ath5k_dbg_info { | 69 | struct ath5k_dbg_info { |
70 | unsigned int level; /* debug level */ | 70 | unsigned int level; /* debug level */ |
71 | /* debugfs entries */ | ||
72 | struct dentry *debugfs_phydir; | ||
73 | struct dentry *debugfs_debug; | ||
74 | struct dentry *debugfs_registers; | ||
75 | struct dentry *debugfs_beacon; | ||
76 | struct dentry *debugfs_reset; | ||
77 | struct dentry *debugfs_antenna; | ||
78 | struct dentry *debugfs_misc; | ||
79 | struct dentry *debugfs_frameerrors; | ||
80 | struct dentry *debugfs_ani; | ||
81 | struct dentry *debugfs_queue; | ||
82 | }; | 71 | }; |
83 | 72 | ||
84 | /** | 73 | /** |
@@ -141,9 +130,6 @@ void | |||
141 | ath5k_debug_init_device(struct ath5k_softc *sc); | 130 | ath5k_debug_init_device(struct ath5k_softc *sc); |
142 | 131 | ||
143 | void | 132 | void |
144 | ath5k_debug_finish_device(struct ath5k_softc *sc); | ||
145 | |||
146 | void | ||
147 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); | 133 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); |
148 | 134 | ||
149 | void | 135 | void |
@@ -167,9 +153,6 @@ static inline void | |||
167 | ath5k_debug_init_device(struct ath5k_softc *sc) {} | 153 | ath5k_debug_init_device(struct ath5k_softc *sc) {} |
168 | 154 | ||
169 | static inline void | 155 | static inline void |
170 | ath5k_debug_finish_device(struct ath5k_softc *sc) {} | ||
171 | |||
172 | static inline void | ||
173 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} | 156 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} |
174 | 157 | ||
175 | static inline void | 158 | static inline void |
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index a8fcc94269f7..62172d585723 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -185,6 +185,12 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
185 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 185 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
186 | unsigned int frame_len; | 186 | unsigned int frame_len; |
187 | 187 | ||
188 | /* | ||
189 | * Use local variables for these to reduce load/store access on | ||
190 | * uncached memory | ||
191 | */ | ||
192 | u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; | ||
193 | |||
188 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 194 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
189 | 195 | ||
190 | /* | 196 | /* |
@@ -208,8 +214,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
208 | if (tx_power > AR5K_TUNE_MAX_TXPOWER) | 214 | if (tx_power > AR5K_TUNE_MAX_TXPOWER) |
209 | tx_power = AR5K_TUNE_MAX_TXPOWER; | 215 | tx_power = AR5K_TUNE_MAX_TXPOWER; |
210 | 216 | ||
211 | /* Clear descriptor */ | 217 | /* Clear descriptor status area */ |
212 | memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); | 218 | memset(&desc->ud.ds_tx5212.tx_stat, 0, |
219 | sizeof(desc->ud.ds_tx5212.tx_stat)); | ||
213 | 220 | ||
214 | /* Setup control descriptor */ | 221 | /* Setup control descriptor */ |
215 | 222 | ||
@@ -221,7 +228,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
221 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 228 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
222 | return -EINVAL; | 229 | return -EINVAL; |
223 | 230 | ||
224 | tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | 231 | txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; |
225 | 232 | ||
226 | /* Verify and set buffer length */ | 233 | /* Verify and set buffer length */ |
227 | 234 | ||
@@ -232,21 +239,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
232 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | 239 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) |
233 | return -EINVAL; | 240 | return -EINVAL; |
234 | 241 | ||
235 | tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | 242 | txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; |
236 | 243 | ||
237 | tx_ctl->tx_control_0 |= | 244 | txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | |
238 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | 245 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
239 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | 246 | txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
240 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | 247 | txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
241 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | 248 | txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
242 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, | ||
243 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | ||
244 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
245 | 249 | ||
246 | #define _TX_FLAGS(_c, _flag) \ | 250 | #define _TX_FLAGS(_c, _flag) \ |
247 | if (flags & AR5K_TXDESC_##_flag) { \ | 251 | if (flags & AR5K_TXDESC_##_flag) { \ |
248 | tx_ctl->tx_control_##_c |= \ | 252 | txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ |
249 | AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ | ||
250 | } | 253 | } |
251 | 254 | ||
252 | _TX_FLAGS(0, CLRDMASK); | 255 | _TX_FLAGS(0, CLRDMASK); |
@@ -262,8 +265,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
262 | * WEP crap | 265 | * WEP crap |
263 | */ | 266 | */ |
264 | if (key_index != AR5K_TXKEYIX_INVALID) { | 267 | if (key_index != AR5K_TXKEYIX_INVALID) { |
265 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 268 | txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
266 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | 269 | txctl1 |= AR5K_REG_SM(key_index, |
267 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); | 270 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); |
268 | } | 271 | } |
269 | 272 | ||
@@ -274,12 +277,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
274 | if ((flags & AR5K_TXDESC_RTSENA) && | 277 | if ((flags & AR5K_TXDESC_RTSENA) && |
275 | (flags & AR5K_TXDESC_CTSENA)) | 278 | (flags & AR5K_TXDESC_CTSENA)) |
276 | return -EINVAL; | 279 | return -EINVAL; |
277 | tx_ctl->tx_control_2 |= rtscts_duration & | 280 | txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; |
278 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | 281 | txctl3 |= AR5K_REG_SM(rtscts_rate, |
279 | tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | ||
280 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | 282 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); |
281 | } | 283 | } |
282 | 284 | ||
285 | tx_ctl->tx_control_0 = txctl0; | ||
286 | tx_ctl->tx_control_1 = txctl1; | ||
287 | tx_ctl->tx_control_2 = txctl2; | ||
288 | tx_ctl->tx_control_3 = txctl3; | ||
289 | |||
283 | return 0; | 290 | return 0; |
284 | } | 291 | } |
285 | 292 | ||
@@ -364,7 +371,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
364 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 371 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
365 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 372 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
366 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 373 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
367 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 374 | ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0, |
368 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 375 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
369 | /*TODO: ts->ts_virtcol + test*/ | 376 | /*TODO: ts->ts_virtcol + test*/ |
370 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 377 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
@@ -373,9 +380,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
373 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 380 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
374 | ts->ts_antenna = 1; | 381 | ts->ts_antenna = 1; |
375 | ts->ts_status = 0; | 382 | ts->ts_status = 0; |
376 | ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, | ||
377 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
378 | ts->ts_retry[0] = ts->ts_longretry; | ||
379 | ts->ts_final_idx = 0; | 383 | ts->ts_final_idx = 0; |
380 | 384 | ||
381 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | 385 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
@@ -401,81 +405,48 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
401 | { | 405 | { |
402 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 406 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
403 | struct ath5k_hw_tx_status *tx_status; | 407 | struct ath5k_hw_tx_status *tx_status; |
408 | u32 txstat0, txstat1; | ||
404 | 409 | ||
405 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 410 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
406 | tx_status = &desc->ud.ds_tx5212.tx_stat; | 411 | tx_status = &desc->ud.ds_tx5212.tx_stat; |
407 | 412 | ||
413 | txstat1 = ACCESS_ONCE(tx_status->tx_status_1); | ||
414 | |||
408 | /* No frame has been send or error */ | 415 | /* No frame has been send or error */ |
409 | if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) | 416 | if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE))) |
410 | return -EINPROGRESS; | 417 | return -EINPROGRESS; |
411 | 418 | ||
419 | txstat0 = ACCESS_ONCE(tx_status->tx_status_0); | ||
420 | |||
412 | /* | 421 | /* |
413 | * Get descriptor status | 422 | * Get descriptor status |
414 | */ | 423 | */ |
415 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | 424 | ts->ts_tstamp = AR5K_REG_MS(txstat0, |
416 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 425 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
417 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 426 | ts->ts_shortretry = AR5K_REG_MS(txstat0, |
418 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 427 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
419 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 428 | ts->ts_final_retry = AR5K_REG_MS(txstat0, |
420 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 429 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
421 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 430 | ts->ts_seqnum = AR5K_REG_MS(txstat1, |
422 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | 431 | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
423 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 432 | ts->ts_rssi = AR5K_REG_MS(txstat1, |
424 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 433 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
425 | ts->ts_antenna = (tx_status->tx_status_1 & | 434 | ts->ts_antenna = (txstat1 & |
426 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; | 435 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; |
427 | ts->ts_status = 0; | 436 | ts->ts_status = 0; |
428 | 437 | ||
429 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, | 438 | ts->ts_final_idx = AR5K_REG_MS(txstat1, |
430 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); | 439 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
431 | 440 | ||
432 | /* The longretry counter has the number of un-acked retries | ||
433 | * for the final rate. To get the total number of retries | ||
434 | * we have to add the retry counters for the other rates | ||
435 | * as well | ||
436 | */ | ||
437 | ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; | ||
438 | switch (ts->ts_final_idx) { | ||
439 | case 3: | ||
440 | ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
441 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
442 | |||
443 | ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
444 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
445 | ts->ts_longretry += ts->ts_retry[2]; | ||
446 | /* fall through */ | ||
447 | case 2: | ||
448 | ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
449 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
450 | |||
451 | ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
452 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
453 | ts->ts_longretry += ts->ts_retry[1]; | ||
454 | /* fall through */ | ||
455 | case 1: | ||
456 | ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
457 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | ||
458 | |||
459 | ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
460 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
461 | ts->ts_longretry += ts->ts_retry[0]; | ||
462 | /* fall through */ | ||
463 | case 0: | ||
464 | ts->ts_rate[0] = tx_ctl->tx_control_3 & | ||
465 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
466 | break; | ||
467 | } | ||
468 | |||
469 | /* TX error */ | 441 | /* TX error */ |
470 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | 442 | if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
471 | if (tx_status->tx_status_0 & | 443 | if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
472 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
473 | ts->ts_status |= AR5K_TXERR_XRETRY; | 444 | ts->ts_status |= AR5K_TXERR_XRETRY; |
474 | 445 | ||
475 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | 446 | if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
476 | ts->ts_status |= AR5K_TXERR_FIFO; | 447 | ts->ts_status |= AR5K_TXERR_FIFO; |
477 | 448 | ||
478 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | 449 | if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED) |
479 | ts->ts_status |= AR5K_TXERR_FILT; | 450 | ts->ts_status |= AR5K_TXERR_FILT; |
480 | } | 451 | } |
481 | 452 | ||
@@ -609,37 +580,37 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
609 | struct ath5k_rx_status *rs) | 580 | struct ath5k_rx_status *rs) |
610 | { | 581 | { |
611 | struct ath5k_hw_rx_status *rx_status; | 582 | struct ath5k_hw_rx_status *rx_status; |
583 | u32 rxstat0, rxstat1; | ||
612 | 584 | ||
613 | rx_status = &desc->ud.ds_rx.rx_stat; | 585 | rx_status = &desc->ud.ds_rx.rx_stat; |
586 | rxstat1 = ACCESS_ONCE(rx_status->rx_status_1); | ||
614 | 587 | ||
615 | /* No frame received / not ready */ | 588 | /* No frame received / not ready */ |
616 | if (unlikely(!(rx_status->rx_status_1 & | 589 | if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE))) |
617 | AR5K_5212_RX_DESC_STATUS1_DONE))) | ||
618 | return -EINPROGRESS; | 590 | return -EINPROGRESS; |
619 | 591 | ||
620 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | 592 | memset(rs, 0, sizeof(struct ath5k_rx_status)); |
593 | rxstat0 = ACCESS_ONCE(rx_status->rx_status_0); | ||
621 | 594 | ||
622 | /* | 595 | /* |
623 | * Frame receive status | 596 | * Frame receive status |
624 | */ | 597 | */ |
625 | rs->rs_datalen = rx_status->rx_status_0 & | 598 | rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; |
626 | AR5K_5212_RX_DESC_STATUS0_DATA_LEN; | 599 | rs->rs_rssi = AR5K_REG_MS(rxstat0, |
627 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
628 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 600 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
629 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 601 | rs->rs_rate = AR5K_REG_MS(rxstat0, |
630 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); | 602 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); |
631 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | 603 | rs->rs_antenna = AR5K_REG_MS(rxstat0, |
632 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); | 604 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); |
633 | rs->rs_more = !!(rx_status->rx_status_0 & | 605 | rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); |
634 | AR5K_5212_RX_DESC_STATUS0_MORE); | 606 | rs->rs_tstamp = AR5K_REG_MS(rxstat1, |
635 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
636 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 607 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
637 | 608 | ||
638 | /* | 609 | /* |
639 | * Key table status | 610 | * Key table status |
640 | */ | 611 | */ |
641 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | 612 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
642 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 613 | rs->rs_keyix = AR5K_REG_MS(rxstat1, |
643 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | 614 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
644 | else | 615 | else |
645 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | 616 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
@@ -647,27 +618,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
647 | /* | 618 | /* |
648 | * Receive/descriptor errors | 619 | * Receive/descriptor errors |
649 | */ | 620 | */ |
650 | if (!(rx_status->rx_status_1 & | 621 | if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
651 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 622 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
652 | if (rx_status->rx_status_1 & | ||
653 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | ||
654 | rs->rs_status |= AR5K_RXERR_CRC; | 623 | rs->rs_status |= AR5K_RXERR_CRC; |
655 | 624 | ||
656 | if (rx_status->rx_status_1 & | 625 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
657 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | ||
658 | rs->rs_status |= AR5K_RXERR_PHY; | 626 | rs->rs_status |= AR5K_RXERR_PHY; |
659 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, | 627 | rs->rs_phyerr = AR5K_REG_MS(rxstat1, |
660 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); | 628 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); |
661 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | 629 | if (!ah->ah_capabilities.cap_has_phyerr_counters) |
662 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | 630 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); |
663 | } | 631 | } |
664 | 632 | ||
665 | if (rx_status->rx_status_1 & | 633 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
666 | AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
667 | rs->rs_status |= AR5K_RXERR_DECRYPT; | 634 | rs->rs_status |= AR5K_RXERR_DECRYPT; |
668 | 635 | ||
669 | if (rx_status->rx_status_1 & | 636 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
670 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | ||
671 | rs->rs_status |= AR5K_RXERR_MIC; | 637 | rs->rs_status |= AR5K_RXERR_MIC; |
672 | } | 638 | } |
673 | return 0; | 639 | return 0; |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index efb672cb31e4..1fef84f87c78 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -660,6 +660,53 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) | |||
660 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; | 660 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int | ||
664 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
665 | { | ||
666 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
667 | struct ath5k_chan_pcal_info *chinfo; | ||
668 | u8 pier, pdg; | ||
669 | |||
670 | switch (mode) { | ||
671 | case AR5K_EEPROM_MODE_11A: | ||
672 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
673 | return 0; | ||
674 | chinfo = ee->ee_pwr_cal_a; | ||
675 | break; | ||
676 | case AR5K_EEPROM_MODE_11B: | ||
677 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
678 | return 0; | ||
679 | chinfo = ee->ee_pwr_cal_b; | ||
680 | break; | ||
681 | case AR5K_EEPROM_MODE_11G: | ||
682 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
683 | return 0; | ||
684 | chinfo = ee->ee_pwr_cal_g; | ||
685 | break; | ||
686 | default: | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
690 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
691 | if (!chinfo[pier].pd_curves) | ||
692 | continue; | ||
693 | |||
694 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | ||
695 | struct ath5k_pdgain_info *pd = | ||
696 | &chinfo[pier].pd_curves[pdg]; | ||
697 | |||
698 | if (pd != NULL) { | ||
699 | kfree(pd->pd_step); | ||
700 | kfree(pd->pd_pwr); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | kfree(chinfo[pier].pd_curves); | ||
705 | } | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
663 | /* Convert RF5111 specific data to generic raw data | 710 | /* Convert RF5111 specific data to generic raw data |
664 | * used by interpolation code */ | 711 | * used by interpolation code */ |
665 | static int | 712 | static int |
@@ -684,7 +731,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
684 | GFP_KERNEL); | 731 | GFP_KERNEL); |
685 | 732 | ||
686 | if (!chinfo[pier].pd_curves) | 733 | if (!chinfo[pier].pd_curves) |
687 | return -ENOMEM; | 734 | goto err_out; |
688 | 735 | ||
689 | /* Only one curve for RF5111 | 736 | /* Only one curve for RF5111 |
690 | * find out which one and place | 737 | * find out which one and place |
@@ -708,12 +755,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
708 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 755 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
709 | sizeof(u8), GFP_KERNEL); | 756 | sizeof(u8), GFP_KERNEL); |
710 | if (!pd->pd_step) | 757 | if (!pd->pd_step) |
711 | return -ENOMEM; | 758 | goto err_out; |
712 | 759 | ||
713 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 760 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
714 | sizeof(s16), GFP_KERNEL); | 761 | sizeof(s16), GFP_KERNEL); |
715 | if (!pd->pd_pwr) | 762 | if (!pd->pd_pwr) |
716 | return -ENOMEM; | 763 | goto err_out; |
717 | 764 | ||
718 | /* Fill raw dataset | 765 | /* Fill raw dataset |
719 | * (convert power to 0.25dB units | 766 | * (convert power to 0.25dB units |
@@ -734,6 +781,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
734 | } | 781 | } |
735 | 782 | ||
736 | return 0; | 783 | return 0; |
784 | |||
785 | err_out: | ||
786 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
787 | return -ENOMEM; | ||
737 | } | 788 | } |
738 | 789 | ||
739 | /* Parse EEPROM data */ | 790 | /* Parse EEPROM data */ |
@@ -867,7 +918,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
867 | GFP_KERNEL); | 918 | GFP_KERNEL); |
868 | 919 | ||
869 | if (!chinfo[pier].pd_curves) | 920 | if (!chinfo[pier].pd_curves) |
870 | return -ENOMEM; | 921 | goto err_out; |
871 | 922 | ||
872 | /* Fill pd_curves */ | 923 | /* Fill pd_curves */ |
873 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 924 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -886,14 +937,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
886 | sizeof(u8), GFP_KERNEL); | 937 | sizeof(u8), GFP_KERNEL); |
887 | 938 | ||
888 | if (!pd->pd_step) | 939 | if (!pd->pd_step) |
889 | return -ENOMEM; | 940 | goto err_out; |
890 | 941 | ||
891 | pd->pd_pwr = kcalloc(pd->pd_points, | 942 | pd->pd_pwr = kcalloc(pd->pd_points, |
892 | sizeof(s16), GFP_KERNEL); | 943 | sizeof(s16), GFP_KERNEL); |
893 | 944 | ||
894 | if (!pd->pd_pwr) | 945 | if (!pd->pd_pwr) |
895 | return -ENOMEM; | 946 | goto err_out; |
896 | |||
897 | 947 | ||
898 | /* Fill raw dataset | 948 | /* Fill raw dataset |
899 | * (all power levels are in 0.25dB units) */ | 949 | * (all power levels are in 0.25dB units) */ |
@@ -925,13 +975,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
925 | sizeof(u8), GFP_KERNEL); | 975 | sizeof(u8), GFP_KERNEL); |
926 | 976 | ||
927 | if (!pd->pd_step) | 977 | if (!pd->pd_step) |
928 | return -ENOMEM; | 978 | goto err_out; |
929 | 979 | ||
930 | pd->pd_pwr = kcalloc(pd->pd_points, | 980 | pd->pd_pwr = kcalloc(pd->pd_points, |
931 | sizeof(s16), GFP_KERNEL); | 981 | sizeof(s16), GFP_KERNEL); |
932 | 982 | ||
933 | if (!pd->pd_pwr) | 983 | if (!pd->pd_pwr) |
934 | return -ENOMEM; | 984 | goto err_out; |
935 | 985 | ||
936 | /* Fill raw dataset | 986 | /* Fill raw dataset |
937 | * (all power levels are in 0.25dB units) */ | 987 | * (all power levels are in 0.25dB units) */ |
@@ -954,6 +1004,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
954 | } | 1004 | } |
955 | 1005 | ||
956 | return 0; | 1006 | return 0; |
1007 | |||
1008 | err_out: | ||
1009 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1010 | return -ENOMEM; | ||
957 | } | 1011 | } |
958 | 1012 | ||
959 | /* Parse EEPROM data */ | 1013 | /* Parse EEPROM data */ |
@@ -1156,7 +1210,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1156 | GFP_KERNEL); | 1210 | GFP_KERNEL); |
1157 | 1211 | ||
1158 | if (!chinfo[pier].pd_curves) | 1212 | if (!chinfo[pier].pd_curves) |
1159 | return -ENOMEM; | 1213 | goto err_out; |
1160 | 1214 | ||
1161 | /* Fill pd_curves */ | 1215 | /* Fill pd_curves */ |
1162 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 1216 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -1177,13 +1231,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1177 | sizeof(u8), GFP_KERNEL); | 1231 | sizeof(u8), GFP_KERNEL); |
1178 | 1232 | ||
1179 | if (!pd->pd_step) | 1233 | if (!pd->pd_step) |
1180 | return -ENOMEM; | 1234 | goto err_out; |
1181 | 1235 | ||
1182 | pd->pd_pwr = kcalloc(pd->pd_points, | 1236 | pd->pd_pwr = kcalloc(pd->pd_points, |
1183 | sizeof(s16), GFP_KERNEL); | 1237 | sizeof(s16), GFP_KERNEL); |
1184 | 1238 | ||
1185 | if (!pd->pd_pwr) | 1239 | if (!pd->pd_pwr) |
1186 | return -ENOMEM; | 1240 | goto err_out; |
1187 | 1241 | ||
1188 | /* Fill raw dataset | 1242 | /* Fill raw dataset |
1189 | * convert all pwr levels to | 1243 | * convert all pwr levels to |
@@ -1213,6 +1267,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1213 | } | 1267 | } |
1214 | 1268 | ||
1215 | return 0; | 1269 | return 0; |
1270 | |||
1271 | err_out: | ||
1272 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1273 | return -ENOMEM; | ||
1216 | } | 1274 | } |
1217 | 1275 | ||
1218 | /* Parse EEPROM data */ | 1276 | /* Parse EEPROM data */ |
@@ -1534,53 +1592,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | |||
1534 | return 0; | 1592 | return 0; |
1535 | } | 1593 | } |
1536 | 1594 | ||
1537 | static int | ||
1538 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
1539 | { | ||
1540 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1541 | struct ath5k_chan_pcal_info *chinfo; | ||
1542 | u8 pier, pdg; | ||
1543 | |||
1544 | switch (mode) { | ||
1545 | case AR5K_EEPROM_MODE_11A: | ||
1546 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
1547 | return 0; | ||
1548 | chinfo = ee->ee_pwr_cal_a; | ||
1549 | break; | ||
1550 | case AR5K_EEPROM_MODE_11B: | ||
1551 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
1552 | return 0; | ||
1553 | chinfo = ee->ee_pwr_cal_b; | ||
1554 | break; | ||
1555 | case AR5K_EEPROM_MODE_11G: | ||
1556 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
1557 | return 0; | ||
1558 | chinfo = ee->ee_pwr_cal_g; | ||
1559 | break; | ||
1560 | default: | ||
1561 | return -EINVAL; | ||
1562 | } | ||
1563 | |||
1564 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
1565 | if (!chinfo[pier].pd_curves) | ||
1566 | continue; | ||
1567 | |||
1568 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | ||
1569 | struct ath5k_pdgain_info *pd = | ||
1570 | &chinfo[pier].pd_curves[pdg]; | ||
1571 | |||
1572 | if (pd != NULL) { | ||
1573 | kfree(pd->pd_step); | ||
1574 | kfree(pd->pd_pwr); | ||
1575 | } | ||
1576 | } | ||
1577 | |||
1578 | kfree(chinfo[pier].pd_curves); | ||
1579 | } | ||
1580 | |||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | /* Read conformance test limits used for regulatory control */ | 1595 | /* Read conformance test limits used for regulatory control */ |
1585 | static int | 1596 | static int |
1586 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | 1597 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) |
@@ -1721,35 +1732,6 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) | |||
1721 | return ret; | 1732 | return ret; |
1722 | } | 1733 | } |
1723 | 1734 | ||
1724 | /* | ||
1725 | * Read the MAC address from eeprom | ||
1726 | */ | ||
1727 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
1728 | { | ||
1729 | u8 mac_d[ETH_ALEN] = {}; | ||
1730 | u32 total, offset; | ||
1731 | u16 data; | ||
1732 | int octet; | ||
1733 | |||
1734 | AR5K_EEPROM_READ(0x20, data); | ||
1735 | |||
1736 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
1737 | AR5K_EEPROM_READ(offset, data); | ||
1738 | |||
1739 | total += data; | ||
1740 | mac_d[octet + 1] = data & 0xff; | ||
1741 | mac_d[octet] = data >> 8; | ||
1742 | octet += 2; | ||
1743 | } | ||
1744 | |||
1745 | if (!total || total == 3 * 0xffff) | ||
1746 | return -EINVAL; | ||
1747 | |||
1748 | memcpy(mac, mac_d, ETH_ALEN); | ||
1749 | |||
1750 | return 0; | ||
1751 | } | ||
1752 | |||
1753 | 1735 | ||
1754 | /***********************\ | 1736 | /***********************\ |
1755 | * Init/Detach functions * | 1737 | * Init/Detach functions * |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 9be29b728b1c..807bd6440169 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -282,6 +282,15 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
282 | if (changes & BSS_CHANGED_BEACON_INT) | 282 | if (changes & BSS_CHANGED_BEACON_INT) |
283 | sc->bintval = bss_conf->beacon_int; | 283 | sc->bintval = bss_conf->beacon_int; |
284 | 284 | ||
285 | if (changes & BSS_CHANGED_ERP_SLOT) { | ||
286 | int slot_time; | ||
287 | |||
288 | ah->ah_short_slot = bss_conf->use_short_slot; | ||
289 | slot_time = ath5k_hw_get_default_slottime(ah) + | ||
290 | 3 * ah->ah_coverage_class; | ||
291 | ath5k_hw_set_ifs_intervals(ah, slot_time); | ||
292 | } | ||
293 | |||
285 | if (changes & BSS_CHANGED_ASSOC) { | 294 | if (changes & BSS_CHANGED_ASSOC) { |
286 | avf->assoc = bss_conf->assoc; | 295 | avf->assoc = bss_conf->assoc; |
287 | if (bss_conf->assoc) | 296 | if (bss_conf->assoc) |
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 3c44689a700b..296c316a8341 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/nl80211.h> | 17 | #include <linux/nl80211.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
20 | #include <linux/etherdevice.h> | ||
20 | #include "../ath.h" | 21 | #include "../ath.h" |
21 | #include "ath5k.h" | 22 | #include "ath5k.h" |
22 | #include "debug.h" | 23 | #include "debug.h" |
@@ -108,11 +109,42 @@ int ath5k_hw_read_srev(struct ath5k_hw *ah) | |||
108 | return 0; | 109 | return 0; |
109 | } | 110 | } |
110 | 111 | ||
112 | /* | ||
113 | * Read the MAC address from eeprom or platform_data | ||
114 | */ | ||
115 | static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
116 | { | ||
117 | u8 mac_d[ETH_ALEN] = {}; | ||
118 | u32 total, offset; | ||
119 | u16 data; | ||
120 | int octet; | ||
121 | |||
122 | AR5K_EEPROM_READ(0x20, data); | ||
123 | |||
124 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
125 | AR5K_EEPROM_READ(offset, data); | ||
126 | |||
127 | total += data; | ||
128 | mac_d[octet + 1] = data & 0xff; | ||
129 | mac_d[octet] = data >> 8; | ||
130 | octet += 2; | ||
131 | } | ||
132 | |||
133 | if (!total || total == 3 * 0xffff) | ||
134 | return -EINVAL; | ||
135 | |||
136 | memcpy(mac, mac_d, ETH_ALEN); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | |||
111 | /* Common ath_bus_opts structure */ | 142 | /* Common ath_bus_opts structure */ |
112 | static const struct ath_bus_ops ath_pci_bus_ops = { | 143 | static const struct ath_bus_ops ath_pci_bus_ops = { |
113 | .ath_bus_type = ATH_PCI, | 144 | .ath_bus_type = ATH_PCI, |
114 | .read_cachesize = ath5k_pci_read_cachesize, | 145 | .read_cachesize = ath5k_pci_read_cachesize, |
115 | .eeprom_read = ath5k_pci_eeprom_read, | 146 | .eeprom_read = ath5k_pci_eeprom_read, |
147 | .eeprom_read_mac = ath5k_pci_eeprom_read_mac, | ||
116 | }; | 148 | }; |
117 | 149 | ||
118 | /********************\ | 150 | /********************\ |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index d9b3f828455a..712a9ac4000e 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -75,7 +75,7 @@ static const unsigned int ack_rates_high[] = | |||
75 | * bwmodes. | 75 | * bwmodes. |
76 | */ | 76 | */ |
77 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | 77 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, |
78 | int len, struct ieee80211_rate *rate) | 78 | int len, struct ieee80211_rate *rate, bool shortpre) |
79 | { | 79 | { |
80 | struct ath5k_softc *sc = ah->ah_sc; | 80 | struct ath5k_softc *sc = ah->ah_sc; |
81 | int sifs, preamble, plcp_bits, sym_time; | 81 | int sifs, preamble, plcp_bits, sym_time; |
@@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | |||
84 | 84 | ||
85 | /* Fallback */ | 85 | /* Fallback */ |
86 | if (!ah->ah_bwmode) { | 86 | if (!ah->ah_bwmode) { |
87 | dur = ieee80211_generic_frame_duration(sc->hw, | 87 | __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, |
88 | NULL, len, rate); | 88 | NULL, len, rate); |
89 | return le16_to_cpu(dur); | 89 | |
90 | /* subtract difference between long and short preamble */ | ||
91 | dur = le16_to_cpu(raw_dur); | ||
92 | if (shortpre) | ||
93 | dur -= 96; | ||
94 | |||
95 | return dur; | ||
90 | } | 96 | } |
91 | 97 | ||
92 | bitrate = rate->bitrate; | 98 | bitrate = rate->bitrate; |
@@ -145,9 +151,9 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | |||
145 | slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; | 151 | slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; |
146 | break; | 152 | break; |
147 | case AR5K_BWMODE_DEFAULT: | 153 | case AR5K_BWMODE_DEFAULT: |
148 | slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; | ||
149 | default: | 154 | default: |
150 | if (channel->hw_value & CHANNEL_CCK) | 155 | slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; |
156 | if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot) | ||
151 | slot_time = AR5K_INIT_SLOT_TIME_B; | 157 | slot_time = AR5K_INIT_SLOT_TIME_B; |
152 | break; | 158 | break; |
153 | } | 159 | } |
@@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) | |||
263 | * actual rate for this rate. See mac80211 tx.c | 269 | * actual rate for this rate. See mac80211 tx.c |
264 | * ieee80211_duration() for a brief description of | 270 | * ieee80211_duration() for a brief description of |
265 | * what rate we should choose to TX ACKs. */ | 271 | * what rate we should choose to TX ACKs. */ |
266 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); | 272 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); |
267 | 273 | ||
268 | ath5k_hw_reg_write(ah, tx_time, reg); | 274 | ath5k_hw_reg_write(ah, tx_time, reg); |
269 | 275 | ||
270 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | 276 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) |
271 | continue; | 277 | continue; |
272 | 278 | ||
273 | /* | 279 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); |
274 | * We're not distinguishing short preamble here, | ||
275 | * This is true, all we'll get is a longer value here | ||
276 | * which is not necessarilly bad. We could use | ||
277 | * export ieee80211_frame_duration() but that needs to be | ||
278 | * fixed first to be properly used by mac802111 drivers: | ||
279 | * | ||
280 | * - remove erp stuff and let the routine figure ofdm | ||
281 | * erp rates | ||
282 | * - remove passing argument ieee80211_local as | ||
283 | * drivers don't have access to it | ||
284 | * - move drivers using ieee80211_generic_frame_duration() | ||
285 | * to this | ||
286 | */ | ||
287 | ath5k_hw_reg_write(ah, tx_time, | 280 | ath5k_hw_reg_write(ah, tx_time, |
288 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | 281 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); |
289 | } | 282 | } |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 3343fb9e4940..b18c5021aac3 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -519,7 +519,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) | |||
519 | return -EINVAL; | 519 | return -EINVAL; |
520 | 520 | ||
521 | sifs = ath5k_hw_get_default_sifs(ah); | 521 | sifs = ath5k_hw_get_default_sifs(ah); |
522 | sifs_clock = ath5k_hw_htoclock(ah, sifs); | 522 | sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); |
523 | 523 | ||
524 | /* EIFS | 524 | /* EIFS |
525 | * Txtime of ack at lowest rate + SIFS + DIFS | 525 | * Txtime of ack at lowest rate + SIFS + DIFS |
@@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) | |||
550 | else | 550 | else |
551 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; | 551 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; |
552 | 552 | ||
553 | ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); | 553 | ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); |
554 | 554 | ||
555 | /* ack_tx_time includes an SIFS already */ | 555 | /* ack_tx_time includes an SIFS already */ |
556 | eifs = ack_tx_time + sifs + 2 * slot_time; | 556 | eifs = ack_tx_time + sifs + 2 * slot_time; |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ad57a6d23110..d9ff8413ab9a 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -5,7 +5,7 @@ config ATH9K_COMMON | |||
5 | 5 | ||
6 | config ATH9K | 6 | config ATH9K |
7 | tristate "Atheros 802.11n wireless cards support" | 7 | tristate "Atheros 802.11n wireless cards support" |
8 | depends on PCI && MAC80211 | 8 | depends on MAC80211 |
9 | select ATH9K_HW | 9 | select ATH9K_HW |
10 | select MAC80211_LEDS | 10 | select MAC80211_LEDS |
11 | select LEDS_CLASS | 11 | select LEDS_CLASS |
@@ -23,6 +23,25 @@ config ATH9K | |||
23 | 23 | ||
24 | If you choose to build a module, it'll be called ath9k. | 24 | If you choose to build a module, it'll be called ath9k. |
25 | 25 | ||
26 | config ATH9K_PCI | ||
27 | bool "Atheros ath9k PCI/PCIe bus support" | ||
28 | depends on ATH9K && PCI | ||
29 | default PCI | ||
30 | ---help--- | ||
31 | This option enables the PCI bus support in ath9k. | ||
32 | |||
33 | Say Y, if you have a compatible PCI/PCIe wireless card. | ||
34 | |||
35 | config ATH9K_AHB | ||
36 | bool "Atheros ath9k AHB bus support" | ||
37 | depends on ATH9K | ||
38 | default n | ||
39 | ---help--- | ||
40 | This option enables the AHB bus support in ath9k. | ||
41 | |||
42 | Say Y, if you have a SoC with a compatible built-in | ||
43 | wireless MAC. Say N if unsure. | ||
44 | |||
26 | config ATH9K_DEBUGFS | 45 | config ATH9K_DEBUGFS |
27 | bool "Atheros ath9k debugging" | 46 | bool "Atheros ath9k debugging" |
28 | depends on ATH9K && DEBUG_FS | 47 | depends on ATH9K && DEBUG_FS |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4d66ca8042eb..05a6fade7b1c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -6,8 +6,8 @@ ath9k-y += beacon.o \ | |||
6 | xmit.o \ | 6 | xmit.o \ |
7 | 7 | ||
8 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o | 8 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
9 | ath9k-$(CONFIG_PCI) += pci.o | 9 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
10 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o | 10 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
11 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 11 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
12 | 12 | ||
13 | obj-$(CONFIG_ATH9K) += ath9k.o | 13 | obj-$(CONFIG_ATH9K) += ath9k.o |
@@ -48,4 +48,6 @@ ath9k_htc-y += htc_hst.o \ | |||
48 | htc_drv_init.o \ | 48 | htc_drv_init.o \ |
49 | htc_drv_gpio.o | 49 | htc_drv_gpio.o |
50 | 50 | ||
51 | ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o | ||
52 | |||
51 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o | 53 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9cb0efa9b4c0..5193ed58a17b 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -21,6 +21,14 @@ | |||
21 | #include <linux/ath9k_platform.h> | 21 | #include <linux/ath9k_platform.h> |
22 | #include "ath9k.h" | 22 | #include "ath9k.h" |
23 | 23 | ||
24 | const struct platform_device_id ath9k_platform_id_table[] = { | ||
25 | { | ||
26 | .name = "ath9k", | ||
27 | .driver_data = AR5416_AR9100_DEVID, | ||
28 | }, | ||
29 | {}, | ||
30 | }; | ||
31 | |||
24 | /* return bus cachesize in 4B word units */ | 32 | /* return bus cachesize in 4B word units */ |
25 | static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) | 33 | static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) |
26 | { | 34 | { |
@@ -57,6 +65,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
57 | struct ath_softc *sc; | 65 | struct ath_softc *sc; |
58 | struct ieee80211_hw *hw; | 66 | struct ieee80211_hw *hw; |
59 | struct resource *res; | 67 | struct resource *res; |
68 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
60 | int irq; | 69 | int irq; |
61 | int ret = 0; | 70 | int ret = 0; |
62 | struct ath_hw *ah; | 71 | struct ath_hw *ah; |
@@ -116,7 +125,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
116 | goto err_free_hw; | 125 | goto err_free_hw; |
117 | } | 126 | } |
118 | 127 | ||
119 | ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); | 128 | ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops); |
120 | if (ret) { | 129 | if (ret) { |
121 | dev_err(&pdev->dev, "failed to initialize device\n"); | 130 | dev_err(&pdev->dev, "failed to initialize device\n"); |
122 | goto err_irq; | 131 | goto err_irq; |
@@ -165,8 +174,11 @@ static struct platform_driver ath_ahb_driver = { | |||
165 | .name = "ath9k", | 174 | .name = "ath9k", |
166 | .owner = THIS_MODULE, | 175 | .owner = THIS_MODULE, |
167 | }, | 176 | }, |
177 | .id_table = ath9k_platform_id_table, | ||
168 | }; | 178 | }; |
169 | 179 | ||
180 | MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); | ||
181 | |||
170 | int ath_ahb_init(void) | 182 | int ath_ahb_init(void) |
171 | { | 183 | { |
172 | return platform_driver_register(&ath_ahb_driver); | 184 | return platform_driver_register(&ath_ahb_driver); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 8dd8f6308502..c338efbccf40 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
290 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 290 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
291 | | SM(txPower, AR_XmitPower) | 291 | | SM(txPower, AR_XmitPower) |
292 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 292 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
293 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
294 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | 293 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
295 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); | 294 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); |
296 | 295 | ||
@@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
311 | } | 310 | } |
312 | } | 311 | } |
313 | 312 | ||
313 | static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
314 | { | ||
315 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
316 | |||
317 | if (val) | ||
318 | ads->ds_ctl0 |= AR_ClrDestMask; | ||
319 | else | ||
320 | ads->ds_ctl0 &= ~AR_ClrDestMask; | ||
321 | } | ||
322 | |||
314 | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | 323 | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
315 | void *lastds, | 324 | void *lastds, |
316 | u32 durUpdateEn, u32 rtsctsRate, | 325 | u32 durUpdateEn, u32 rtsctsRate, |
@@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | |||
448 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; | 457 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; |
449 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; | 458 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; |
450 | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; | 459 | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; |
460 | ops->set_clrdmask = ar9002_hw_set_clrdmask; | ||
451 | } | 461 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 37663dbbcf57..47780ef1c892 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -483,7 +483,11 @@ | |||
483 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 | 483 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 |
484 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | 484 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 |
485 | 485 | ||
486 | #define AR_PHY_TX_PWRCTRL8 0xa278 | ||
487 | |||
486 | #define AR_PHY_TX_PWRCTRL9 0xa27C | 488 | #define AR_PHY_TX_PWRCTRL9 0xa27C |
489 | |||
490 | #define AR_PHY_TX_PWRCTRL10 0xa394 | ||
487 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 | 491 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 |
488 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 | 492 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 |
489 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 | 493 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 |
@@ -495,6 +499,8 @@ | |||
495 | 499 | ||
496 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 | 500 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 |
497 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 | 501 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 |
502 | #define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc | ||
503 | #define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 | ||
498 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 | 504 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 |
499 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 | 505 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 |
500 | 506 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 9ecca93392e8..f915a3dbfcad 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -34,10 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { | |||
34 | 34 | ||
35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | 35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { |
36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
37 | {0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, | 37 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
38 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, | 38 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
39 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, | 39 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
40 | {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 40 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
41 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 41 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
42 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 42 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
43 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 43 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -119,14 +119,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | |||
119 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | 119 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
120 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | 120 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
121 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | 121 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
122 | {0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, | 122 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
123 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, | 123 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
124 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, | 124 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
125 | {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 125 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
126 | {0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800}, | 126 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
127 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000}, | 127 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
128 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000}, | 128 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
129 | {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 129 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
130 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 130 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
131 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | 131 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, |
132 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 132 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -835,10 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
835 | 835 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | 836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 838 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
839 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 839 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, |
840 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 840 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, |
841 | {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 841 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
842 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 842 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
843 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 843 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
844 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 844 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -920,14 +920,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
920 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 920 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
921 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 921 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
922 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 922 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
923 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 923 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
924 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 924 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, |
925 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 925 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, |
926 | {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 926 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
927 | {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 927 | {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, |
928 | {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 928 | {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, |
929 | {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 929 | {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, |
930 | {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 930 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
931 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 931 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, |
932 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 932 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, |
933 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 933 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, |
@@ -941,10 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
941 | 941 | ||
942 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | 942 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { |
943 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 943 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
944 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, | 944 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, |
945 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, | 945 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
946 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, | 946 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
947 | {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 947 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
948 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 948 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
949 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 949 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
950 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 950 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -1026,14 +1026,14 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | |||
1026 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 1026 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
1027 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 1027 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
1028 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | 1028 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, |
1029 | {0x0000b2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, | 1029 | {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, |
1030 | {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, | 1030 | {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
1031 | {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, | 1031 | {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
1032 | {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1032 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
1033 | {0x0000c2dc, 0x01feee00, 0x01feee00, 0x00637800, 0x00637800}, | 1033 | {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, |
1034 | {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03838000, 0x03838000}, | 1034 | {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, |
1035 | {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03fc0000, 0x03fc0000}, | 1035 | {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, |
1036 | {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1036 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
1037 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 1037 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, |
1038 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 1038 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, |
1039 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1039 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -1307,10 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | |||
1307 | 1307 | ||
1308 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | 1308 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { |
1309 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 1309 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
1310 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 1310 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
1311 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 1311 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
1312 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 1312 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
1313 | {0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1313 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
1314 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1314 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
1315 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1315 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1316 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 1316 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -1329,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | |||
1329 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | 1329 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, |
1330 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | 1330 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, |
1331 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | 1331 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, |
1332 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | 1332 | {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, |
1333 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | 1333 | {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, |
1334 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, | 1334 | {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, |
1335 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, | 1335 | {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, |
1336 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, | 1336 | {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, |
1337 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, | 1337 | {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, |
1338 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, | 1338 | {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, |
1339 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, | 1339 | {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, |
1340 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1340 | {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1341 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1341 | {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1342 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1342 | {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1343 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1343 | {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1344 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1344 | {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1345 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1345 | {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1346 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1346 | {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1347 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 1347 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, |
1348 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | 1348 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, |
1349 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | 1349 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, |
@@ -1361,45 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | |||
1361 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, | 1361 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, |
1362 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, | 1362 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, |
1363 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, | 1363 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, |
1364 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, | 1364 | {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, |
1365 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, | 1365 | {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, |
1366 | {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, | 1366 | {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, |
1367 | {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, | 1367 | {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, |
1368 | {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, | 1368 | {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, |
1369 | {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, | 1369 | {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, |
1370 | {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, | 1370 | {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, |
1371 | {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, | 1371 | {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, |
1372 | {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1372 | {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1373 | {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1373 | {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1374 | {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1374 | {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1375 | {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1375 | {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1376 | {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1376 | {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1377 | {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1377 | {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1378 | {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1378 | {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1379 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1379 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1380 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1380 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1381 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1381 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1382 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1382 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1383 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1383 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1384 | {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, | 1384 | {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, |
1385 | {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, | 1385 | {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, |
1386 | {0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, | 1386 | {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, |
1387 | {0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, | 1387 | {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, |
1388 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | 1388 | {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, |
1389 | {0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, | 1389 | {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, |
1390 | {0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, | 1390 | {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
1391 | {0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | 1391 | {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
1392 | {0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | 1392 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
1393 | {0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | 1393 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
1394 | {0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, | 1394 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
1395 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 1395 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
1396 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 1396 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
1397 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 1397 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
1398 | {0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1398 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
1399 | {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800}, | 1399 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
1400 | {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000}, | 1400 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
1401 | {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000}, | 1401 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
1402 | {0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1402 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
1403 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 1403 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
1404 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, | 1404 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, |
1405 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1405 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 724ac2464ad5..c1264d60c499 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
329 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 329 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
330 | | SM(txpower, AR_XmitPower) | 330 | | SM(txpower, AR_XmitPower) |
331 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 331 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
332 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
333 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | 332 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) |
334 | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); | 333 | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); |
335 | 334 | ||
@@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
350 | ads->ctl22 = 0; | 349 | ads->ctl22 = 0; |
351 | } | 350 | } |
352 | 351 | ||
352 | static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
353 | { | ||
354 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
355 | |||
356 | if (val) | ||
357 | ads->ctl11 |= AR_ClrDestMask; | ||
358 | else | ||
359 | ads->ctl11 &= ~AR_ClrDestMask; | ||
360 | } | ||
361 | |||
353 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | 362 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
354 | void *lastds, | 363 | void *lastds, |
355 | u32 durUpdateEn, u32 rtsctsRate, | 364 | u32 durUpdateEn, u32 rtsctsRate, |
@@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
510 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; | 519 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; |
511 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; | 520 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; |
512 | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; | 521 | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; |
522 | ops->set_clrdmask = ar9003_hw_set_clrdmask; | ||
513 | } | 523 | } |
514 | 524 | ||
515 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 525 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index eb250d6b8038..1bc33f51e466 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -75,9 +75,18 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
75 | freq = centers.synth_center; | 75 | freq = centers.synth_center; |
76 | 76 | ||
77 | if (freq < 4800) { /* 2 GHz, fractional mode */ | 77 | if (freq < 4800) { /* 2 GHz, fractional mode */ |
78 | if (AR_SREV_9485(ah)) | 78 | if (AR_SREV_9485(ah)) { |
79 | channelSel = CHANSEL_2G_9485(freq); | 79 | u32 chan_frac; |
80 | else | 80 | |
81 | /* | ||
82 | * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 | ||
83 | * ndiv = ((chan_mhz * 4) / 3) / freq_ref; | ||
84 | * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 | ||
85 | */ | ||
86 | channelSel = (freq * 4) / 120; | ||
87 | chan_frac = (((freq * 4) % 120) * 0x20000) / 120; | ||
88 | channelSel = (channelSel << 17) | chan_frac; | ||
89 | } else | ||
81 | channelSel = CHANSEL_2G(freq); | 90 | channelSel = CHANSEL_2G(freq); |
82 | /* Set to 2G mode */ | 91 | /* Set to 2G mode */ |
83 | bMode = 1; | 92 | bMode = 1; |
@@ -401,7 +410,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, | |||
401 | 410 | ||
402 | ar9003_hw_spur_ofdm_clear(ah); | 411 | ar9003_hw_spur_ofdm_clear(ah); |
403 | 412 | ||
404 | for (i = 0; spurChansPtr[i] && i < 5; i++) { | 413 | for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { |
405 | freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; | 414 | freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; |
406 | if (abs(freq_offset) < range) { | 415 | if (abs(freq_offset) < range) { |
407 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); | 416 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index f91f73e50d00..fbdde29f0ab8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h | |||
@@ -396,7 +396,7 @@ static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { | |||
396 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | 396 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, |
397 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | 397 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, |
398 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 398 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
399 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, | 399 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
400 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 400 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
401 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 401 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, |
402 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 402 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, |
@@ -469,7 +469,7 @@ static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { | |||
469 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | 469 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, |
470 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | 470 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, |
471 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 471 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
472 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, | 472 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
473 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 473 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
474 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 474 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, |
475 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 475 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, |
@@ -635,7 +635,7 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | |||
635 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | 635 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, |
636 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | 636 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, |
637 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 637 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
638 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, | 638 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
639 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 639 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
640 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 640 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, |
641 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 641 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, |
@@ -728,7 +728,7 @@ static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { | |||
728 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | 728 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, |
729 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | 729 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, |
730 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 730 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
731 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, | 731 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
732 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 732 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
733 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 733 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, |
734 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 734 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, |
@@ -827,7 +827,7 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | |||
827 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | 827 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, |
828 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | 828 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, |
829 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | 829 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, |
830 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb}, | 830 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, |
831 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | 831 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, |
832 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | 832 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, |
833 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | 833 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 38835bc324b2..a6b538802251 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -200,6 +200,7 @@ struct ath_atx_ac { | |||
200 | int sched; | 200 | int sched; |
201 | struct list_head list; | 201 | struct list_head list; |
202 | struct list_head tid_q; | 202 | struct list_head tid_q; |
203 | bool clear_ps_filter; | ||
203 | }; | 204 | }; |
204 | 205 | ||
205 | struct ath_frame_info { | 206 | struct ath_frame_info { |
@@ -255,8 +256,12 @@ struct ath_node { | |||
255 | #endif | 256 | #endif |
256 | struct ath_atx_tid tid[WME_NUM_TID]; | 257 | struct ath_atx_tid tid[WME_NUM_TID]; |
257 | struct ath_atx_ac ac[WME_NUM_AC]; | 258 | struct ath_atx_ac ac[WME_NUM_AC]; |
259 | int ps_key; | ||
260 | |||
258 | u16 maxampdu; | 261 | u16 maxampdu; |
259 | u8 mpdudensity; | 262 | u8 mpdudensity; |
263 | |||
264 | bool sleeping; | ||
260 | }; | 265 | }; |
261 | 266 | ||
262 | #define AGGR_CLEANUP BIT(1) | 267 | #define AGGR_CLEANUP BIT(1) |
@@ -338,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
338 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 343 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
339 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 344 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
340 | 345 | ||
346 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); | ||
347 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); | ||
348 | |||
341 | /********/ | 349 | /********/ |
342 | /* VIFs */ | 350 | /* VIFs */ |
343 | /********/ | 351 | /********/ |
@@ -665,7 +673,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); | |||
665 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); | 673 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); |
666 | bool ath9k_uses_beacons(int type); | 674 | bool ath9k_uses_beacons(int type); |
667 | 675 | ||
668 | #ifdef CONFIG_PCI | 676 | #ifdef CONFIG_ATH9K_PCI |
669 | int ath_pci_init(void); | 677 | int ath_pci_init(void); |
670 | void ath_pci_exit(void); | 678 | void ath_pci_exit(void); |
671 | #else | 679 | #else |
@@ -673,7 +681,7 @@ static inline int ath_pci_init(void) { return 0; }; | |||
673 | static inline void ath_pci_exit(void) {}; | 681 | static inline void ath_pci_exit(void) {}; |
674 | #endif | 682 | #endif |
675 | 683 | ||
676 | #ifdef CONFIG_ATHEROS_AR71XX | 684 | #ifdef CONFIG_ATH9K_AHB |
677 | int ath_ahb_init(void); | 685 | int ath_ahb_init(void); |
678 | void ath_ahb_exit(void); | 686 | void ath_ahb_exit(void); |
679 | #else | 687 | #else |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index eccb0ec87adb..24f565ba9988 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -320,6 +320,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | |||
320 | if (avp->av_bcbuf != NULL) { | 320 | if (avp->av_bcbuf != NULL) { |
321 | struct ath_buf *bf; | 321 | struct ath_buf *bf; |
322 | 322 | ||
323 | avp->is_bslot_active = false; | ||
323 | if (avp->av_bslot != -1) { | 324 | if (avp->av_bslot != -1) { |
324 | sc->beacon.bslot[avp->av_bslot] = NULL; | 325 | sc->beacon.bslot[avp->av_bslot] = NULL; |
325 | sc->nbcnvifs--; | 326 | sc->nbcnvifs--; |
@@ -743,9 +744,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
743 | cur_conf->dtim_period = 1; | 744 | cur_conf->dtim_period = 1; |
744 | 745 | ||
745 | ath_set_beacon(sc); | 746 | ath_set_beacon(sc); |
746 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | ||
747 | } | 747 | } |
748 | 748 | ||
749 | static bool ath_has_valid_bslot(struct ath_softc *sc) | ||
750 | { | ||
751 | struct ath_vif *avp; | ||
752 | int slot; | ||
753 | bool found = false; | ||
754 | |||
755 | for (slot = 0; slot < ATH_BCBUF; slot++) { | ||
756 | if (sc->beacon.bslot[slot]) { | ||
757 | avp = (void *)sc->beacon.bslot[slot]->drv_priv; | ||
758 | if (avp->is_bslot_active) { | ||
759 | found = true; | ||
760 | break; | ||
761 | } | ||
762 | } | ||
763 | } | ||
764 | return found; | ||
765 | } | ||
766 | |||
767 | |||
749 | void ath_set_beacon(struct ath_softc *sc) | 768 | void ath_set_beacon(struct ath_softc *sc) |
750 | { | 769 | { |
751 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 770 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -753,7 +772,8 @@ void ath_set_beacon(struct ath_softc *sc) | |||
753 | 772 | ||
754 | switch (sc->sc_ah->opmode) { | 773 | switch (sc->sc_ah->opmode) { |
755 | case NL80211_IFTYPE_AP: | 774 | case NL80211_IFTYPE_AP: |
756 | ath_beacon_config_ap(sc, cur_conf); | 775 | if (ath_has_valid_bslot(sc)) |
776 | ath_beacon_config_ap(sc, cur_conf); | ||
757 | break; | 777 | break; |
758 | case NL80211_IFTYPE_ADHOC: | 778 | case NL80211_IFTYPE_ADHOC: |
759 | case NL80211_IFTYPE_MESH_POINT: | 779 | case NL80211_IFTYPE_MESH_POINT: |
@@ -761,6 +781,12 @@ void ath_set_beacon(struct ath_softc *sc) | |||
761 | break; | 781 | break; |
762 | case NL80211_IFTYPE_STATION: | 782 | case NL80211_IFTYPE_STATION: |
763 | ath_beacon_config_sta(sc, cur_conf); | 783 | ath_beacon_config_sta(sc, cur_conf); |
784 | /* | ||
785 | * Request a re-configuration of Beacon related timers | ||
786 | * on the receipt of the first Beacon frame (i.e., | ||
787 | * after time sync with the AP). | ||
788 | */ | ||
789 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | ||
764 | break; | 790 | break; |
765 | default: | 791 | default: |
766 | ath_dbg(common, ATH_DBG_CONFIG, | 792 | ath_dbg(common, ATH_DBG_CONFIG, |
@@ -774,20 +800,8 @@ void ath_set_beacon(struct ath_softc *sc) | |||
774 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) | 800 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) |
775 | { | 801 | { |
776 | struct ath_hw *ah = sc->sc_ah; | 802 | struct ath_hw *ah = sc->sc_ah; |
777 | struct ath_vif *avp; | ||
778 | int slot; | ||
779 | bool found = false; | ||
780 | 803 | ||
781 | for (slot = 0; slot < ATH_BCBUF; slot++) { | 804 | if (!ath_has_valid_bslot(sc)) |
782 | if (sc->beacon.bslot[slot]) { | ||
783 | avp = (void *)sc->beacon.bslot[slot]->drv_priv; | ||
784 | if (avp->is_bslot_active) { | ||
785 | found = true; | ||
786 | break; | ||
787 | } | ||
788 | } | ||
789 | } | ||
790 | if (!found) | ||
791 | return; | 805 | return; |
792 | 806 | ||
793 | ath9k_ps_wakeup(sc); | 807 | ath9k_ps_wakeup(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index a762cadb3ab7..34f191ec8e8c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -845,7 +845,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
845 | 845 | ||
846 | struct ath_softc *sc = file->private_data; | 846 | struct ath_softc *sc = file->private_data; |
847 | char *buf; | 847 | char *buf; |
848 | unsigned int len = 0, size = 1152; | 848 | unsigned int len = 0, size = 1400; |
849 | ssize_t retval = 0; | 849 | ssize_t retval = 0; |
850 | 850 | ||
851 | buf = kzalloc(size, GFP_KERNEL); | 851 | buf = kzalloc(size, GFP_KERNEL); |
@@ -874,6 +874,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
874 | "%18s : %10u\n", "DECRYPT BUSY ERR", | 874 | "%18s : %10u\n", "DECRYPT BUSY ERR", |
875 | sc->debug.stats.rxstats.decrypt_busy_err); | 875 | sc->debug.stats.rxstats.decrypt_busy_err); |
876 | 876 | ||
877 | len += snprintf(buf + len, size - len, | ||
878 | "%18s : %10d\n", "RSSI-CTL0", | ||
879 | sc->debug.stats.rxstats.rs_rssi_ctl0); | ||
880 | |||
881 | len += snprintf(buf + len, size - len, | ||
882 | "%18s : %10d\n", "RSSI-CTL1", | ||
883 | sc->debug.stats.rxstats.rs_rssi_ctl1); | ||
884 | |||
885 | len += snprintf(buf + len, size - len, | ||
886 | "%18s : %10d\n", "RSSI-CTL2", | ||
887 | sc->debug.stats.rxstats.rs_rssi_ctl2); | ||
888 | |||
889 | len += snprintf(buf + len, size - len, | ||
890 | "%18s : %10d\n", "RSSI-EXT0", | ||
891 | sc->debug.stats.rxstats.rs_rssi_ext0); | ||
892 | |||
893 | len += snprintf(buf + len, size - len, | ||
894 | "%18s : %10d\n", "RSSI-EXT1", | ||
895 | sc->debug.stats.rxstats.rs_rssi_ext1); | ||
896 | |||
897 | len += snprintf(buf + len, size - len, | ||
898 | "%18s : %10d\n", "RSSI-EXT2", | ||
899 | sc->debug.stats.rxstats.rs_rssi_ext2); | ||
900 | |||
901 | len += snprintf(buf + len, size - len, | ||
902 | "%18s : %10d\n", "Rx Antenna", | ||
903 | sc->debug.stats.rxstats.rs_antenna); | ||
904 | |||
877 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | 905 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); |
878 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | 906 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); |
879 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | 907 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); |
@@ -948,6 +976,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
948 | RX_PHY_ERR_INC(phyerr); | 976 | RX_PHY_ERR_INC(phyerr); |
949 | } | 977 | } |
950 | 978 | ||
979 | sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; | ||
980 | sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; | ||
981 | sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; | ||
982 | |||
983 | sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; | ||
984 | sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; | ||
985 | sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; | ||
986 | |||
987 | sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; | ||
988 | |||
951 | #undef RX_STAT_INC | 989 | #undef RX_STAT_INC |
952 | #undef RX_PHY_ERR_INC | 990 | #undef RX_PHY_ERR_INC |
953 | } | 991 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 59338de0ce19..1f9f8eada465 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -157,6 +157,13 @@ struct ath_rx_stats { | |||
157 | u32 post_delim_crc_err; | 157 | u32 post_delim_crc_err; |
158 | u32 decrypt_busy_err; | 158 | u32 decrypt_busy_err; |
159 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | 159 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; |
160 | int8_t rs_rssi_ctl0; | ||
161 | int8_t rs_rssi_ctl1; | ||
162 | int8_t rs_rssi_ctl2; | ||
163 | int8_t rs_rssi_ext0; | ||
164 | int8_t rs_rssi_ext1; | ||
165 | int8_t rs_rssi_ext2; | ||
166 | u8 rs_antenna; | ||
160 | }; | 167 | }; |
161 | 168 | ||
162 | struct ath_stats { | 169 | struct ath_stats { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index bd82447f5b78..3e316133f114 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -436,7 +436,11 @@ struct modal_eep_4k_header { | |||
436 | u8 db2_2:4, db2_3:4; | 436 | u8 db2_2:4, db2_3:4; |
437 | u8 db2_4:4, reserved:4; | 437 | u8 db2_4:4, reserved:4; |
438 | #endif | 438 | #endif |
439 | u8 futureModal[4]; | 439 | u8 tx_diversity; |
440 | u8 flc_pwr_thresh; | ||
441 | u8 bb_scale_smrt_antenna; | ||
442 | #define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f | ||
443 | u8 futureModal[1]; | ||
440 | struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; | 444 | struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; |
441 | } __packed; | 445 | } __packed; |
442 | 446 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index bc77a308c901..6f714dd72365 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -781,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
781 | { | 781 | { |
782 | struct modal_eep_4k_header *pModal; | 782 | struct modal_eep_4k_header *pModal; |
783 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 783 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
784 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | ||
784 | u8 txRxAttenLocal; | 785 | u8 txRxAttenLocal; |
785 | u8 ob[5], db1[5], db2[5]; | 786 | u8 ob[5], db1[5], db2[5]; |
786 | u8 ant_div_control1, ant_div_control2; | 787 | u8 ant_div_control1, ant_div_control2; |
@@ -1003,6 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1003 | AR_PHY_SETTLING_SWITCH, | 1004 | AR_PHY_SETTLING_SWITCH, |
1004 | pModal->swSettleHt40); | 1005 | pModal->swSettleHt40); |
1005 | } | 1006 | } |
1007 | if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { | ||
1008 | u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & | ||
1009 | EEP_4K_BB_DESIRED_SCALE_MASK); | ||
1010 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { | ||
1011 | u32 pwrctrl, mask, clr; | ||
1012 | |||
1013 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); | ||
1014 | pwrctrl = mask * bb_desired_scale; | ||
1015 | clr = mask * 0x1f; | ||
1016 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); | ||
1017 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); | ||
1018 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); | ||
1019 | |||
1020 | mask = BIT(0)|BIT(5)|BIT(15); | ||
1021 | pwrctrl = mask * bb_desired_scale; | ||
1022 | clr = mask * 0x1f; | ||
1023 | REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); | ||
1024 | |||
1025 | mask = BIT(0)|BIT(5); | ||
1026 | pwrctrl = mask * bb_desired_scale; | ||
1027 | clr = mask * 0x1f; | ||
1028 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); | ||
1029 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); | ||
1030 | } | ||
1031 | } | ||
1006 | } | 1032 | } |
1007 | 1033 | ||
1008 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | 1034 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 2f0712ea49a6..13579752a300 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -858,35 +858,12 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
858 | { | 858 | { |
859 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 859 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
860 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 860 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
861 | u16 antWrites[AR9287_ANT_16S]; | ||
862 | u32 regChainOffset, regval; | 861 | u32 regChainOffset, regval; |
863 | u8 txRxAttenLocal; | 862 | u8 txRxAttenLocal; |
864 | int i, j, offset_num; | 863 | int i; |
865 | 864 | ||
866 | pModal = &eep->modalHeader; | 865 | pModal = &eep->modalHeader; |
867 | 866 | ||
868 | antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); | ||
869 | antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); | ||
870 | antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); | ||
871 | antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); | ||
872 | antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); | ||
873 | antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); | ||
874 | antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); | ||
875 | antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); | ||
876 | |||
877 | offset_num = 8; | ||
878 | |||
879 | for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { | ||
880 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); | ||
881 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); | ||
882 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); | ||
883 | antWrites[j++] = 0; | ||
884 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); | ||
885 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); | ||
886 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); | ||
887 | antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); | ||
888 | } | ||
889 | |||
890 | REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); | 867 | REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); |
891 | 868 | ||
892 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | 869 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 2d10239ce829..2e3a33a53406 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -17,11 +17,9 @@ | |||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | /* identify firmware images */ | 19 | /* identify firmware images */ |
20 | #define FIRMWARE_AR7010 "ar7010.fw" | 20 | #define FIRMWARE_AR7010_1_1 "htc_7010.fw" |
21 | #define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" | 21 | #define FIRMWARE_AR9271 "htc_9271.fw" |
22 | #define FIRMWARE_AR9271 "ar9271.fw" | ||
23 | 22 | ||
24 | MODULE_FIRMWARE(FIRMWARE_AR7010); | ||
25 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); | 23 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); |
26 | MODULE_FIRMWARE(FIRMWARE_AR9271); | 24 | MODULE_FIRMWARE(FIRMWARE_AR9271); |
27 | 25 | ||
@@ -80,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb) | |||
80 | 78 | ||
81 | if (cmd) { | 79 | if (cmd) { |
82 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | 80 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, |
83 | cmd->skb, 1); | 81 | cmd->skb, true); |
84 | kfree(cmd); | 82 | kfree(cmd); |
85 | } | 83 | } |
86 | 84 | ||
@@ -126,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
126 | return ret; | 124 | return ret; |
127 | } | 125 | } |
128 | 126 | ||
127 | static void hif_usb_mgmt_cb(struct urb *urb) | ||
128 | { | ||
129 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | ||
130 | struct hif_device_usb *hif_dev = cmd->hif_dev; | ||
131 | bool txok = true; | ||
132 | |||
133 | if (!cmd || !cmd->skb || !cmd->hif_dev) | ||
134 | return; | ||
135 | |||
136 | switch (urb->status) { | ||
137 | case 0: | ||
138 | break; | ||
139 | case -ENOENT: | ||
140 | case -ECONNRESET: | ||
141 | case -ENODEV: | ||
142 | case -ESHUTDOWN: | ||
143 | txok = false; | ||
144 | |||
145 | /* | ||
146 | * If the URBs are being flushed, no need to complete | ||
147 | * this packet. | ||
148 | */ | ||
149 | spin_lock(&hif_dev->tx.tx_lock); | ||
150 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { | ||
151 | spin_unlock(&hif_dev->tx.tx_lock); | ||
152 | dev_kfree_skb_any(cmd->skb); | ||
153 | kfree(cmd); | ||
154 | return; | ||
155 | } | ||
156 | spin_unlock(&hif_dev->tx.tx_lock); | ||
157 | |||
158 | break; | ||
159 | default: | ||
160 | txok = false; | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | skb_pull(cmd->skb, 4); | ||
165 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | ||
166 | cmd->skb, txok); | ||
167 | kfree(cmd); | ||
168 | } | ||
169 | |||
170 | static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, | ||
171 | struct sk_buff *skb) | ||
172 | { | ||
173 | struct urb *urb; | ||
174 | struct cmd_buf *cmd; | ||
175 | int ret = 0; | ||
176 | __le16 *hdr; | ||
177 | |||
178 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
179 | if (urb == NULL) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); | ||
183 | if (cmd == NULL) { | ||
184 | usb_free_urb(urb); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | |||
188 | cmd->skb = skb; | ||
189 | cmd->hif_dev = hif_dev; | ||
190 | |||
191 | hdr = (__le16 *) skb_push(skb, 4); | ||
192 | *hdr++ = cpu_to_le16(skb->len - 4); | ||
193 | *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); | ||
194 | |||
195 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
196 | usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), | ||
197 | skb->data, skb->len, | ||
198 | hif_usb_mgmt_cb, cmd); | ||
199 | |||
200 | usb_anchor_urb(urb, &hif_dev->mgmt_submitted); | ||
201 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
202 | if (ret) { | ||
203 | usb_unanchor_urb(urb); | ||
204 | kfree(cmd); | ||
205 | } | ||
206 | usb_free_urb(urb); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
129 | static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, | 211 | static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, |
130 | struct sk_buff_head *list) | 212 | struct sk_buff_head *list) |
131 | { | 213 | { |
@@ -133,7 +215,22 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, | |||
133 | 215 | ||
134 | while ((skb = __skb_dequeue(list)) != NULL) { | 216 | while ((skb = __skb_dequeue(list)) != NULL) { |
135 | dev_kfree_skb_any(skb); | 217 | dev_kfree_skb_any(skb); |
136 | TX_STAT_INC(skb_dropped); | 218 | } |
219 | } | ||
220 | |||
221 | static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, | ||
222 | struct sk_buff_head *queue, | ||
223 | bool txok) | ||
224 | { | ||
225 | struct sk_buff *skb; | ||
226 | |||
227 | while ((skb = __skb_dequeue(queue)) != NULL) { | ||
228 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
229 | skb, txok); | ||
230 | if (txok) | ||
231 | TX_STAT_INC(skb_success); | ||
232 | else | ||
233 | TX_STAT_INC(skb_failed); | ||
137 | } | 234 | } |
138 | } | 235 | } |
139 | 236 | ||
@@ -141,7 +238,7 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
141 | { | 238 | { |
142 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; | 239 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; |
143 | struct hif_device_usb *hif_dev; | 240 | struct hif_device_usb *hif_dev; |
144 | struct sk_buff *skb; | 241 | bool txok = true; |
145 | 242 | ||
146 | if (!tx_buf || !tx_buf->hif_dev) | 243 | if (!tx_buf || !tx_buf->hif_dev) |
147 | return; | 244 | return; |
@@ -155,10 +252,7 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
155 | case -ECONNRESET: | 252 | case -ECONNRESET: |
156 | case -ENODEV: | 253 | case -ENODEV: |
157 | case -ESHUTDOWN: | 254 | case -ESHUTDOWN: |
158 | /* | 255 | txok = false; |
159 | * The URB has been killed, free the SKBs. | ||
160 | */ | ||
161 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | ||
162 | 256 | ||
163 | /* | 257 | /* |
164 | * If the URBs are being flushed, no need to add this | 258 | * If the URBs are being flushed, no need to add this |
@@ -167,41 +261,19 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
167 | spin_lock(&hif_dev->tx.tx_lock); | 261 | spin_lock(&hif_dev->tx.tx_lock); |
168 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { | 262 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { |
169 | spin_unlock(&hif_dev->tx.tx_lock); | 263 | spin_unlock(&hif_dev->tx.tx_lock); |
264 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | ||
170 | return; | 265 | return; |
171 | } | 266 | } |
172 | spin_unlock(&hif_dev->tx.tx_lock); | 267 | spin_unlock(&hif_dev->tx.tx_lock); |
173 | 268 | ||
174 | /* | 269 | break; |
175 | * In the stop() case, this URB has to be added to | ||
176 | * the free list. | ||
177 | */ | ||
178 | goto add_free; | ||
179 | default: | 270 | default: |
271 | txok = false; | ||
180 | break; | 272 | break; |
181 | } | 273 | } |
182 | 274 | ||
183 | /* | 275 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); |
184 | * Check if TX has been stopped, this is needed because | ||
185 | * this CB could have been invoked just after the TX lock | ||
186 | * was released in hif_stop() and kill_urb() hasn't been | ||
187 | * called yet. | ||
188 | */ | ||
189 | spin_lock(&hif_dev->tx.tx_lock); | ||
190 | if (hif_dev->tx.flags & HIF_USB_TX_STOP) { | ||
191 | spin_unlock(&hif_dev->tx.tx_lock); | ||
192 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | ||
193 | goto add_free; | ||
194 | } | ||
195 | spin_unlock(&hif_dev->tx.tx_lock); | ||
196 | |||
197 | /* Complete the queued SKBs. */ | ||
198 | while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { | ||
199 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
200 | skb, 1); | ||
201 | TX_STAT_INC(skb_completed); | ||
202 | } | ||
203 | 276 | ||
204 | add_free: | ||
205 | /* Re-initialize the SKB queue */ | 277 | /* Re-initialize the SKB queue */ |
206 | tx_buf->len = tx_buf->offset = 0; | 278 | tx_buf->len = tx_buf->offset = 0; |
207 | __skb_queue_head_init(&tx_buf->skb_queue); | 279 | __skb_queue_head_init(&tx_buf->skb_queue); |
@@ -274,7 +346,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
274 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); | 346 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); |
275 | if (ret) { | 347 | if (ret) { |
276 | tx_buf->len = tx_buf->offset = 0; | 348 | tx_buf->len = tx_buf->offset = 0; |
277 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | 349 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false); |
278 | __skb_queue_head_init(&tx_buf->skb_queue); | 350 | __skb_queue_head_init(&tx_buf->skb_queue); |
279 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | 351 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); |
280 | hif_dev->tx.tx_buf_cnt++; | 352 | hif_dev->tx.tx_buf_cnt++; |
@@ -286,10 +358,11 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
286 | return ret; | 358 | return ret; |
287 | } | 359 | } |
288 | 360 | ||
289 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, | 361 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) |
290 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
291 | { | 362 | { |
363 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
292 | unsigned long flags; | 364 | unsigned long flags; |
365 | int ret = 0; | ||
293 | 366 | ||
294 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | 367 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
295 | 368 | ||
@@ -304,26 +377,36 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, | |||
304 | return -ENOMEM; | 377 | return -ENOMEM; |
305 | } | 378 | } |
306 | 379 | ||
307 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | 380 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
308 | hif_dev->tx.tx_skb_cnt++; | ||
309 | 381 | ||
310 | /* Send normal frames immediately */ | 382 | tx_ctl = HTC_SKB_CB(skb); |
311 | if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) | 383 | |
312 | __hif_usb_tx(hif_dev); | 384 | /* Mgmt/Beacon frames don't use the TX buffer pool */ |
385 | if ((tx_ctl->type == ATH9K_HTC_MGMT) || | ||
386 | (tx_ctl->type == ATH9K_HTC_BEACON)) { | ||
387 | ret = hif_usb_send_mgmt(hif_dev, skb); | ||
388 | } | ||
389 | |||
390 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
391 | |||
392 | if ((tx_ctl->type == ATH9K_HTC_NORMAL) || | ||
393 | (tx_ctl->type == ATH9K_HTC_AMPDU)) { | ||
394 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | ||
395 | hif_dev->tx.tx_skb_cnt++; | ||
396 | } | ||
313 | 397 | ||
314 | /* Check if AMPDUs have to be sent immediately */ | 398 | /* Check if AMPDUs have to be sent immediately */ |
315 | if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && | 399 | if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && |
316 | (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && | ||
317 | (hif_dev->tx.tx_skb_cnt < 2)) { | 400 | (hif_dev->tx.tx_skb_cnt < 2)) { |
318 | __hif_usb_tx(hif_dev); | 401 | __hif_usb_tx(hif_dev); |
319 | } | 402 | } |
320 | 403 | ||
321 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 404 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
322 | 405 | ||
323 | return 0; | 406 | return ret; |
324 | } | 407 | } |
325 | 408 | ||
326 | static void hif_usb_start(void *hif_handle, u8 pipe_id) | 409 | static void hif_usb_start(void *hif_handle) |
327 | { | 410 | { |
328 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 411 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
329 | unsigned long flags; | 412 | unsigned long flags; |
@@ -335,14 +418,14 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id) | |||
335 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 418 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
336 | } | 419 | } |
337 | 420 | ||
338 | static void hif_usb_stop(void *hif_handle, u8 pipe_id) | 421 | static void hif_usb_stop(void *hif_handle) |
339 | { | 422 | { |
340 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 423 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
341 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; | 424 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; |
342 | unsigned long flags; | 425 | unsigned long flags; |
343 | 426 | ||
344 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | 427 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
345 | ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); | 428 | ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false); |
346 | hif_dev->tx.tx_skb_cnt = 0; | 429 | hif_dev->tx.tx_skb_cnt = 0; |
347 | hif_dev->tx.flags |= HIF_USB_TX_STOP; | 430 | hif_dev->tx.flags |= HIF_USB_TX_STOP; |
348 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 431 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
@@ -352,17 +435,18 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) | |||
352 | &hif_dev->tx.tx_pending, list) { | 435 | &hif_dev->tx.tx_pending, list) { |
353 | usb_kill_urb(tx_buf->urb); | 436 | usb_kill_urb(tx_buf->urb); |
354 | } | 437 | } |
438 | |||
439 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | ||
355 | } | 440 | } |
356 | 441 | ||
357 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | 442 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) |
358 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
359 | { | 443 | { |
360 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 444 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
361 | int ret = 0; | 445 | int ret = 0; |
362 | 446 | ||
363 | switch (pipe_id) { | 447 | switch (pipe_id) { |
364 | case USB_WLAN_TX_PIPE: | 448 | case USB_WLAN_TX_PIPE: |
365 | ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); | 449 | ret = hif_usb_send_tx(hif_dev, skb); |
366 | break; | 450 | break; |
367 | case USB_REG_OUT_PIPE: | 451 | case USB_REG_OUT_PIPE: |
368 | ret = hif_usb_send_regout(hif_dev, skb); | 452 | ret = hif_usb_send_regout(hif_dev, skb); |
@@ -377,6 +461,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | |||
377 | return ret; | 461 | return ret; |
378 | } | 462 | } |
379 | 463 | ||
464 | static inline bool check_index(struct sk_buff *skb, u8 idx) | ||
465 | { | ||
466 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
467 | |||
468 | tx_ctl = HTC_SKB_CB(skb); | ||
469 | |||
470 | if ((tx_ctl->type == ATH9K_HTC_AMPDU) && | ||
471 | (tx_ctl->sta_idx == idx)) | ||
472 | return true; | ||
473 | |||
474 | return false; | ||
475 | } | ||
476 | |||
477 | static void hif_usb_sta_drain(void *hif_handle, u8 idx) | ||
478 | { | ||
479 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | ||
480 | struct sk_buff *skb, *tmp; | ||
481 | unsigned long flags; | ||
482 | |||
483 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
484 | |||
485 | skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { | ||
486 | if (check_index(skb, idx)) { | ||
487 | __skb_unlink(skb, &hif_dev->tx.tx_skb_queue); | ||
488 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
489 | skb, false); | ||
490 | hif_dev->tx.tx_skb_cnt--; | ||
491 | TX_STAT_INC(skb_failed); | ||
492 | } | ||
493 | } | ||
494 | |||
495 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
496 | } | ||
497 | |||
380 | static struct ath9k_htc_hif hif_usb = { | 498 | static struct ath9k_htc_hif hif_usb = { |
381 | .transport = ATH9K_HIF_USB, | 499 | .transport = ATH9K_HIF_USB, |
382 | .name = "ath9k_hif_usb", | 500 | .name = "ath9k_hif_usb", |
@@ -386,6 +504,7 @@ static struct ath9k_htc_hif hif_usb = { | |||
386 | 504 | ||
387 | .start = hif_usb_start, | 505 | .start = hif_usb_start, |
388 | .stop = hif_usb_stop, | 506 | .stop = hif_usb_stop, |
507 | .sta_drain = hif_usb_sta_drain, | ||
389 | .send = hif_usb_send, | 508 | .send = hif_usb_send, |
390 | }; | 509 | }; |
391 | 510 | ||
@@ -567,6 +686,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
567 | case -ESHUTDOWN: | 686 | case -ESHUTDOWN: |
568 | goto free; | 687 | goto free; |
569 | default: | 688 | default: |
689 | skb_reset_tail_pointer(skb); | ||
690 | skb_trim(skb, 0); | ||
691 | |||
570 | goto resubmit; | 692 | goto resubmit; |
571 | } | 693 | } |
572 | 694 | ||
@@ -591,23 +713,15 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
591 | USB_REG_IN_PIPE), | 713 | USB_REG_IN_PIPE), |
592 | nskb->data, MAX_REG_IN_BUF_SIZE, | 714 | nskb->data, MAX_REG_IN_BUF_SIZE, |
593 | ath9k_hif_usb_reg_in_cb, nskb); | 715 | ath9k_hif_usb_reg_in_cb, nskb); |
594 | |||
595 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
596 | if (ret) { | ||
597 | kfree_skb(nskb); | ||
598 | urb->context = NULL; | ||
599 | } | ||
600 | |||
601 | return; | ||
602 | } | 716 | } |
603 | 717 | ||
604 | resubmit: | 718 | resubmit: |
605 | skb_reset_tail_pointer(skb); | 719 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); |
606 | skb_trim(skb, 0); | ||
607 | |||
608 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 720 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
609 | if (ret) | 721 | if (ret) { |
722 | usb_unanchor_urb(urb); | ||
610 | goto free; | 723 | goto free; |
724 | } | ||
611 | 725 | ||
612 | return; | 726 | return; |
613 | free: | 727 | free: |
@@ -641,6 +755,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
641 | kfree(tx_buf->buf); | 755 | kfree(tx_buf->buf); |
642 | kfree(tx_buf); | 756 | kfree(tx_buf); |
643 | } | 757 | } |
758 | |||
759 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | ||
644 | } | 760 | } |
645 | 761 | ||
646 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | 762 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) |
@@ -652,6 +768,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
652 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); | 768 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); |
653 | spin_lock_init(&hif_dev->tx.tx_lock); | 769 | spin_lock_init(&hif_dev->tx.tx_lock); |
654 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); | 770 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); |
771 | init_usb_anchor(&hif_dev->mgmt_submitted); | ||
655 | 772 | ||
656 | for (i = 0; i < MAX_TX_URB_NUM; i++) { | 773 | for (i = 0; i < MAX_TX_URB_NUM; i++) { |
657 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); | 774 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); |
@@ -748,43 +865,67 @@ err_urb: | |||
748 | return ret; | 865 | return ret; |
749 | } | 866 | } |
750 | 867 | ||
751 | static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) | 868 | static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
752 | { | 869 | { |
753 | if (hif_dev->reg_in_urb) { | 870 | usb_kill_anchored_urbs(&hif_dev->reg_in_submitted); |
754 | usb_kill_urb(hif_dev->reg_in_urb); | ||
755 | if (hif_dev->reg_in_urb->context) | ||
756 | kfree_skb((void *)hif_dev->reg_in_urb->context); | ||
757 | usb_free_urb(hif_dev->reg_in_urb); | ||
758 | hif_dev->reg_in_urb = NULL; | ||
759 | } | ||
760 | } | 871 | } |
761 | 872 | ||
762 | static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | 873 | static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
763 | { | 874 | { |
764 | struct sk_buff *skb; | 875 | struct urb *urb = NULL; |
876 | struct sk_buff *skb = NULL; | ||
877 | int i, ret; | ||
765 | 878 | ||
766 | hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); | 879 | init_usb_anchor(&hif_dev->reg_in_submitted); |
767 | if (hif_dev->reg_in_urb == NULL) | ||
768 | return -ENOMEM; | ||
769 | 880 | ||
770 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); | 881 | for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { |
771 | if (!skb) | ||
772 | goto err; | ||
773 | 882 | ||
774 | usb_fill_bulk_urb(hif_dev->reg_in_urb, hif_dev->udev, | 883 | /* Allocate URB */ |
775 | usb_rcvbulkpipe(hif_dev->udev, | 884 | urb = usb_alloc_urb(0, GFP_KERNEL); |
776 | USB_REG_IN_PIPE), | 885 | if (urb == NULL) { |
777 | skb->data, MAX_REG_IN_BUF_SIZE, | 886 | ret = -ENOMEM; |
778 | ath9k_hif_usb_reg_in_cb, skb); | 887 | goto err_urb; |
888 | } | ||
779 | 889 | ||
780 | if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) | 890 | /* Allocate buffer */ |
781 | goto err; | 891 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); |
892 | if (!skb) { | ||
893 | ret = -ENOMEM; | ||
894 | goto err_skb; | ||
895 | } | ||
896 | |||
897 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
898 | usb_rcvbulkpipe(hif_dev->udev, | ||
899 | USB_REG_IN_PIPE), | ||
900 | skb->data, MAX_REG_IN_BUF_SIZE, | ||
901 | ath9k_hif_usb_reg_in_cb, skb); | ||
902 | |||
903 | /* Anchor URB */ | ||
904 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); | ||
905 | |||
906 | /* Submit URB */ | ||
907 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
908 | if (ret) { | ||
909 | usb_unanchor_urb(urb); | ||
910 | goto err_submit; | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | * Drop reference count. | ||
915 | * This ensures that the URB is freed when killing them. | ||
916 | */ | ||
917 | usb_free_urb(urb); | ||
918 | } | ||
782 | 919 | ||
783 | return 0; | 920 | return 0; |
784 | 921 | ||
785 | err: | 922 | err_submit: |
786 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 923 | kfree_skb(skb); |
787 | return -ENOMEM; | 924 | err_skb: |
925 | usb_free_urb(urb); | ||
926 | err_urb: | ||
927 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); | ||
928 | return ret; | ||
788 | } | 929 | } |
789 | 930 | ||
790 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | 931 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) |
@@ -801,7 +942,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | |||
801 | goto err_rx; | 942 | goto err_rx; |
802 | 943 | ||
803 | /* Register Read */ | 944 | /* Register Read */ |
804 | if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) | 945 | if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0) |
805 | goto err_reg; | 946 | goto err_reg; |
806 | 947 | ||
807 | return 0; | 948 | return 0; |
@@ -816,7 +957,7 @@ err: | |||
816 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) | 957 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) |
817 | { | 958 | { |
818 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); | 959 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); |
819 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 960 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); |
820 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | 961 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
821 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | 962 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); |
822 | } | 963 | } |
@@ -1026,10 +1167,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
1026 | /* Find out which firmware to load */ | 1167 | /* Find out which firmware to load */ |
1027 | 1168 | ||
1028 | if (IS_AR7010_DEVICE(id->driver_info)) | 1169 | if (IS_AR7010_DEVICE(id->driver_info)) |
1029 | if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) | 1170 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; |
1030 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; | ||
1031 | else | ||
1032 | hif_dev->fw_name = FIRMWARE_AR7010; | ||
1033 | else | 1171 | else |
1034 | hif_dev->fw_name = FIRMWARE_AR9271; | 1172 | hif_dev->fw_name = FIRMWARE_AR9271; |
1035 | 1173 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7b9d863d4035..f59df48a86e2 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | /* FIXME: Verify these numbers (with Windows) */ | 32 | /* FIXME: Verify these numbers (with Windows) */ |
33 | #define MAX_TX_URB_NUM 8 | 33 | #define MAX_TX_URB_NUM 8 |
34 | #define MAX_TX_BUF_NUM 1024 | 34 | #define MAX_TX_BUF_NUM 256 |
35 | #define MAX_TX_BUF_SIZE 32768 | 35 | #define MAX_TX_BUF_SIZE 32768 |
36 | #define MAX_TX_AGGR_NUM 20 | 36 | #define MAX_TX_AGGR_NUM 20 |
37 | 37 | ||
@@ -40,7 +40,7 @@ | |||
40 | #define MAX_PKT_NUM_IN_TRANSFER 10 | 40 | #define MAX_PKT_NUM_IN_TRANSFER 10 |
41 | 41 | ||
42 | #define MAX_REG_OUT_URB_NUM 1 | 42 | #define MAX_REG_OUT_URB_NUM 1 |
43 | #define MAX_REG_OUT_BUF_NUM 8 | 43 | #define MAX_REG_IN_URB_NUM 64 |
44 | 44 | ||
45 | #define MAX_REG_IN_BUF_SIZE 64 | 45 | #define MAX_REG_IN_BUF_SIZE 64 |
46 | 46 | ||
@@ -90,9 +90,10 @@ struct hif_device_usb { | |||
90 | const struct firmware *firmware; | 90 | const struct firmware *firmware; |
91 | struct htc_target *htc_handle; | 91 | struct htc_target *htc_handle; |
92 | struct hif_usb_tx tx; | 92 | struct hif_usb_tx tx; |
93 | struct urb *reg_in_urb; | ||
94 | struct usb_anchor regout_submitted; | 93 | struct usb_anchor regout_submitted; |
95 | struct usb_anchor rx_submitted; | 94 | struct usb_anchor rx_submitted; |
95 | struct usb_anchor reg_in_submitted; | ||
96 | struct usb_anchor mgmt_submitted; | ||
96 | struct sk_buff *remain_skb; | 97 | struct sk_buff *remain_skb; |
97 | const char *fw_name; | 98 | const char *fw_name; |
98 | int rx_remain_len; | 99 | int rx_remain_len; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index ec47be94b74f..48a885575085 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -67,8 +67,11 @@ enum htc_opmode { | |||
67 | }; | 67 | }; |
68 | 68 | ||
69 | #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) | 69 | #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) |
70 | #define ATH9K_HTC_AMPDU 1 | 70 | |
71 | #define ATH9K_HTC_AMPDU 1 | ||
71 | #define ATH9K_HTC_NORMAL 2 | 72 | #define ATH9K_HTC_NORMAL 2 |
73 | #define ATH9K_HTC_BEACON 3 | ||
74 | #define ATH9K_HTC_MGMT 4 | ||
72 | 75 | ||
73 | #define ATH9K_HTC_TX_CTSONLY 0x1 | 76 | #define ATH9K_HTC_TX_CTSONLY 0x1 |
74 | #define ATH9K_HTC_TX_RTSCTS 0x2 | 77 | #define ATH9K_HTC_TX_RTSCTS 0x2 |
@@ -82,7 +85,8 @@ struct tx_frame_hdr { | |||
82 | __be32 flags; /* ATH9K_HTC_TX_* */ | 85 | __be32 flags; /* ATH9K_HTC_TX_* */ |
83 | u8 key_type; | 86 | u8 key_type; |
84 | u8 keyix; | 87 | u8 keyix; |
85 | u8 reserved[26]; | 88 | u8 cookie; |
89 | u8 pad; | ||
86 | } __packed; | 90 | } __packed; |
87 | 91 | ||
88 | struct tx_mgmt_hdr { | 92 | struct tx_mgmt_hdr { |
@@ -92,26 +96,16 @@ struct tx_mgmt_hdr { | |||
92 | u8 flags; | 96 | u8 flags; |
93 | u8 key_type; | 97 | u8 key_type; |
94 | u8 keyix; | 98 | u8 keyix; |
95 | u16 reserved; | 99 | u8 cookie; |
100 | u8 pad; | ||
96 | } __packed; | 101 | } __packed; |
97 | 102 | ||
98 | struct tx_beacon_header { | 103 | struct tx_beacon_header { |
99 | u8 len_changed; | ||
100 | u8 vif_index; | 104 | u8 vif_index; |
105 | u8 len_changed; | ||
101 | u16 rev; | 106 | u16 rev; |
102 | } __packed; | 107 | } __packed; |
103 | 108 | ||
104 | struct ath9k_htc_target_hw { | ||
105 | u32 flags; | ||
106 | u32 flags_ext; | ||
107 | u32 ampdu_limit; | ||
108 | u8 ampdu_subframes; | ||
109 | u8 tx_chainmask; | ||
110 | u8 tx_chainmask_legacy; | ||
111 | u8 rtscts_ratecode; | ||
112 | u8 protmode; | ||
113 | } __packed; | ||
114 | |||
115 | struct ath9k_htc_cap_target { | 109 | struct ath9k_htc_cap_target { |
116 | u32 flags; | 110 | u32 flags; |
117 | u32 flags_ext; | 111 | u32 flags_ext; |
@@ -121,21 +115,16 @@ struct ath9k_htc_cap_target { | |||
121 | u8 tx_chainmask_legacy; | 115 | u8 tx_chainmask_legacy; |
122 | u8 rtscts_ratecode; | 116 | u8 rtscts_ratecode; |
123 | u8 protmode; | 117 | u8 protmode; |
118 | u8 pad; | ||
124 | } __packed; | 119 | } __packed; |
125 | 120 | ||
126 | struct ath9k_htc_target_vif { | 121 | struct ath9k_htc_target_vif { |
127 | u8 index; | 122 | u8 index; |
128 | u8 des_bssid[ETH_ALEN]; | 123 | u8 opmode; |
129 | __be32 opmode; | ||
130 | u8 myaddr[ETH_ALEN]; | 124 | u8 myaddr[ETH_ALEN]; |
131 | u8 bssid[ETH_ALEN]; | ||
132 | u32 flags; | ||
133 | u32 flags_ext; | ||
134 | u16 ps_sta; | ||
135 | __be16 rtsthreshold; | ||
136 | u8 ath_cap; | 125 | u8 ath_cap; |
137 | u8 node; | 126 | __be16 rtsthreshold; |
138 | s8 mcast_rate; | 127 | u8 pad; |
139 | } __packed; | 128 | } __packed; |
140 | 129 | ||
141 | #define ATH_HTC_STA_AUTH 0x0001 | 130 | #define ATH_HTC_STA_AUTH 0x0001 |
@@ -143,27 +132,16 @@ struct ath9k_htc_target_vif { | |||
143 | #define ATH_HTC_STA_ERP 0x0004 | 132 | #define ATH_HTC_STA_ERP 0x0004 |
144 | #define ATH_HTC_STA_HT 0x0008 | 133 | #define ATH_HTC_STA_HT 0x0008 |
145 | 134 | ||
146 | /* FIXME: UAPSD variables */ | ||
147 | struct ath9k_htc_target_sta { | 135 | struct ath9k_htc_target_sta { |
148 | u16 associd; | ||
149 | u16 txpower; | ||
150 | u32 ucastkey; | ||
151 | u8 macaddr[ETH_ALEN]; | 136 | u8 macaddr[ETH_ALEN]; |
152 | u8 bssid[ETH_ALEN]; | 137 | u8 bssid[ETH_ALEN]; |
153 | u8 sta_index; | 138 | u8 sta_index; |
154 | u8 vif_index; | 139 | u8 vif_index; |
155 | u8 vif_sta; | ||
156 | __be16 flags; /* ATH_HTC_STA_* */ | ||
157 | u16 htcap; | ||
158 | u8 valid; | ||
159 | u16 capinfo; | ||
160 | struct ath9k_htc_target_hw *hw; | ||
161 | struct ath9k_htc_target_vif *vif; | ||
162 | u16 txseqmgmt; | ||
163 | u8 is_vif_sta; | 140 | u8 is_vif_sta; |
164 | u16 maxampdu; | 141 | __be16 flags; /* ATH_HTC_STA_* */ |
165 | u16 iv16; | 142 | __be16 htcap; |
166 | u32 iv32; | 143 | __be16 maxampdu; |
144 | u8 pad; | ||
167 | } __packed; | 145 | } __packed; |
168 | 146 | ||
169 | struct ath9k_htc_target_aggr { | 147 | struct ath9k_htc_target_aggr { |
@@ -197,12 +175,31 @@ struct ath9k_htc_target_rate { | |||
197 | struct ath9k_htc_rate rates; | 175 | struct ath9k_htc_rate rates; |
198 | }; | 176 | }; |
199 | 177 | ||
200 | struct ath9k_htc_target_stats { | 178 | struct ath9k_htc_target_int_stats { |
201 | __be32 tx_shortretry; | 179 | __be32 rx; |
202 | __be32 tx_longretry; | 180 | __be32 rxorn; |
203 | __be32 tx_xretries; | 181 | __be32 rxeol; |
204 | __be32 ht_txunaggr_xretry; | 182 | __be32 txurn; |
205 | __be32 ht_tx_xretries; | 183 | __be32 txto; |
184 | __be32 cst; | ||
185 | } __packed; | ||
186 | |||
187 | struct ath9k_htc_target_tx_stats { | ||
188 | __be32 xretries; | ||
189 | __be32 fifoerr; | ||
190 | __be32 filtered; | ||
191 | __be32 timer_exp; | ||
192 | __be32 shortretries; | ||
193 | __be32 longretries; | ||
194 | __be32 qnull; | ||
195 | __be32 encap_fail; | ||
196 | __be32 nobuf; | ||
197 | } __packed; | ||
198 | |||
199 | struct ath9k_htc_target_rx_stats { | ||
200 | __be32 nobuf; | ||
201 | __be32 host_send; | ||
202 | __be32 host_done; | ||
206 | } __packed; | 203 | } __packed; |
207 | 204 | ||
208 | #define ATH9K_HTC_MAX_VIF 2 | 205 | #define ATH9K_HTC_MAX_VIF 2 |
@@ -244,6 +241,8 @@ struct ath9k_htc_vif { | |||
244 | u8 index; | 241 | u8 index; |
245 | u16 seq_no; | 242 | u16 seq_no; |
246 | bool beacon_configured; | 243 | bool beacon_configured; |
244 | int bslot; | ||
245 | __le64 tsfadjust; | ||
247 | }; | 246 | }; |
248 | 247 | ||
249 | struct ath9k_vif_iter_data { | 248 | struct ath9k_vif_iter_data { |
@@ -282,23 +281,65 @@ struct ath9k_htc_rx { | |||
282 | spinlock_t rxbuflock; | 281 | spinlock_t rxbuflock; |
283 | }; | 282 | }; |
284 | 283 | ||
284 | #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ | ||
285 | #define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */ | ||
286 | #define ATH9K_HTC_TX_RESERVE 10 | ||
287 | #define ATH9K_HTC_TX_TIMEOUT_COUNT 20 | ||
288 | #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) | ||
289 | |||
290 | #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) | ||
291 | #define ATH9K_HTC_OP_TX_DRAIN BIT(1) | ||
292 | |||
293 | struct ath9k_htc_tx { | ||
294 | u8 flags; | ||
295 | int queued_cnt; | ||
296 | struct sk_buff_head mgmt_ep_queue; | ||
297 | struct sk_buff_head cab_ep_queue; | ||
298 | struct sk_buff_head data_be_queue; | ||
299 | struct sk_buff_head data_bk_queue; | ||
300 | struct sk_buff_head data_vi_queue; | ||
301 | struct sk_buff_head data_vo_queue; | ||
302 | struct sk_buff_head tx_failed; | ||
303 | DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); | ||
304 | struct timer_list cleanup_timer; | ||
305 | spinlock_t tx_lock; | ||
306 | }; | ||
307 | |||
285 | struct ath9k_htc_tx_ctl { | 308 | struct ath9k_htc_tx_ctl { |
286 | u8 type; /* ATH9K_HTC_* */ | 309 | u8 type; /* ATH9K_HTC_* */ |
310 | u8 epid; | ||
311 | u8 txok; | ||
312 | u8 sta_idx; | ||
313 | unsigned long timestamp; | ||
287 | }; | 314 | }; |
288 | 315 | ||
316 | static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) | ||
317 | { | ||
318 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
319 | |||
320 | BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) > | ||
321 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE); | ||
322 | return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data; | ||
323 | } | ||
324 | |||
289 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 325 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
290 | 326 | ||
291 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) | 327 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) |
292 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) | 328 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) |
329 | #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ | ||
293 | 330 | ||
294 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) | 331 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) |
295 | 332 | ||
333 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
334 | struct ath_htc_rx_status *rxs); | ||
335 | |||
296 | struct ath_tx_stats { | 336 | struct ath_tx_stats { |
297 | u32 buf_queued; | 337 | u32 buf_queued; |
298 | u32 buf_completed; | 338 | u32 buf_completed; |
299 | u32 skb_queued; | 339 | u32 skb_queued; |
300 | u32 skb_completed; | 340 | u32 skb_success; |
301 | u32 skb_dropped; | 341 | u32 skb_failed; |
342 | u32 cab_queued; | ||
302 | u32 queue_stats[WME_NUM_AC]; | 343 | u32 queue_stats[WME_NUM_AC]; |
303 | }; | 344 | }; |
304 | 345 | ||
@@ -306,25 +347,35 @@ struct ath_rx_stats { | |||
306 | u32 skb_allocated; | 347 | u32 skb_allocated; |
307 | u32 skb_completed; | 348 | u32 skb_completed; |
308 | u32 skb_dropped; | 349 | u32 skb_dropped; |
350 | u32 err_crc; | ||
351 | u32 err_decrypt_crc; | ||
352 | u32 err_mic; | ||
353 | u32 err_pre_delim; | ||
354 | u32 err_post_delim; | ||
355 | u32 err_decrypt_busy; | ||
356 | u32 err_phy; | ||
357 | u32 err_phy_stats[ATH9K_PHYERR_MAX]; | ||
309 | }; | 358 | }; |
310 | 359 | ||
311 | struct ath9k_debug { | 360 | struct ath9k_debug { |
312 | struct dentry *debugfs_phy; | 361 | struct dentry *debugfs_phy; |
313 | struct dentry *debugfs_tgt_stats; | ||
314 | struct dentry *debugfs_xmit; | ||
315 | struct dentry *debugfs_recv; | ||
316 | struct ath_tx_stats tx_stats; | 362 | struct ath_tx_stats tx_stats; |
317 | struct ath_rx_stats rx_stats; | 363 | struct ath_rx_stats rx_stats; |
318 | u32 txrate; | ||
319 | }; | 364 | }; |
320 | 365 | ||
321 | #else | 366 | #else |
322 | 367 | ||
323 | #define TX_STAT_INC(c) do { } while (0) | 368 | #define TX_STAT_INC(c) do { } while (0) |
324 | #define RX_STAT_INC(c) do { } while (0) | 369 | #define RX_STAT_INC(c) do { } while (0) |
370 | #define CAB_STAT_INC do { } while (0) | ||
325 | 371 | ||
326 | #define TX_QSTAT_INC(c) do { } while (0) | 372 | #define TX_QSTAT_INC(c) do { } while (0) |
327 | 373 | ||
374 | static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
375 | struct ath_htc_rx_status *rxs) | ||
376 | { | ||
377 | } | ||
378 | |||
328 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 379 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
329 | 380 | ||
330 | #define ATH_LED_PIN_DEF 1 | 381 | #define ATH_LED_PIN_DEF 1 |
@@ -351,10 +402,21 @@ struct ath_led { | |||
351 | int brightness; | 402 | int brightness; |
352 | }; | 403 | }; |
353 | 404 | ||
405 | #define BSTUCK_THRESHOLD 10 | ||
406 | |||
407 | /* | ||
408 | * Adjust these when the max. no of beaconing interfaces is | ||
409 | * increased. | ||
410 | */ | ||
411 | #define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ | ||
412 | #define MIN_SWBA_RESPONSE 10 /* in TUs */ | ||
413 | |||
354 | struct htc_beacon_config { | 414 | struct htc_beacon_config { |
415 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; | ||
355 | u16 beacon_interval; | 416 | u16 beacon_interval; |
356 | u16 dtim_period; | 417 | u16 dtim_period; |
357 | u16 bmiss_timeout; | 418 | u16 bmiss_timeout; |
419 | u32 bmiss_cnt; | ||
358 | }; | 420 | }; |
359 | 421 | ||
360 | struct ath_btcoex { | 422 | struct ath_btcoex { |
@@ -388,6 +450,9 @@ struct ath9k_htc_priv { | |||
388 | struct htc_target *htc; | 450 | struct htc_target *htc; |
389 | struct wmi *wmi; | 451 | struct wmi *wmi; |
390 | 452 | ||
453 | u16 fw_version_major; | ||
454 | u16 fw_version_minor; | ||
455 | |||
391 | enum htc_endpoint_id wmi_cmd_ep; | 456 | enum htc_endpoint_id wmi_cmd_ep; |
392 | enum htc_endpoint_id beacon_ep; | 457 | enum htc_endpoint_id beacon_ep; |
393 | enum htc_endpoint_id cab_ep; | 458 | enum htc_endpoint_id cab_ep; |
@@ -411,27 +476,23 @@ struct ath9k_htc_priv { | |||
411 | u16 txpowlimit; | 476 | u16 txpowlimit; |
412 | u16 nvifs; | 477 | u16 nvifs; |
413 | u16 nstations; | 478 | u16 nstations; |
414 | u32 bmiss_cnt; | ||
415 | bool rearm_ani; | 479 | bool rearm_ani; |
416 | bool reconfig_beacon; | 480 | bool reconfig_beacon; |
481 | unsigned int rxfilter; | ||
417 | 482 | ||
418 | struct ath9k_hw_cal_data caldata; | 483 | struct ath9k_hw_cal_data caldata; |
484 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
419 | 485 | ||
420 | spinlock_t beacon_lock; | 486 | spinlock_t beacon_lock; |
487 | struct htc_beacon_config cur_beacon_conf; | ||
421 | 488 | ||
422 | bool tx_queues_stop; | 489 | struct ath9k_htc_rx rx; |
423 | spinlock_t tx_lock; | 490 | struct ath9k_htc_tx tx; |
424 | 491 | ||
425 | struct ieee80211_vif *vif; | ||
426 | struct htc_beacon_config cur_beacon_conf; | ||
427 | unsigned int rxfilter; | ||
428 | struct tasklet_struct swba_tasklet; | 492 | struct tasklet_struct swba_tasklet; |
429 | struct tasklet_struct rx_tasklet; | 493 | struct tasklet_struct rx_tasklet; |
430 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
431 | struct ath9k_htc_rx rx; | ||
432 | struct tasklet_struct tx_tasklet; | ||
433 | struct sk_buff_head tx_queue; | ||
434 | struct delayed_work ani_work; | 494 | struct delayed_work ani_work; |
495 | struct tasklet_struct tx_failed_tasklet; | ||
435 | struct work_struct ps_work; | 496 | struct work_struct ps_work; |
436 | struct work_struct fatal_work; | 497 | struct work_struct fatal_work; |
437 | 498 | ||
@@ -470,11 +531,18 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
470 | 531 | ||
471 | void ath9k_htc_reset(struct ath9k_htc_priv *priv); | 532 | void ath9k_htc_reset(struct ath9k_htc_priv *priv); |
472 | 533 | ||
534 | void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, | ||
535 | struct ieee80211_vif *vif); | ||
536 | void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, | ||
537 | struct ieee80211_vif *vif); | ||
538 | void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, | ||
539 | struct ieee80211_vif *vif); | ||
473 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); | 540 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); |
474 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 541 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
475 | struct ieee80211_vif *vif); | 542 | struct ieee80211_vif *vif); |
476 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); | 543 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); |
477 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | 544 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, |
545 | struct wmi_event_swba *swba); | ||
478 | 546 | ||
479 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, | 547 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, |
480 | enum htc_endpoint_id ep_id); | 548 | enum htc_endpoint_id ep_id); |
@@ -491,14 +559,23 @@ void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); | |||
491 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); | 559 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); |
492 | 560 | ||
493 | int ath9k_tx_init(struct ath9k_htc_priv *priv); | 561 | int ath9k_tx_init(struct ath9k_htc_priv *priv); |
494 | void ath9k_tx_tasklet(unsigned long data); | 562 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, |
495 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); | 563 | struct sk_buff *skb, u8 slot, bool is_cab); |
496 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); | 564 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); |
497 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); | 565 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); |
498 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); | 566 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); |
499 | int get_hw_qnum(u16 queue, int *hwq_map); | 567 | int get_hw_qnum(u16 queue, int *hwq_map); |
500 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 568 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
501 | struct ath9k_tx_queue_info *qinfo); | 569 | struct ath9k_tx_queue_info *qinfo); |
570 | void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); | ||
571 | void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); | ||
572 | int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); | ||
573 | void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); | ||
574 | void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); | ||
575 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); | ||
576 | void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); | ||
577 | void ath9k_tx_failed_tasklet(unsigned long data); | ||
578 | void ath9k_htc_tx_cleanup_timer(unsigned long data); | ||
502 | 579 | ||
503 | int ath9k_rx_init(struct ath9k_htc_priv *priv); | 580 | int ath9k_rx_init(struct ath9k_htc_priv *priv); |
504 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); | 581 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); |
@@ -528,15 +605,9 @@ void ath9k_htc_suspend(struct htc_target *htc_handle); | |||
528 | int ath9k_htc_resume(struct htc_target *htc_handle); | 605 | int ath9k_htc_resume(struct htc_target *htc_handle); |
529 | #endif | 606 | #endif |
530 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 607 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
531 | int ath9k_htc_debug_create_root(void); | ||
532 | void ath9k_htc_debug_remove_root(void); | ||
533 | int ath9k_htc_init_debug(struct ath_hw *ah); | 608 | int ath9k_htc_init_debug(struct ath_hw *ah); |
534 | void ath9k_htc_exit_debug(struct ath_hw *ah); | ||
535 | #else | 609 | #else |
536 | static inline int ath9k_htc_debug_create_root(void) { return 0; }; | ||
537 | static inline void ath9k_htc_debug_remove_root(void) {}; | ||
538 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; | 610 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; |
539 | static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; | ||
540 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 611 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
541 | 612 | ||
542 | #endif /* HTC_H */ | 613 | #endif /* HTC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 8f56158e5887..a157107b3f3b 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -18,6 +18,50 @@ | |||
18 | 18 | ||
19 | #define FUDGE 2 | 19 | #define FUDGE 2 |
20 | 20 | ||
21 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | ||
22 | { | ||
23 | struct ath_hw *ah = priv->ah; | ||
24 | struct ath9k_tx_queue_info qi, qi_be; | ||
25 | |||
26 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
27 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | ||
28 | |||
29 | ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); | ||
30 | |||
31 | if (priv->ah->opmode == NL80211_IFTYPE_AP) { | ||
32 | qi.tqi_aifs = 1; | ||
33 | qi.tqi_cwmin = 0; | ||
34 | qi.tqi_cwmax = 0; | ||
35 | } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { | ||
36 | int qnum = priv->hwq_map[WME_AC_BE]; | ||
37 | |||
38 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | ||
39 | |||
40 | qi.tqi_aifs = qi_be.tqi_aifs; | ||
41 | |||
42 | /* | ||
43 | * For WIFI Beacon Distribution | ||
44 | * Long slot time : 2x cwmin | ||
45 | * Short slot time : 4x cwmin | ||
46 | */ | ||
47 | if (ah->slottime == ATH9K_SLOT_TIME_20) | ||
48 | qi.tqi_cwmin = 2*qi_be.tqi_cwmin; | ||
49 | else | ||
50 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
51 | |||
52 | qi.tqi_cwmax = qi_be.tqi_cwmax; | ||
53 | |||
54 | } | ||
55 | |||
56 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | ||
57 | ath_err(ath9k_hw_common(ah), | ||
58 | "Unable to update beacon queue %u!\n", priv->beaconq); | ||
59 | } else { | ||
60 | ath9k_hw_resettxqueue(ah, priv->beaconq); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | |||
21 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | 65 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, |
22 | struct htc_beacon_config *bss_conf) | 66 | struct htc_beacon_config *bss_conf) |
23 | { | 67 | { |
@@ -154,6 +198,15 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
154 | intval /= ATH9K_HTC_MAX_BCN_VIF; | 198 | intval /= ATH9K_HTC_MAX_BCN_VIF; |
155 | nexttbtt = intval; | 199 | nexttbtt = intval; |
156 | 200 | ||
201 | /* | ||
202 | * To reduce beacon misses under heavy TX load, | ||
203 | * set the beacon response time to a larger value. | ||
204 | */ | ||
205 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
206 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
207 | else | ||
208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
209 | |||
157 | if (priv->op_flags & OP_TSF_RESET) { | 210 | if (priv->op_flags & OP_TSF_RESET) { |
158 | ath9k_hw_reset_tsf(priv->ah); | 211 | ath9k_hw_reset_tsf(priv->ah); |
159 | priv->op_flags &= ~OP_TSF_RESET; | 212 | priv->op_flags &= ~OP_TSF_RESET; |
@@ -172,12 +225,16 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | |||
172 | imask |= ATH9K_INT_SWBA; | 225 | imask |= ATH9K_INT_SWBA; |
173 | 226 | ||
174 | ath_dbg(common, ATH_DBG_CONFIG, | 227 | ath_dbg(common, ATH_DBG_CONFIG, |
175 | "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", | 228 | "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " |
176 | bss_conf->beacon_interval, nexttbtt, imask); | 229 | "imask: 0x%x\n", |
230 | bss_conf->beacon_interval, nexttbtt, | ||
231 | priv->ah->config.sw_beacon_response_time, imask); | ||
232 | |||
233 | ath9k_htc_beaconq_config(priv); | ||
177 | 234 | ||
178 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 235 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
179 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | 236 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
180 | priv->bmiss_cnt = 0; | 237 | priv->cur_beacon_conf.bmiss_cnt = 0; |
181 | htc_imask = cpu_to_be32(imask); | 238 | htc_imask = cpu_to_be32(imask); |
182 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 239 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
183 | } | 240 | } |
@@ -205,16 +262,26 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | |||
205 | nexttbtt += intval; | 262 | nexttbtt += intval; |
206 | } while (nexttbtt < tsftu); | 263 | } while (nexttbtt < tsftu); |
207 | 264 | ||
265 | /* | ||
266 | * Only one IBSS interfce is allowed. | ||
267 | */ | ||
268 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
269 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
270 | else | ||
271 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
272 | |||
208 | if (priv->op_flags & OP_ENABLE_BEACON) | 273 | if (priv->op_flags & OP_ENABLE_BEACON) |
209 | imask |= ATH9K_INT_SWBA; | 274 | imask |= ATH9K_INT_SWBA; |
210 | 275 | ||
211 | ath_dbg(common, ATH_DBG_CONFIG, | 276 | ath_dbg(common, ATH_DBG_CONFIG, |
212 | "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", | 277 | "IBSS Beacon config, intval: %d, nexttbtt: %u, " |
213 | bss_conf->beacon_interval, nexttbtt, imask); | 278 | "resp_time: %d, imask: 0x%x\n", |
279 | bss_conf->beacon_interval, nexttbtt, | ||
280 | priv->ah->config.sw_beacon_response_time, imask); | ||
214 | 281 | ||
215 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 282 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
216 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | 283 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
217 | priv->bmiss_cnt = 0; | 284 | priv->cur_beacon_conf.bmiss_cnt = 0; |
218 | htc_imask = cpu_to_be32(imask); | 285 | htc_imask = cpu_to_be32(imask); |
219 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 286 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
220 | } | 287 | } |
@@ -225,38 +292,101 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, | |||
225 | dev_kfree_skb_any(skb); | 292 | dev_kfree_skb_any(skb); |
226 | } | 293 | } |
227 | 294 | ||
228 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | 295 | static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, |
296 | int slot) | ||
297 | { | ||
298 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
299 | struct ieee80211_vif *vif; | ||
300 | struct sk_buff *skb; | ||
301 | struct ieee80211_hdr *hdr; | ||
302 | int padpos, padsize, ret, tx_slot; | ||
303 | |||
304 | spin_lock_bh(&priv->beacon_lock); | ||
305 | |||
306 | vif = priv->cur_beacon_conf.bslot[slot]; | ||
307 | |||
308 | skb = ieee80211_get_buffered_bc(priv->hw, vif); | ||
309 | |||
310 | while(skb) { | ||
311 | hdr = (struct ieee80211_hdr *) skb->data; | ||
312 | |||
313 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
314 | padsize = padpos & 3; | ||
315 | if (padsize && skb->len > padpos) { | ||
316 | if (skb_headroom(skb) < padsize) { | ||
317 | dev_kfree_skb_any(skb); | ||
318 | goto next; | ||
319 | } | ||
320 | skb_push(skb, padsize); | ||
321 | memmove(skb->data, skb->data + padsize, padpos); | ||
322 | } | ||
323 | |||
324 | tx_slot = ath9k_htc_tx_get_slot(priv); | ||
325 | if (tx_slot < 0) { | ||
326 | ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); | ||
327 | dev_kfree_skb_any(skb); | ||
328 | goto next; | ||
329 | } | ||
330 | |||
331 | ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); | ||
332 | if (ret != 0) { | ||
333 | ath9k_htc_tx_clear_slot(priv, tx_slot); | ||
334 | dev_kfree_skb_any(skb); | ||
335 | |||
336 | ath_dbg(common, ATH_DBG_XMIT, | ||
337 | "Failed to send CAB frame\n"); | ||
338 | } else { | ||
339 | spin_lock_bh(&priv->tx.tx_lock); | ||
340 | priv->tx.queued_cnt++; | ||
341 | spin_unlock_bh(&priv->tx.tx_lock); | ||
342 | } | ||
343 | next: | ||
344 | skb = ieee80211_get_buffered_bc(priv->hw, vif); | ||
345 | } | ||
346 | |||
347 | spin_unlock_bh(&priv->beacon_lock); | ||
348 | } | ||
349 | |||
350 | static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | ||
351 | int slot) | ||
229 | { | 352 | { |
230 | struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; | 353 | struct ath_common *common = ath9k_hw_common(priv->ah); |
354 | struct ieee80211_vif *vif; | ||
355 | struct ath9k_htc_vif *avp; | ||
231 | struct tx_beacon_header beacon_hdr; | 356 | struct tx_beacon_header beacon_hdr; |
232 | struct ath9k_htc_tx_ctl tx_ctl; | 357 | struct ath9k_htc_tx_ctl *tx_ctl; |
233 | struct ieee80211_tx_info *info; | 358 | struct ieee80211_tx_info *info; |
359 | struct ieee80211_mgmt *mgmt; | ||
234 | struct sk_buff *beacon; | 360 | struct sk_buff *beacon; |
235 | u8 *tx_fhdr; | 361 | u8 *tx_fhdr; |
362 | int ret; | ||
236 | 363 | ||
237 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); | 364 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); |
238 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | ||
239 | |||
240 | /* FIXME: Handle BMISS */ | ||
241 | if (beacon_pending != 0) { | ||
242 | priv->bmiss_cnt++; | ||
243 | return; | ||
244 | } | ||
245 | 365 | ||
246 | spin_lock_bh(&priv->beacon_lock); | 366 | spin_lock_bh(&priv->beacon_lock); |
247 | 367 | ||
368 | vif = priv->cur_beacon_conf.bslot[slot]; | ||
369 | avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
370 | |||
248 | if (unlikely(priv->op_flags & OP_SCANNING)) { | 371 | if (unlikely(priv->op_flags & OP_SCANNING)) { |
249 | spin_unlock_bh(&priv->beacon_lock); | 372 | spin_unlock_bh(&priv->beacon_lock); |
250 | return; | 373 | return; |
251 | } | 374 | } |
252 | 375 | ||
253 | /* Get a new beacon */ | 376 | /* Get a new beacon */ |
254 | beacon = ieee80211_beacon_get(priv->hw, priv->vif); | 377 | beacon = ieee80211_beacon_get(priv->hw, vif); |
255 | if (!beacon) { | 378 | if (!beacon) { |
256 | spin_unlock_bh(&priv->beacon_lock); | 379 | spin_unlock_bh(&priv->beacon_lock); |
257 | return; | 380 | return; |
258 | } | 381 | } |
259 | 382 | ||
383 | /* | ||
384 | * Update the TSF adjust value here, the HW will | ||
385 | * add this value for every beacon. | ||
386 | */ | ||
387 | mgmt = (struct ieee80211_mgmt *)beacon->data; | ||
388 | mgmt->u.beacon.timestamp = avp->tsfadjust; | ||
389 | |||
260 | info = IEEE80211_SKB_CB(beacon); | 390 | info = IEEE80211_SKB_CB(beacon); |
261 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 391 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
262 | struct ieee80211_hdr *hdr = | 392 | struct ieee80211_hdr *hdr = |
@@ -266,45 +396,149 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | |||
266 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); | 396 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
267 | } | 397 | } |
268 | 398 | ||
269 | tx_ctl.type = ATH9K_HTC_NORMAL; | 399 | tx_ctl = HTC_SKB_CB(beacon); |
400 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
401 | |||
402 | tx_ctl->type = ATH9K_HTC_BEACON; | ||
403 | tx_ctl->epid = priv->beacon_ep; | ||
404 | |||
270 | beacon_hdr.vif_index = avp->index; | 405 | beacon_hdr.vif_index = avp->index; |
271 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); | 406 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); |
272 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); | 407 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); |
273 | 408 | ||
274 | htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); | 409 | ret = htc_send(priv->htc, beacon); |
410 | if (ret != 0) { | ||
411 | if (ret == -ENOMEM) { | ||
412 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
413 | "Failed to send beacon, no free TX buffer\n"); | ||
414 | } | ||
415 | dev_kfree_skb_any(beacon); | ||
416 | } | ||
417 | |||
418 | spin_unlock_bh(&priv->beacon_lock); | ||
419 | } | ||
420 | |||
421 | static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, | ||
422 | struct wmi_event_swba *swba) | ||
423 | { | ||
424 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
425 | u64 tsf; | ||
426 | u32 tsftu; | ||
427 | u16 intval; | ||
428 | int slot; | ||
429 | |||
430 | intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; | ||
275 | 431 | ||
432 | tsf = be64_to_cpu(swba->tsf); | ||
433 | tsftu = TSF_TO_TU(tsf >> 32, tsf); | ||
434 | slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; | ||
435 | slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; | ||
436 | |||
437 | ath_dbg(common, ATH_DBG_BEACON, | ||
438 | "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", | ||
439 | slot, tsf, tsftu, intval); | ||
440 | |||
441 | return slot; | ||
442 | } | ||
443 | |||
444 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, | ||
445 | struct wmi_event_swba *swba) | ||
446 | { | ||
447 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
448 | int slot; | ||
449 | |||
450 | if (swba->beacon_pending != 0) { | ||
451 | priv->cur_beacon_conf.bmiss_cnt++; | ||
452 | if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { | ||
453 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
454 | "Beacon stuck, HW reset\n"); | ||
455 | ieee80211_queue_work(priv->hw, | ||
456 | &priv->fatal_work); | ||
457 | } | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | if (priv->cur_beacon_conf.bmiss_cnt) { | ||
462 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
463 | "Resuming beacon xmit after %u misses\n", | ||
464 | priv->cur_beacon_conf.bmiss_cnt); | ||
465 | priv->cur_beacon_conf.bmiss_cnt = 0; | ||
466 | } | ||
467 | |||
468 | slot = ath9k_htc_choose_bslot(priv, swba); | ||
469 | spin_lock_bh(&priv->beacon_lock); | ||
470 | if (priv->cur_beacon_conf.bslot[slot] == NULL) { | ||
471 | spin_unlock_bh(&priv->beacon_lock); | ||
472 | return; | ||
473 | } | ||
276 | spin_unlock_bh(&priv->beacon_lock); | 474 | spin_unlock_bh(&priv->beacon_lock); |
475 | |||
476 | ath9k_htc_send_buffered(priv, slot); | ||
477 | ath9k_htc_send_beacon(priv, slot); | ||
277 | } | 478 | } |
278 | 479 | ||
279 | /* Currently, only for IBSS */ | 480 | void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, |
280 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | 481 | struct ieee80211_vif *vif) |
281 | { | 482 | { |
282 | struct ath_hw *ah = priv->ah; | 483 | struct ath_common *common = ath9k_hw_common(priv->ah); |
283 | struct ath9k_tx_queue_info qi, qi_be; | 484 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; |
284 | int qnum = priv->hwq_map[WME_AC_BE]; | 485 | int i = 0; |
285 | 486 | ||
286 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 487 | spin_lock_bh(&priv->beacon_lock); |
287 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | 488 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { |
489 | if (priv->cur_beacon_conf.bslot[i] == NULL) { | ||
490 | avp->bslot = i; | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | priv->cur_beacon_conf.bslot[avp->bslot] = vif; | ||
496 | spin_unlock_bh(&priv->beacon_lock); | ||
497 | |||
498 | ath_dbg(common, ATH_DBG_CONFIG, | ||
499 | "Added interface at beacon slot: %d\n", avp->bslot); | ||
500 | } | ||
501 | |||
502 | void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, | ||
503 | struct ieee80211_vif *vif) | ||
504 | { | ||
505 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
506 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
507 | |||
508 | spin_lock_bh(&priv->beacon_lock); | ||
509 | priv->cur_beacon_conf.bslot[avp->bslot] = NULL; | ||
510 | spin_unlock_bh(&priv->beacon_lock); | ||
511 | |||
512 | ath_dbg(common, ATH_DBG_CONFIG, | ||
513 | "Removed interface at beacon slot: %d\n", avp->bslot); | ||
514 | } | ||
288 | 515 | ||
289 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | 516 | /* |
517 | * Calculate the TSF adjustment value for all slots | ||
518 | * other than zero. | ||
519 | */ | ||
520 | void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, | ||
521 | struct ieee80211_vif *vif) | ||
522 | { | ||
523 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
524 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
525 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
526 | u64 tsfadjust; | ||
527 | |||
528 | if (avp->bslot == 0) | ||
529 | return; | ||
290 | 530 | ||
291 | qi.tqi_aifs = qi_be.tqi_aifs; | 531 | /* |
292 | /* For WIFI Beacon Distribution | 532 | * The beacon interval cannot be different for multi-AP mode, |
293 | * Long slot time : 2x cwmin | 533 | * and we reach here only for VIF slots greater than zero, |
294 | * Short slot time : 4x cwmin | 534 | * so beacon_interval is guaranteed to be set in cur_conf. |
295 | */ | 535 | */ |
296 | if (ah->slottime == ATH9K_SLOT_TIME_20) | 536 | tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; |
297 | qi.tqi_cwmin = 2*qi_be.tqi_cwmin; | 537 | avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); |
298 | else | ||
299 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
300 | qi.tqi_cwmax = qi_be.tqi_cwmax; | ||
301 | 538 | ||
302 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | 539 | ath_dbg(common, ATH_DBG_CONFIG, |
303 | ath_err(ath9k_hw_common(ah), | 540 | "tsfadjust is: %llu for bslot: %d\n", |
304 | "Unable to update beacon queue %u!\n", qnum); | 541 | (unsigned long long)tsfadjust, avp->bslot); |
305 | } else { | ||
306 | ath9k_hw_resettxqueue(ah, priv->beaconq); | ||
307 | } | ||
308 | } | 542 | } |
309 | 543 | ||
310 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 544 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c new file mode 100644 index 000000000000..eca777497fe5 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "htc.h" | ||
18 | |||
19 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
20 | { | ||
21 | file->private_data = inode->i_private; | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, | ||
26 | size_t count, loff_t *ppos) | ||
27 | { | ||
28 | struct ath9k_htc_priv *priv = file->private_data; | ||
29 | struct ath9k_htc_target_int_stats cmd_rsp; | ||
30 | char buf[512]; | ||
31 | unsigned int len = 0; | ||
32 | int ret = 0; | ||
33 | |||
34 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
35 | |||
36 | WMI_CMD(WMI_INT_STATS_CMDID); | ||
37 | if (ret) | ||
38 | return -EINVAL; | ||
39 | |||
40 | len += snprintf(buf + len, sizeof(buf) - len, | ||
41 | "%20s : %10u\n", "RX", | ||
42 | be32_to_cpu(cmd_rsp.rx)); | ||
43 | |||
44 | len += snprintf(buf + len, sizeof(buf) - len, | ||
45 | "%20s : %10u\n", "RXORN", | ||
46 | be32_to_cpu(cmd_rsp.rxorn)); | ||
47 | |||
48 | len += snprintf(buf + len, sizeof(buf) - len, | ||
49 | "%20s : %10u\n", "RXEOL", | ||
50 | be32_to_cpu(cmd_rsp.rxeol)); | ||
51 | |||
52 | len += snprintf(buf + len, sizeof(buf) - len, | ||
53 | "%20s : %10u\n", "TXURN", | ||
54 | be32_to_cpu(cmd_rsp.txurn)); | ||
55 | |||
56 | len += snprintf(buf + len, sizeof(buf) - len, | ||
57 | "%20s : %10u\n", "TXTO", | ||
58 | be32_to_cpu(cmd_rsp.txto)); | ||
59 | |||
60 | len += snprintf(buf + len, sizeof(buf) - len, | ||
61 | "%20s : %10u\n", "CST", | ||
62 | be32_to_cpu(cmd_rsp.cst)); | ||
63 | |||
64 | if (len > sizeof(buf)) | ||
65 | len = sizeof(buf); | ||
66 | |||
67 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
68 | } | ||
69 | |||
70 | static const struct file_operations fops_tgt_int_stats = { | ||
71 | .read = read_file_tgt_int_stats, | ||
72 | .open = ath9k_debugfs_open, | ||
73 | .owner = THIS_MODULE, | ||
74 | .llseek = default_llseek, | ||
75 | }; | ||
76 | |||
77 | static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, | ||
78 | size_t count, loff_t *ppos) | ||
79 | { | ||
80 | struct ath9k_htc_priv *priv = file->private_data; | ||
81 | struct ath9k_htc_target_tx_stats cmd_rsp; | ||
82 | char buf[512]; | ||
83 | unsigned int len = 0; | ||
84 | int ret = 0; | ||
85 | |||
86 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
87 | |||
88 | WMI_CMD(WMI_TX_STATS_CMDID); | ||
89 | if (ret) | ||
90 | return -EINVAL; | ||
91 | |||
92 | len += snprintf(buf + len, sizeof(buf) - len, | ||
93 | "%20s : %10u\n", "Xretries", | ||
94 | be32_to_cpu(cmd_rsp.xretries)); | ||
95 | |||
96 | len += snprintf(buf + len, sizeof(buf) - len, | ||
97 | "%20s : %10u\n", "FifoErr", | ||
98 | be32_to_cpu(cmd_rsp.fifoerr)); | ||
99 | |||
100 | len += snprintf(buf + len, sizeof(buf) - len, | ||
101 | "%20s : %10u\n", "Filtered", | ||
102 | be32_to_cpu(cmd_rsp.filtered)); | ||
103 | |||
104 | len += snprintf(buf + len, sizeof(buf) - len, | ||
105 | "%20s : %10u\n", "TimerExp", | ||
106 | be32_to_cpu(cmd_rsp.timer_exp)); | ||
107 | |||
108 | len += snprintf(buf + len, sizeof(buf) - len, | ||
109 | "%20s : %10u\n", "ShortRetries", | ||
110 | be32_to_cpu(cmd_rsp.shortretries)); | ||
111 | |||
112 | len += snprintf(buf + len, sizeof(buf) - len, | ||
113 | "%20s : %10u\n", "LongRetries", | ||
114 | be32_to_cpu(cmd_rsp.longretries)); | ||
115 | |||
116 | len += snprintf(buf + len, sizeof(buf) - len, | ||
117 | "%20s : %10u\n", "QueueNull", | ||
118 | be32_to_cpu(cmd_rsp.qnull)); | ||
119 | |||
120 | len += snprintf(buf + len, sizeof(buf) - len, | ||
121 | "%20s : %10u\n", "EncapFail", | ||
122 | be32_to_cpu(cmd_rsp.encap_fail)); | ||
123 | |||
124 | len += snprintf(buf + len, sizeof(buf) - len, | ||
125 | "%20s : %10u\n", "NoBuf", | ||
126 | be32_to_cpu(cmd_rsp.nobuf)); | ||
127 | |||
128 | if (len > sizeof(buf)) | ||
129 | len = sizeof(buf); | ||
130 | |||
131 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
132 | } | ||
133 | |||
134 | static const struct file_operations fops_tgt_tx_stats = { | ||
135 | .read = read_file_tgt_tx_stats, | ||
136 | .open = ath9k_debugfs_open, | ||
137 | .owner = THIS_MODULE, | ||
138 | .llseek = default_llseek, | ||
139 | }; | ||
140 | |||
141 | static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, | ||
142 | size_t count, loff_t *ppos) | ||
143 | { | ||
144 | struct ath9k_htc_priv *priv = file->private_data; | ||
145 | struct ath9k_htc_target_rx_stats cmd_rsp; | ||
146 | char buf[512]; | ||
147 | unsigned int len = 0; | ||
148 | int ret = 0; | ||
149 | |||
150 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
151 | |||
152 | WMI_CMD(WMI_RX_STATS_CMDID); | ||
153 | if (ret) | ||
154 | return -EINVAL; | ||
155 | |||
156 | len += snprintf(buf + len, sizeof(buf) - len, | ||
157 | "%20s : %10u\n", "NoBuf", | ||
158 | be32_to_cpu(cmd_rsp.nobuf)); | ||
159 | |||
160 | len += snprintf(buf + len, sizeof(buf) - len, | ||
161 | "%20s : %10u\n", "HostSend", | ||
162 | be32_to_cpu(cmd_rsp.host_send)); | ||
163 | |||
164 | len += snprintf(buf + len, sizeof(buf) - len, | ||
165 | "%20s : %10u\n", "HostDone", | ||
166 | be32_to_cpu(cmd_rsp.host_done)); | ||
167 | |||
168 | if (len > sizeof(buf)) | ||
169 | len = sizeof(buf); | ||
170 | |||
171 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
172 | } | ||
173 | |||
174 | static const struct file_operations fops_tgt_rx_stats = { | ||
175 | .read = read_file_tgt_rx_stats, | ||
176 | .open = ath9k_debugfs_open, | ||
177 | .owner = THIS_MODULE, | ||
178 | .llseek = default_llseek, | ||
179 | }; | ||
180 | |||
181 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
182 | size_t count, loff_t *ppos) | ||
183 | { | ||
184 | struct ath9k_htc_priv *priv = file->private_data; | ||
185 | char buf[512]; | ||
186 | unsigned int len = 0; | ||
187 | |||
188 | len += snprintf(buf + len, sizeof(buf) - len, | ||
189 | "%20s : %10u\n", "Buffers queued", | ||
190 | priv->debug.tx_stats.buf_queued); | ||
191 | len += snprintf(buf + len, sizeof(buf) - len, | ||
192 | "%20s : %10u\n", "Buffers completed", | ||
193 | priv->debug.tx_stats.buf_completed); | ||
194 | len += snprintf(buf + len, sizeof(buf) - len, | ||
195 | "%20s : %10u\n", "SKBs queued", | ||
196 | priv->debug.tx_stats.skb_queued); | ||
197 | len += snprintf(buf + len, sizeof(buf) - len, | ||
198 | "%20s : %10u\n", "SKBs success", | ||
199 | priv->debug.tx_stats.skb_success); | ||
200 | len += snprintf(buf + len, sizeof(buf) - len, | ||
201 | "%20s : %10u\n", "SKBs failed", | ||
202 | priv->debug.tx_stats.skb_failed); | ||
203 | len += snprintf(buf + len, sizeof(buf) - len, | ||
204 | "%20s : %10u\n", "CAB queued", | ||
205 | priv->debug.tx_stats.cab_queued); | ||
206 | |||
207 | len += snprintf(buf + len, sizeof(buf) - len, | ||
208 | "%20s : %10u\n", "BE queued", | ||
209 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
210 | len += snprintf(buf + len, sizeof(buf) - len, | ||
211 | "%20s : %10u\n", "BK queued", | ||
212 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
213 | len += snprintf(buf + len, sizeof(buf) - len, | ||
214 | "%20s : %10u\n", "VI queued", | ||
215 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
216 | len += snprintf(buf + len, sizeof(buf) - len, | ||
217 | "%20s : %10u\n", "VO queued", | ||
218 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
219 | |||
220 | if (len > sizeof(buf)) | ||
221 | len = sizeof(buf); | ||
222 | |||
223 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
224 | } | ||
225 | |||
226 | static const struct file_operations fops_xmit = { | ||
227 | .read = read_file_xmit, | ||
228 | .open = ath9k_debugfs_open, | ||
229 | .owner = THIS_MODULE, | ||
230 | .llseek = default_llseek, | ||
231 | }; | ||
232 | |||
233 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
234 | struct ath_htc_rx_status *rxs) | ||
235 | { | ||
236 | #define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ | ||
237 | |||
238 | if (rxs->rs_status & ATH9K_RXERR_CRC) | ||
239 | priv->debug.rx_stats.err_crc++; | ||
240 | if (rxs->rs_status & ATH9K_RXERR_DECRYPT) | ||
241 | priv->debug.rx_stats.err_decrypt_crc++; | ||
242 | if (rxs->rs_status & ATH9K_RXERR_MIC) | ||
243 | priv->debug.rx_stats.err_mic++; | ||
244 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
245 | priv->debug.rx_stats.err_pre_delim++; | ||
246 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
247 | priv->debug.rx_stats.err_post_delim++; | ||
248 | if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
249 | priv->debug.rx_stats.err_decrypt_busy++; | ||
250 | |||
251 | if (rxs->rs_status & ATH9K_RXERR_PHY) { | ||
252 | priv->debug.rx_stats.err_phy++; | ||
253 | if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
254 | RX_PHY_ERR_INC(rxs->rs_phyerr); | ||
255 | } | ||
256 | |||
257 | #undef RX_PHY_ERR_INC | ||
258 | } | ||
259 | |||
260 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
261 | size_t count, loff_t *ppos) | ||
262 | { | ||
263 | #define PHY_ERR(s, p) \ | ||
264 | len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ | ||
265 | priv->debug.rx_stats.err_phy_stats[p]); | ||
266 | |||
267 | struct ath9k_htc_priv *priv = file->private_data; | ||
268 | char *buf; | ||
269 | unsigned int len = 0, size = 1500; | ||
270 | ssize_t retval = 0; | ||
271 | |||
272 | buf = kzalloc(size, GFP_KERNEL); | ||
273 | if (buf == NULL) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | len += snprintf(buf + len, size - len, | ||
277 | "%20s : %10u\n", "SKBs allocated", | ||
278 | priv->debug.rx_stats.skb_allocated); | ||
279 | len += snprintf(buf + len, size - len, | ||
280 | "%20s : %10u\n", "SKBs completed", | ||
281 | priv->debug.rx_stats.skb_completed); | ||
282 | len += snprintf(buf + len, size - len, | ||
283 | "%20s : %10u\n", "SKBs Dropped", | ||
284 | priv->debug.rx_stats.skb_dropped); | ||
285 | |||
286 | len += snprintf(buf + len, size - len, | ||
287 | "%20s : %10u\n", "CRC ERR", | ||
288 | priv->debug.rx_stats.err_crc); | ||
289 | len += snprintf(buf + len, size - len, | ||
290 | "%20s : %10u\n", "DECRYPT CRC ERR", | ||
291 | priv->debug.rx_stats.err_decrypt_crc); | ||
292 | len += snprintf(buf + len, size - len, | ||
293 | "%20s : %10u\n", "MIC ERR", | ||
294 | priv->debug.rx_stats.err_mic); | ||
295 | len += snprintf(buf + len, size - len, | ||
296 | "%20s : %10u\n", "PRE-DELIM CRC ERR", | ||
297 | priv->debug.rx_stats.err_pre_delim); | ||
298 | len += snprintf(buf + len, size - len, | ||
299 | "%20s : %10u\n", "POST-DELIM CRC ERR", | ||
300 | priv->debug.rx_stats.err_post_delim); | ||
301 | len += snprintf(buf + len, size - len, | ||
302 | "%20s : %10u\n", "DECRYPT BUSY ERR", | ||
303 | priv->debug.rx_stats.err_decrypt_busy); | ||
304 | len += snprintf(buf + len, size - len, | ||
305 | "%20s : %10u\n", "TOTAL PHY ERR", | ||
306 | priv->debug.rx_stats.err_phy); | ||
307 | |||
308 | |||
309 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | ||
310 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | ||
311 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | ||
312 | PHY_ERR("RATE", ATH9K_PHYERR_RATE); | ||
313 | PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); | ||
314 | PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); | ||
315 | PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); | ||
316 | PHY_ERR("TOR", ATH9K_PHYERR_TOR); | ||
317 | PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); | ||
318 | PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
319 | PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
320 | PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
321 | PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
322 | PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); | ||
323 | PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); | ||
324 | PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
325 | PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); | ||
326 | PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
327 | PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
328 | PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); | ||
329 | PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); | ||
330 | PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
331 | PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); | ||
332 | PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); | ||
333 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
334 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
335 | |||
336 | if (len > size) | ||
337 | len = size; | ||
338 | |||
339 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
340 | kfree(buf); | ||
341 | |||
342 | return retval; | ||
343 | |||
344 | #undef PHY_ERR | ||
345 | } | ||
346 | |||
347 | static const struct file_operations fops_recv = { | ||
348 | .read = read_file_recv, | ||
349 | .open = ath9k_debugfs_open, | ||
350 | .owner = THIS_MODULE, | ||
351 | .llseek = default_llseek, | ||
352 | }; | ||
353 | |||
354 | static ssize_t read_file_slot(struct file *file, char __user *user_buf, | ||
355 | size_t count, loff_t *ppos) | ||
356 | { | ||
357 | struct ath9k_htc_priv *priv = file->private_data; | ||
358 | char buf[512]; | ||
359 | unsigned int len = 0; | ||
360 | |||
361 | spin_lock_bh(&priv->tx.tx_lock); | ||
362 | |||
363 | len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); | ||
364 | |||
365 | len += bitmap_scnprintf(buf + len, sizeof(buf) - len, | ||
366 | priv->tx.tx_slot, MAX_TX_BUF_NUM); | ||
367 | |||
368 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
369 | |||
370 | len += snprintf(buf + len, sizeof(buf) - len, | ||
371 | "Used slots : %d\n", | ||
372 | bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); | ||
373 | |||
374 | spin_unlock_bh(&priv->tx.tx_lock); | ||
375 | |||
376 | if (len > sizeof(buf)) | ||
377 | len = sizeof(buf); | ||
378 | |||
379 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
380 | } | ||
381 | |||
382 | static const struct file_operations fops_slot = { | ||
383 | .read = read_file_slot, | ||
384 | .open = ath9k_debugfs_open, | ||
385 | .owner = THIS_MODULE, | ||
386 | .llseek = default_llseek, | ||
387 | }; | ||
388 | |||
389 | static ssize_t read_file_queue(struct file *file, char __user *user_buf, | ||
390 | size_t count, loff_t *ppos) | ||
391 | { | ||
392 | struct ath9k_htc_priv *priv = file->private_data; | ||
393 | char buf[512]; | ||
394 | unsigned int len = 0; | ||
395 | |||
396 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
397 | "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); | ||
398 | |||
399 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
400 | "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); | ||
401 | |||
402 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
403 | "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); | ||
404 | |||
405 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
406 | "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); | ||
407 | |||
408 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
409 | "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); | ||
410 | |||
411 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
412 | "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); | ||
413 | |||
414 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
415 | "Failed queue", skb_queue_len(&priv->tx.tx_failed)); | ||
416 | |||
417 | spin_lock_bh(&priv->tx.tx_lock); | ||
418 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
419 | "Queued count", priv->tx.queued_cnt); | ||
420 | spin_unlock_bh(&priv->tx.tx_lock); | ||
421 | |||
422 | if (len > sizeof(buf)) | ||
423 | len = sizeof(buf); | ||
424 | |||
425 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
426 | |||
427 | } | ||
428 | |||
429 | static const struct file_operations fops_queue = { | ||
430 | .read = read_file_queue, | ||
431 | .open = ath9k_debugfs_open, | ||
432 | .owner = THIS_MODULE, | ||
433 | .llseek = default_llseek, | ||
434 | }; | ||
435 | |||
436 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, | ||
437 | size_t count, loff_t *ppos) | ||
438 | { | ||
439 | struct ath9k_htc_priv *priv = file->private_data; | ||
440 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
441 | char buf[32]; | ||
442 | unsigned int len; | ||
443 | |||
444 | len = sprintf(buf, "0x%08x\n", common->debug_mask); | ||
445 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
446 | } | ||
447 | |||
448 | static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | ||
449 | size_t count, loff_t *ppos) | ||
450 | { | ||
451 | struct ath9k_htc_priv *priv = file->private_data; | ||
452 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
453 | unsigned long mask; | ||
454 | char buf[32]; | ||
455 | ssize_t len; | ||
456 | |||
457 | len = min(count, sizeof(buf) - 1); | ||
458 | if (copy_from_user(buf, user_buf, len)) | ||
459 | return -EFAULT; | ||
460 | |||
461 | buf[len] = '\0'; | ||
462 | if (strict_strtoul(buf, 0, &mask)) | ||
463 | return -EINVAL; | ||
464 | |||
465 | common->debug_mask = mask; | ||
466 | return count; | ||
467 | } | ||
468 | |||
469 | static const struct file_operations fops_debug = { | ||
470 | .read = read_file_debug, | ||
471 | .write = write_file_debug, | ||
472 | .open = ath9k_debugfs_open, | ||
473 | .owner = THIS_MODULE, | ||
474 | .llseek = default_llseek, | ||
475 | }; | ||
476 | |||
477 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
478 | { | ||
479 | struct ath_common *common = ath9k_hw_common(ah); | ||
480 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
481 | |||
482 | priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, | ||
483 | priv->hw->wiphy->debugfsdir); | ||
484 | if (!priv->debug.debugfs_phy) | ||
485 | return -ENOMEM; | ||
486 | |||
487 | debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
488 | priv, &fops_tgt_int_stats); | ||
489 | debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
490 | priv, &fops_tgt_tx_stats); | ||
491 | debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
492 | priv, &fops_tgt_rx_stats); | ||
493 | debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, | ||
494 | priv, &fops_xmit); | ||
495 | debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, | ||
496 | priv, &fops_recv); | ||
497 | debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, | ||
498 | priv, &fops_slot); | ||
499 | debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, | ||
500 | priv, &fops_queue); | ||
501 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, | ||
502 | priv, &fops_debug); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 7e630a81b453..dc0b33d01210 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -398,9 +398,9 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | |||
398 | 398 | ||
399 | /* Start TX */ | 399 | /* Start TX */ |
400 | htc_start(priv->htc); | 400 | htc_start(priv->htc); |
401 | spin_lock_bh(&priv->tx_lock); | 401 | spin_lock_bh(&priv->tx.tx_lock); |
402 | priv->tx_queues_stop = false; | 402 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; |
403 | spin_unlock_bh(&priv->tx_lock); | 403 | spin_unlock_bh(&priv->tx.tx_lock); |
404 | ieee80211_wake_queues(hw); | 404 | ieee80211_wake_queues(hw); |
405 | 405 | ||
406 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | 406 | WMI_CMD(WMI_ENABLE_INTR_CMDID); |
@@ -429,13 +429,15 @@ void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | |||
429 | 429 | ||
430 | /* Stop TX */ | 430 | /* Stop TX */ |
431 | ieee80211_stop_queues(hw); | 431 | ieee80211_stop_queues(hw); |
432 | htc_stop(priv->htc); | 432 | ath9k_htc_tx_drain(priv); |
433 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 433 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
434 | skb_queue_purge(&priv->tx_queue); | ||
435 | 434 | ||
436 | /* Stop RX */ | 435 | /* Stop RX */ |
437 | WMI_CMD(WMI_STOP_RECV_CMDID); | 436 | WMI_CMD(WMI_STOP_RECV_CMDID); |
438 | 437 | ||
438 | /* Clear the WMI event queue */ | ||
439 | ath9k_wmi_event_drain(priv); | ||
440 | |||
439 | /* | 441 | /* |
440 | * The MIB counters have to be disabled here, | 442 | * The MIB counters have to be disabled here, |
441 | * since the target doesn't do it. | 443 | * since the target doesn't do it. |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 8303b34bdc90..06e043bffaf4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -140,7 +140,6 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | |||
140 | 140 | ||
141 | static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) | 141 | static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) |
142 | { | 142 | { |
143 | ath9k_htc_exit_debug(priv->ah); | ||
144 | ath9k_hw_deinit(priv->ah); | 143 | ath9k_hw_deinit(priv->ah); |
145 | kfree(priv->ah); | 144 | kfree(priv->ah); |
146 | priv->ah = NULL; | 145 | priv->ah = NULL; |
@@ -643,7 +642,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
643 | { | 642 | { |
644 | struct ath_hw *ah = NULL; | 643 | struct ath_hw *ah = NULL; |
645 | struct ath_common *common; | 644 | struct ath_common *common; |
646 | int ret = 0, csz = 0; | 645 | int i, ret = 0, csz = 0; |
647 | 646 | ||
648 | priv->op_flags |= OP_INVALID; | 647 | priv->op_flags |= OP_INVALID; |
649 | 648 | ||
@@ -671,20 +670,19 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
671 | common->priv = priv; | 670 | common->priv = priv; |
672 | common->debug_mask = ath9k_debug; | 671 | common->debug_mask = ath9k_debug; |
673 | 672 | ||
674 | spin_lock_init(&priv->wmi->wmi_lock); | ||
675 | spin_lock_init(&priv->beacon_lock); | 673 | spin_lock_init(&priv->beacon_lock); |
676 | spin_lock_init(&priv->tx_lock); | 674 | spin_lock_init(&priv->tx.tx_lock); |
677 | mutex_init(&priv->mutex); | 675 | mutex_init(&priv->mutex); |
678 | mutex_init(&priv->htc_pm_lock); | 676 | mutex_init(&priv->htc_pm_lock); |
679 | tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet, | ||
680 | (unsigned long)priv); | ||
681 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | 677 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, |
682 | (unsigned long)priv); | 678 | (unsigned long)priv); |
683 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, | 679 | tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet, |
684 | (unsigned long)priv); | 680 | (unsigned long)priv); |
685 | INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); | 681 | INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); |
686 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | 682 | INIT_WORK(&priv->ps_work, ath9k_ps_work); |
687 | INIT_WORK(&priv->fatal_work, ath9k_fatal_work); | 683 | INIT_WORK(&priv->fatal_work, ath9k_fatal_work); |
684 | setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, | ||
685 | (unsigned long)priv); | ||
688 | 686 | ||
689 | /* | 687 | /* |
690 | * Cache line size is used to size and align various | 688 | * Cache line size is used to size and align various |
@@ -701,16 +699,13 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
701 | goto err_hw; | 699 | goto err_hw; |
702 | } | 700 | } |
703 | 701 | ||
704 | ret = ath9k_htc_init_debug(ah); | ||
705 | if (ret) { | ||
706 | ath_err(common, "Unable to create debugfs files\n"); | ||
707 | goto err_debug; | ||
708 | } | ||
709 | |||
710 | ret = ath9k_init_queues(priv); | 702 | ret = ath9k_init_queues(priv); |
711 | if (ret) | 703 | if (ret) |
712 | goto err_queues; | 704 | goto err_queues; |
713 | 705 | ||
706 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) | ||
707 | priv->cur_beacon_conf.bslot[i] = NULL; | ||
708 | |||
714 | ath9k_init_crypto(priv); | 709 | ath9k_init_crypto(priv); |
715 | ath9k_init_channels_rates(priv); | 710 | ath9k_init_channels_rates(priv); |
716 | ath9k_init_misc(priv); | 711 | ath9k_init_misc(priv); |
@@ -723,8 +718,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
723 | return 0; | 718 | return 0; |
724 | 719 | ||
725 | err_queues: | 720 | err_queues: |
726 | ath9k_htc_exit_debug(ah); | ||
727 | err_debug: | ||
728 | ath9k_hw_deinit(ah); | 721 | ath9k_hw_deinit(ah); |
729 | err_hw: | 722 | err_hw: |
730 | 723 | ||
@@ -745,11 +738,15 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
745 | IEEE80211_HW_HAS_RATE_CONTROL | | 738 | IEEE80211_HW_HAS_RATE_CONTROL | |
746 | IEEE80211_HW_RX_INCLUDES_FCS | | 739 | IEEE80211_HW_RX_INCLUDES_FCS | |
747 | IEEE80211_HW_SUPPORTS_PS | | 740 | IEEE80211_HW_SUPPORTS_PS | |
748 | IEEE80211_HW_PS_NULLFUNC_STACK; | 741 | IEEE80211_HW_PS_NULLFUNC_STACK | |
742 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; | ||
749 | 743 | ||
750 | hw->wiphy->interface_modes = | 744 | hw->wiphy->interface_modes = |
751 | BIT(NL80211_IFTYPE_STATION) | | 745 | BIT(NL80211_IFTYPE_STATION) | |
752 | BIT(NL80211_IFTYPE_ADHOC); | 746 | BIT(NL80211_IFTYPE_ADHOC) | |
747 | BIT(NL80211_IFTYPE_AP) | | ||
748 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
749 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
753 | 750 | ||
754 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 751 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
755 | 752 | ||
@@ -782,6 +779,32 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
782 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 779 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
783 | } | 780 | } |
784 | 781 | ||
782 | static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) | ||
783 | { | ||
784 | struct ieee80211_hw *hw = priv->hw; | ||
785 | struct wmi_fw_version cmd_rsp; | ||
786 | int ret; | ||
787 | |||
788 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
789 | |||
790 | WMI_CMD(WMI_GET_FW_VERSION); | ||
791 | if (ret) | ||
792 | return -EINVAL; | ||
793 | |||
794 | priv->fw_version_major = be16_to_cpu(cmd_rsp.major); | ||
795 | priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); | ||
796 | |||
797 | snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", | ||
798 | priv->fw_version_major, | ||
799 | priv->fw_version_minor); | ||
800 | |||
801 | dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", | ||
802 | priv->fw_version_major, | ||
803 | priv->fw_version_minor); | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
785 | static int ath9k_init_device(struct ath9k_htc_priv *priv, | 808 | static int ath9k_init_device(struct ath9k_htc_priv *priv, |
786 | u16 devid, char *product, u32 drv_info) | 809 | u16 devid, char *product, u32 drv_info) |
787 | { | 810 | { |
@@ -801,6 +824,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, | |||
801 | common = ath9k_hw_common(ah); | 824 | common = ath9k_hw_common(ah); |
802 | ath9k_set_hw_capab(priv, hw); | 825 | ath9k_set_hw_capab(priv, hw); |
803 | 826 | ||
827 | error = ath9k_init_firmware_version(priv); | ||
828 | if (error != 0) | ||
829 | goto err_fw; | ||
830 | |||
804 | /* Initialize regulatory */ | 831 | /* Initialize regulatory */ |
805 | error = ath_regd_init(&common->regulatory, priv->hw->wiphy, | 832 | error = ath_regd_init(&common->regulatory, priv->hw->wiphy, |
806 | ath9k_reg_notifier); | 833 | ath9k_reg_notifier); |
@@ -831,6 +858,12 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, | |||
831 | goto err_world; | 858 | goto err_world; |
832 | } | 859 | } |
833 | 860 | ||
861 | error = ath9k_htc_init_debug(priv->ah); | ||
862 | if (error) { | ||
863 | ath_err(common, "Unable to create debugfs files\n"); | ||
864 | goto err_world; | ||
865 | } | ||
866 | |||
834 | ath_dbg(common, ATH_DBG_CONFIG, | 867 | ath_dbg(common, ATH_DBG_CONFIG, |
835 | "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " | 868 | "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " |
836 | "BE:%d, BK:%d, VI:%d, VO:%d\n", | 869 | "BE:%d, BK:%d, VI:%d, VO:%d\n", |
@@ -861,6 +894,8 @@ err_rx: | |||
861 | err_tx: | 894 | err_tx: |
862 | /* Nothing */ | 895 | /* Nothing */ |
863 | err_regd: | 896 | err_regd: |
897 | /* Nothing */ | ||
898 | err_fw: | ||
864 | ath9k_deinit_priv(priv); | 899 | ath9k_deinit_priv(priv); |
865 | err_init: | 900 | err_init: |
866 | return error; | 901 | return error; |
@@ -949,38 +984,20 @@ int ath9k_htc_resume(struct htc_target *htc_handle) | |||
949 | 984 | ||
950 | static int __init ath9k_htc_init(void) | 985 | static int __init ath9k_htc_init(void) |
951 | { | 986 | { |
952 | int error; | 987 | if (ath9k_hif_usb_init() < 0) { |
953 | |||
954 | error = ath9k_htc_debug_create_root(); | ||
955 | if (error < 0) { | ||
956 | printk(KERN_ERR | ||
957 | "ath9k_htc: Unable to create debugfs root: %d\n", | ||
958 | error); | ||
959 | goto err_dbg; | ||
960 | } | ||
961 | |||
962 | error = ath9k_hif_usb_init(); | ||
963 | if (error < 0) { | ||
964 | printk(KERN_ERR | 988 | printk(KERN_ERR |
965 | "ath9k_htc: No USB devices found," | 989 | "ath9k_htc: No USB devices found," |
966 | " driver not installed.\n"); | 990 | " driver not installed.\n"); |
967 | error = -ENODEV; | 991 | return -ENODEV; |
968 | goto err_usb; | ||
969 | } | 992 | } |
970 | 993 | ||
971 | return 0; | 994 | return 0; |
972 | |||
973 | err_usb: | ||
974 | ath9k_htc_debug_remove_root(); | ||
975 | err_dbg: | ||
976 | return error; | ||
977 | } | 995 | } |
978 | module_init(ath9k_htc_init); | 996 | module_init(ath9k_htc_init); |
979 | 997 | ||
980 | static void __exit ath9k_htc_exit(void) | 998 | static void __exit ath9k_htc_exit(void) |
981 | { | 999 | { |
982 | ath9k_hif_usb_exit(); | 1000 | ath9k_hif_usb_exit(); |
983 | ath9k_htc_debug_remove_root(); | ||
984 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); | 1001 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); |
985 | } | 1002 | } |
986 | module_exit(ath9k_htc_exit); | 1003 | module_exit(ath9k_htc_exit); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index db8c0c044e9e..4de38643cb53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -16,10 +16,6 @@ | |||
16 | 16 | ||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
20 | static struct dentry *ath9k_debugfs_root; | ||
21 | #endif | ||
22 | |||
23 | /*************/ | 19 | /*************/ |
24 | /* Utilities */ | 20 | /* Utilities */ |
25 | /*************/ | 21 | /*************/ |
@@ -197,11 +193,16 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
197 | 193 | ||
198 | ath9k_htc_stop_ani(priv); | 194 | ath9k_htc_stop_ani(priv); |
199 | ieee80211_stop_queues(priv->hw); | 195 | ieee80211_stop_queues(priv->hw); |
200 | htc_stop(priv->htc); | 196 | |
197 | del_timer_sync(&priv->tx.cleanup_timer); | ||
198 | ath9k_htc_tx_drain(priv); | ||
199 | |||
201 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 200 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
202 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 201 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
203 | WMI_CMD(WMI_STOP_RECV_CMDID); | 202 | WMI_CMD(WMI_STOP_RECV_CMDID); |
204 | 203 | ||
204 | ath9k_wmi_event_drain(priv); | ||
205 | |||
205 | caldata = &priv->caldata; | 206 | caldata = &priv->caldata; |
206 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); | 207 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); |
207 | if (ret) { | 208 | if (ret) { |
@@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
225 | ath9k_htc_vif_reconfig(priv); | 226 | ath9k_htc_vif_reconfig(priv); |
226 | ieee80211_wake_queues(priv->hw); | 227 | ieee80211_wake_queues(priv->hw); |
227 | 228 | ||
229 | mod_timer(&priv->tx.cleanup_timer, | ||
230 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
231 | |||
228 | ath9k_htc_ps_restore(priv); | 232 | ath9k_htc_ps_restore(priv); |
229 | mutex_unlock(&priv->mutex); | 233 | mutex_unlock(&priv->mutex); |
230 | } | 234 | } |
@@ -250,11 +254,16 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
250 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | 254 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
251 | 255 | ||
252 | ath9k_htc_ps_wakeup(priv); | 256 | ath9k_htc_ps_wakeup(priv); |
253 | htc_stop(priv->htc); | 257 | |
258 | del_timer_sync(&priv->tx.cleanup_timer); | ||
259 | ath9k_htc_tx_drain(priv); | ||
260 | |||
254 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 261 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
255 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 262 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
256 | WMI_CMD(WMI_STOP_RECV_CMDID); | 263 | WMI_CMD(WMI_STOP_RECV_CMDID); |
257 | 264 | ||
265 | ath9k_wmi_event_drain(priv); | ||
266 | |||
258 | ath_dbg(common, ATH_DBG_CONFIG, | 267 | ath_dbg(common, ATH_DBG_CONFIG, |
259 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", | 268 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", |
260 | priv->ah->curchan->channel, | 269 | priv->ah->curchan->channel, |
@@ -263,6 +272,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
263 | 272 | ||
264 | if (!fastcc) | 273 | if (!fastcc) |
265 | caldata = &priv->caldata; | 274 | caldata = &priv->caldata; |
275 | |||
266 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 276 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
267 | if (ret) { | 277 | if (ret) { |
268 | ath_err(common, | 278 | ath_err(common, |
@@ -296,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
296 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 306 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
297 | ath9k_htc_vif_reconfig(priv); | 307 | ath9k_htc_vif_reconfig(priv); |
298 | 308 | ||
309 | mod_timer(&priv->tx.cleanup_timer, | ||
310 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
311 | |||
299 | err: | 312 | err: |
300 | ath9k_htc_ps_restore(priv); | 313 | ath9k_htc_ps_restore(priv); |
301 | return ret; | 314 | return ret; |
@@ -349,7 +362,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | |||
349 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 362 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
350 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 363 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
351 | 364 | ||
352 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | 365 | hvif.opmode = HTC_M_MONITOR; |
353 | hvif.index = ffz(priv->vif_slot); | 366 | hvif.index = ffz(priv->vif_slot); |
354 | 367 | ||
355 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 368 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
@@ -382,7 +395,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | |||
382 | tsta.is_vif_sta = 1; | 395 | tsta.is_vif_sta = 1; |
383 | tsta.sta_index = sta_idx; | 396 | tsta.sta_index = sta_idx; |
384 | tsta.vif_index = hvif.index; | 397 | tsta.vif_index = hvif.index; |
385 | tsta.maxampdu = 0xffff; | 398 | tsta.maxampdu = cpu_to_be16(0xffff); |
386 | 399 | ||
387 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | 400 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
388 | if (ret) { | 401 | if (ret) { |
@@ -463,9 +476,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
463 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 476 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
464 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); | 477 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); |
465 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); | 478 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); |
466 | tsta.associd = common->curaid; | ||
467 | tsta.is_vif_sta = 0; | 479 | tsta.is_vif_sta = 0; |
468 | tsta.valid = true; | ||
469 | ista->index = sta_idx; | 480 | ista->index = sta_idx; |
470 | } else { | 481 | } else { |
471 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); | 482 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); |
@@ -474,7 +485,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
474 | 485 | ||
475 | tsta.sta_index = sta_idx; | 486 | tsta.sta_index = sta_idx; |
476 | tsta.vif_index = avp->index; | 487 | tsta.vif_index = avp->index; |
477 | tsta.maxampdu = 0xffff; | 488 | tsta.maxampdu = cpu_to_be16(0xffff); |
478 | if (sta && sta->ht_cap.ht_supported) | 489 | if (sta && sta->ht_cap.ht_supported) |
479 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); | 490 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); |
480 | 491 | ||
@@ -709,218 +720,13 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, | |||
709 | (aggr.aggr_enable) ? "Starting" : "Stopping", | 720 | (aggr.aggr_enable) ? "Starting" : "Stopping", |
710 | sta->addr, tid); | 721 | sta->addr, tid); |
711 | 722 | ||
712 | spin_lock_bh(&priv->tx_lock); | 723 | spin_lock_bh(&priv->tx.tx_lock); |
713 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; | 724 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
714 | spin_unlock_bh(&priv->tx_lock); | 725 | spin_unlock_bh(&priv->tx.tx_lock); |
715 | 726 | ||
716 | return ret; | 727 | return ret; |
717 | } | 728 | } |
718 | 729 | ||
719 | /*********/ | ||
720 | /* DEBUG */ | ||
721 | /*********/ | ||
722 | |||
723 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
724 | |||
725 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
726 | { | ||
727 | file->private_data = inode->i_private; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | ||
732 | size_t count, loff_t *ppos) | ||
733 | { | ||
734 | struct ath9k_htc_priv *priv = file->private_data; | ||
735 | struct ath9k_htc_target_stats cmd_rsp; | ||
736 | char buf[512]; | ||
737 | unsigned int len = 0; | ||
738 | int ret = 0; | ||
739 | |||
740 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
741 | |||
742 | WMI_CMD(WMI_TGT_STATS_CMDID); | ||
743 | if (ret) | ||
744 | return -EINVAL; | ||
745 | |||
746 | |||
747 | len += snprintf(buf + len, sizeof(buf) - len, | ||
748 | "%19s : %10u\n", "TX Short Retries", | ||
749 | be32_to_cpu(cmd_rsp.tx_shortretry)); | ||
750 | len += snprintf(buf + len, sizeof(buf) - len, | ||
751 | "%19s : %10u\n", "TX Long Retries", | ||
752 | be32_to_cpu(cmd_rsp.tx_longretry)); | ||
753 | len += snprintf(buf + len, sizeof(buf) - len, | ||
754 | "%19s : %10u\n", "TX Xretries", | ||
755 | be32_to_cpu(cmd_rsp.tx_xretries)); | ||
756 | len += snprintf(buf + len, sizeof(buf) - len, | ||
757 | "%19s : %10u\n", "TX Unaggr. Xretries", | ||
758 | be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); | ||
759 | len += snprintf(buf + len, sizeof(buf) - len, | ||
760 | "%19s : %10u\n", "TX Xretries (HT)", | ||
761 | be32_to_cpu(cmd_rsp.ht_tx_xretries)); | ||
762 | len += snprintf(buf + len, sizeof(buf) - len, | ||
763 | "%19s : %10u\n", "TX Rate", priv->debug.txrate); | ||
764 | |||
765 | if (len > sizeof(buf)) | ||
766 | len = sizeof(buf); | ||
767 | |||
768 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
769 | } | ||
770 | |||
771 | static const struct file_operations fops_tgt_stats = { | ||
772 | .read = read_file_tgt_stats, | ||
773 | .open = ath9k_debugfs_open, | ||
774 | .owner = THIS_MODULE, | ||
775 | .llseek = default_llseek, | ||
776 | }; | ||
777 | |||
778 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
779 | size_t count, loff_t *ppos) | ||
780 | { | ||
781 | struct ath9k_htc_priv *priv = file->private_data; | ||
782 | char buf[512]; | ||
783 | unsigned int len = 0; | ||
784 | |||
785 | len += snprintf(buf + len, sizeof(buf) - len, | ||
786 | "%20s : %10u\n", "Buffers queued", | ||
787 | priv->debug.tx_stats.buf_queued); | ||
788 | len += snprintf(buf + len, sizeof(buf) - len, | ||
789 | "%20s : %10u\n", "Buffers completed", | ||
790 | priv->debug.tx_stats.buf_completed); | ||
791 | len += snprintf(buf + len, sizeof(buf) - len, | ||
792 | "%20s : %10u\n", "SKBs queued", | ||
793 | priv->debug.tx_stats.skb_queued); | ||
794 | len += snprintf(buf + len, sizeof(buf) - len, | ||
795 | "%20s : %10u\n", "SKBs completed", | ||
796 | priv->debug.tx_stats.skb_completed); | ||
797 | len += snprintf(buf + len, sizeof(buf) - len, | ||
798 | "%20s : %10u\n", "SKBs dropped", | ||
799 | priv->debug.tx_stats.skb_dropped); | ||
800 | |||
801 | len += snprintf(buf + len, sizeof(buf) - len, | ||
802 | "%20s : %10u\n", "BE queued", | ||
803 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
804 | len += snprintf(buf + len, sizeof(buf) - len, | ||
805 | "%20s : %10u\n", "BK queued", | ||
806 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
807 | len += snprintf(buf + len, sizeof(buf) - len, | ||
808 | "%20s : %10u\n", "VI queued", | ||
809 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
810 | len += snprintf(buf + len, sizeof(buf) - len, | ||
811 | "%20s : %10u\n", "VO queued", | ||
812 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
813 | |||
814 | if (len > sizeof(buf)) | ||
815 | len = sizeof(buf); | ||
816 | |||
817 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
818 | } | ||
819 | |||
820 | static const struct file_operations fops_xmit = { | ||
821 | .read = read_file_xmit, | ||
822 | .open = ath9k_debugfs_open, | ||
823 | .owner = THIS_MODULE, | ||
824 | .llseek = default_llseek, | ||
825 | }; | ||
826 | |||
827 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
828 | size_t count, loff_t *ppos) | ||
829 | { | ||
830 | struct ath9k_htc_priv *priv = file->private_data; | ||
831 | char buf[512]; | ||
832 | unsigned int len = 0; | ||
833 | |||
834 | len += snprintf(buf + len, sizeof(buf) - len, | ||
835 | "%20s : %10u\n", "SKBs allocated", | ||
836 | priv->debug.rx_stats.skb_allocated); | ||
837 | len += snprintf(buf + len, sizeof(buf) - len, | ||
838 | "%20s : %10u\n", "SKBs completed", | ||
839 | priv->debug.rx_stats.skb_completed); | ||
840 | len += snprintf(buf + len, sizeof(buf) - len, | ||
841 | "%20s : %10u\n", "SKBs Dropped", | ||
842 | priv->debug.rx_stats.skb_dropped); | ||
843 | |||
844 | if (len > sizeof(buf)) | ||
845 | len = sizeof(buf); | ||
846 | |||
847 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
848 | } | ||
849 | |||
850 | static const struct file_operations fops_recv = { | ||
851 | .read = read_file_recv, | ||
852 | .open = ath9k_debugfs_open, | ||
853 | .owner = THIS_MODULE, | ||
854 | .llseek = default_llseek, | ||
855 | }; | ||
856 | |||
857 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
858 | { | ||
859 | struct ath_common *common = ath9k_hw_common(ah); | ||
860 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
861 | |||
862 | if (!ath9k_debugfs_root) | ||
863 | return -ENOENT; | ||
864 | |||
865 | priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), | ||
866 | ath9k_debugfs_root); | ||
867 | if (!priv->debug.debugfs_phy) | ||
868 | goto err; | ||
869 | |||
870 | priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, | ||
871 | priv->debug.debugfs_phy, | ||
872 | priv, &fops_tgt_stats); | ||
873 | if (!priv->debug.debugfs_tgt_stats) | ||
874 | goto err; | ||
875 | |||
876 | |||
877 | priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, | ||
878 | priv->debug.debugfs_phy, | ||
879 | priv, &fops_xmit); | ||
880 | if (!priv->debug.debugfs_xmit) | ||
881 | goto err; | ||
882 | |||
883 | priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, | ||
884 | priv->debug.debugfs_phy, | ||
885 | priv, &fops_recv); | ||
886 | if (!priv->debug.debugfs_recv) | ||
887 | goto err; | ||
888 | |||
889 | return 0; | ||
890 | |||
891 | err: | ||
892 | ath9k_htc_exit_debug(ah); | ||
893 | return -ENOMEM; | ||
894 | } | ||
895 | |||
896 | void ath9k_htc_exit_debug(struct ath_hw *ah) | ||
897 | { | ||
898 | struct ath_common *common = ath9k_hw_common(ah); | ||
899 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
900 | |||
901 | debugfs_remove(priv->debug.debugfs_recv); | ||
902 | debugfs_remove(priv->debug.debugfs_xmit); | ||
903 | debugfs_remove(priv->debug.debugfs_tgt_stats); | ||
904 | debugfs_remove(priv->debug.debugfs_phy); | ||
905 | } | ||
906 | |||
907 | int ath9k_htc_debug_create_root(void) | ||
908 | { | ||
909 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
910 | if (!ath9k_debugfs_root) | ||
911 | return -ENOENT; | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | void ath9k_htc_debug_remove_root(void) | ||
917 | { | ||
918 | debugfs_remove(ath9k_debugfs_root); | ||
919 | ath9k_debugfs_root = NULL; | ||
920 | } | ||
921 | |||
922 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
923 | |||
924 | /*******/ | 730 | /*******/ |
925 | /* ANI */ | 731 | /* ANI */ |
926 | /*******/ | 732 | /*******/ |
@@ -1040,7 +846,8 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1040 | { | 846 | { |
1041 | struct ieee80211_hdr *hdr; | 847 | struct ieee80211_hdr *hdr; |
1042 | struct ath9k_htc_priv *priv = hw->priv; | 848 | struct ath9k_htc_priv *priv = hw->priv; |
1043 | int padpos, padsize, ret; | 849 | struct ath_common *common = ath9k_hw_common(priv->ah); |
850 | int padpos, padsize, ret, slot; | ||
1044 | 851 | ||
1045 | hdr = (struct ieee80211_hdr *) skb->data; | 852 | hdr = (struct ieee80211_hdr *) skb->data; |
1046 | 853 | ||
@@ -1048,30 +855,32 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1048 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 855 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1049 | padsize = padpos & 3; | 856 | padsize = padpos & 3; |
1050 | if (padsize && skb->len > padpos) { | 857 | if (padsize && skb->len > padpos) { |
1051 | if (skb_headroom(skb) < padsize) | 858 | if (skb_headroom(skb) < padsize) { |
859 | ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n"); | ||
1052 | goto fail_tx; | 860 | goto fail_tx; |
861 | } | ||
1053 | skb_push(skb, padsize); | 862 | skb_push(skb, padsize); |
1054 | memmove(skb->data, skb->data + padsize, padpos); | 863 | memmove(skb->data, skb->data + padsize, padpos); |
1055 | } | 864 | } |
1056 | 865 | ||
1057 | ret = ath9k_htc_tx_start(priv, skb); | 866 | slot = ath9k_htc_tx_get_slot(priv); |
1058 | if (ret != 0) { | 867 | if (slot < 0) { |
1059 | if (ret == -ENOMEM) { | 868 | ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n"); |
1060 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1061 | "Stopping TX queues\n"); | ||
1062 | ieee80211_stop_queues(hw); | ||
1063 | spin_lock_bh(&priv->tx_lock); | ||
1064 | priv->tx_queues_stop = true; | ||
1065 | spin_unlock_bh(&priv->tx_lock); | ||
1066 | } else { | ||
1067 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1068 | "Tx failed\n"); | ||
1069 | } | ||
1070 | goto fail_tx; | 869 | goto fail_tx; |
1071 | } | 870 | } |
1072 | 871 | ||
872 | ret = ath9k_htc_tx_start(priv, skb, slot, false); | ||
873 | if (ret != 0) { | ||
874 | ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); | ||
875 | goto clear_slot; | ||
876 | } | ||
877 | |||
878 | ath9k_htc_check_stop_queues(priv); | ||
879 | |||
1073 | return; | 880 | return; |
1074 | 881 | ||
882 | clear_slot: | ||
883 | ath9k_htc_tx_clear_slot(priv, slot); | ||
1075 | fail_tx: | 884 | fail_tx: |
1076 | dev_kfree_skb_any(skb); | 885 | dev_kfree_skb_any(skb); |
1077 | } | 886 | } |
@@ -1130,12 +939,15 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1130 | priv->op_flags &= ~OP_INVALID; | 939 | priv->op_flags &= ~OP_INVALID; |
1131 | htc_start(priv->htc); | 940 | htc_start(priv->htc); |
1132 | 941 | ||
1133 | spin_lock_bh(&priv->tx_lock); | 942 | spin_lock_bh(&priv->tx.tx_lock); |
1134 | priv->tx_queues_stop = false; | 943 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; |
1135 | spin_unlock_bh(&priv->tx_lock); | 944 | spin_unlock_bh(&priv->tx.tx_lock); |
1136 | 945 | ||
1137 | ieee80211_wake_queues(hw); | 946 | ieee80211_wake_queues(hw); |
1138 | 947 | ||
948 | mod_timer(&priv->tx.cleanup_timer, | ||
949 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
950 | |||
1139 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { | 951 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { |
1140 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | 952 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, |
1141 | AR_STOMP_LOW_WLAN_WGHT); | 953 | AR_STOMP_LOW_WLAN_WGHT); |
@@ -1164,16 +976,16 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1164 | } | 976 | } |
1165 | 977 | ||
1166 | ath9k_htc_ps_wakeup(priv); | 978 | ath9k_htc_ps_wakeup(priv); |
1167 | htc_stop(priv->htc); | 979 | |
1168 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 980 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1169 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 981 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
1170 | WMI_CMD(WMI_STOP_RECV_CMDID); | 982 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1171 | 983 | ||
1172 | tasklet_kill(&priv->swba_tasklet); | ||
1173 | tasklet_kill(&priv->rx_tasklet); | 984 | tasklet_kill(&priv->rx_tasklet); |
1174 | tasklet_kill(&priv->tx_tasklet); | ||
1175 | 985 | ||
1176 | skb_queue_purge(&priv->tx_queue); | 986 | del_timer_sync(&priv->tx.cleanup_timer); |
987 | ath9k_htc_tx_drain(priv); | ||
988 | ath9k_wmi_event_drain(priv); | ||
1177 | 989 | ||
1178 | mutex_unlock(&priv->mutex); | 990 | mutex_unlock(&priv->mutex); |
1179 | 991 | ||
@@ -1245,13 +1057,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1245 | 1057 | ||
1246 | switch (vif->type) { | 1058 | switch (vif->type) { |
1247 | case NL80211_IFTYPE_STATION: | 1059 | case NL80211_IFTYPE_STATION: |
1248 | hvif.opmode = cpu_to_be32(HTC_M_STA); | 1060 | hvif.opmode = HTC_M_STA; |
1249 | break; | 1061 | break; |
1250 | case NL80211_IFTYPE_ADHOC: | 1062 | case NL80211_IFTYPE_ADHOC: |
1251 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); | 1063 | hvif.opmode = HTC_M_IBSS; |
1252 | break; | 1064 | break; |
1253 | case NL80211_IFTYPE_AP: | 1065 | case NL80211_IFTYPE_AP: |
1254 | hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); | 1066 | hvif.opmode = HTC_M_HOSTAP; |
1255 | break; | 1067 | break; |
1256 | default: | 1068 | default: |
1257 | ath_err(common, | 1069 | ath_err(common, |
@@ -1281,14 +1093,20 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1281 | 1093 | ||
1282 | priv->vif_slot |= (1 << avp->index); | 1094 | priv->vif_slot |= (1 << avp->index); |
1283 | priv->nvifs++; | 1095 | priv->nvifs++; |
1284 | priv->vif = vif; | ||
1285 | 1096 | ||
1286 | INC_VIF(priv, vif->type); | 1097 | INC_VIF(priv, vif->type); |
1098 | |||
1099 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1100 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1101 | ath9k_htc_assign_bslot(priv, vif); | ||
1102 | |||
1287 | ath9k_htc_set_opmode(priv); | 1103 | ath9k_htc_set_opmode(priv); |
1288 | 1104 | ||
1289 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | 1105 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1290 | !(priv->op_flags & OP_ANI_RUNNING)) | 1106 | !(priv->op_flags & OP_ANI_RUNNING)) { |
1107 | ath9k_hw_set_tsfadjust(priv->ah, 1); | ||
1291 | ath9k_htc_start_ani(priv); | 1108 | ath9k_htc_start_ani(priv); |
1109 | } | ||
1292 | 1110 | ||
1293 | ath_dbg(common, ATH_DBG_CONFIG, | 1111 | ath_dbg(common, ATH_DBG_CONFIG, |
1294 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); | 1112 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); |
@@ -1321,9 +1139,13 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1321 | priv->vif_slot &= ~(1 << avp->index); | 1139 | priv->vif_slot &= ~(1 << avp->index); |
1322 | 1140 | ||
1323 | ath9k_htc_remove_station(priv, vif, NULL); | 1141 | ath9k_htc_remove_station(priv, vif, NULL); |
1324 | priv->vif = NULL; | ||
1325 | 1142 | ||
1326 | DEC_VIF(priv, vif->type); | 1143 | DEC_VIF(priv, vif->type); |
1144 | |||
1145 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1146 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1147 | ath9k_htc_remove_bslot(priv, vif); | ||
1148 | |||
1327 | ath9k_htc_set_opmode(priv); | 1149 | ath9k_htc_set_opmode(priv); |
1328 | 1150 | ||
1329 | /* | 1151 | /* |
@@ -1493,10 +1315,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, | |||
1493 | struct ieee80211_sta *sta) | 1315 | struct ieee80211_sta *sta) |
1494 | { | 1316 | { |
1495 | struct ath9k_htc_priv *priv = hw->priv; | 1317 | struct ath9k_htc_priv *priv = hw->priv; |
1318 | struct ath9k_htc_sta *ista; | ||
1496 | int ret; | 1319 | int ret; |
1497 | 1320 | ||
1498 | mutex_lock(&priv->mutex); | 1321 | mutex_lock(&priv->mutex); |
1499 | ath9k_htc_ps_wakeup(priv); | 1322 | ath9k_htc_ps_wakeup(priv); |
1323 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
1324 | htc_sta_drain(priv->htc, ista->index); | ||
1500 | ret = ath9k_htc_remove_station(priv, vif, sta); | 1325 | ret = ath9k_htc_remove_station(priv, vif, sta); |
1501 | ath9k_htc_ps_restore(priv); | 1326 | ath9k_htc_ps_restore(priv); |
1502 | mutex_unlock(&priv->mutex); | 1327 | mutex_unlock(&priv->mutex); |
@@ -1644,6 +1469,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1644 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { | 1469 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |
1645 | ath_dbg(common, ATH_DBG_CONFIG, | 1470 | ath_dbg(common, ATH_DBG_CONFIG, |
1646 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); | 1471 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); |
1472 | ath9k_htc_set_tsfadjust(priv, vif); | ||
1647 | priv->op_flags |= OP_ENABLE_BEACON; | 1473 | priv->op_flags |= OP_ENABLE_BEACON; |
1648 | ath9k_htc_beacon_config(priv, vif); | 1474 | ath9k_htc_beacon_config(priv, vif); |
1649 | } | 1475 | } |
@@ -1758,9 +1584,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1758 | break; | 1584 | break; |
1759 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1585 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1760 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 1586 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1761 | spin_lock_bh(&priv->tx_lock); | 1587 | spin_lock_bh(&priv->tx.tx_lock); |
1762 | ista->tid_state[tid] = AGGR_OPERATIONAL; | 1588 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1763 | spin_unlock_bh(&priv->tx_lock); | 1589 | spin_unlock_bh(&priv->tx.tx_lock); |
1764 | break; | 1590 | break; |
1765 | default: | 1591 | default: |
1766 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); | 1592 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 4a4f27ba96af..723a3a9c5cd9 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -53,6 +53,138 @@ int get_hw_qnum(u16 queue, int *hwq_map) | |||
53 | } | 53 | } |
54 | } | 54 | } |
55 | 55 | ||
56 | void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) | ||
57 | { | ||
58 | spin_lock_bh(&priv->tx.tx_lock); | ||
59 | priv->tx.queued_cnt++; | ||
60 | if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && | ||
61 | !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { | ||
62 | priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
63 | ieee80211_stop_queues(priv->hw); | ||
64 | } | ||
65 | spin_unlock_bh(&priv->tx.tx_lock); | ||
66 | } | ||
67 | |||
68 | void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) | ||
69 | { | ||
70 | spin_lock_bh(&priv->tx.tx_lock); | ||
71 | if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && | ||
72 | (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { | ||
73 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
74 | ieee80211_wake_queues(priv->hw); | ||
75 | } | ||
76 | spin_unlock_bh(&priv->tx.tx_lock); | ||
77 | } | ||
78 | |||
79 | int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv) | ||
80 | { | ||
81 | int slot; | ||
82 | |||
83 | spin_lock_bh(&priv->tx.tx_lock); | ||
84 | slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM); | ||
85 | if (slot >= MAX_TX_BUF_NUM) { | ||
86 | spin_unlock_bh(&priv->tx.tx_lock); | ||
87 | return -ENOBUFS; | ||
88 | } | ||
89 | __set_bit(slot, priv->tx.tx_slot); | ||
90 | spin_unlock_bh(&priv->tx.tx_lock); | ||
91 | |||
92 | return slot; | ||
93 | } | ||
94 | |||
95 | void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) | ||
96 | { | ||
97 | spin_lock_bh(&priv->tx.tx_lock); | ||
98 | __clear_bit(slot, priv->tx.tx_slot); | ||
99 | spin_unlock_bh(&priv->tx.tx_lock); | ||
100 | } | ||
101 | |||
102 | static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, | ||
103 | u16 qnum) | ||
104 | { | ||
105 | enum htc_endpoint_id epid; | ||
106 | |||
107 | switch (qnum) { | ||
108 | case 0: | ||
109 | TX_QSTAT_INC(WME_AC_VO); | ||
110 | epid = priv->data_vo_ep; | ||
111 | break; | ||
112 | case 1: | ||
113 | TX_QSTAT_INC(WME_AC_VI); | ||
114 | epid = priv->data_vi_ep; | ||
115 | break; | ||
116 | case 2: | ||
117 | TX_QSTAT_INC(WME_AC_BE); | ||
118 | epid = priv->data_be_ep; | ||
119 | break; | ||
120 | case 3: | ||
121 | default: | ||
122 | TX_QSTAT_INC(WME_AC_BK); | ||
123 | epid = priv->data_bk_ep; | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | return epid; | ||
128 | } | ||
129 | |||
130 | static inline struct sk_buff_head* | ||
131 | get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid) | ||
132 | { | ||
133 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
134 | struct sk_buff_head *epid_queue = NULL; | ||
135 | |||
136 | if (epid == priv->mgmt_ep) | ||
137 | epid_queue = &priv->tx.mgmt_ep_queue; | ||
138 | else if (epid == priv->cab_ep) | ||
139 | epid_queue = &priv->tx.cab_ep_queue; | ||
140 | else if (epid == priv->data_be_ep) | ||
141 | epid_queue = &priv->tx.data_be_queue; | ||
142 | else if (epid == priv->data_bk_ep) | ||
143 | epid_queue = &priv->tx.data_bk_queue; | ||
144 | else if (epid == priv->data_vi_ep) | ||
145 | epid_queue = &priv->tx.data_vi_queue; | ||
146 | else if (epid == priv->data_vo_ep) | ||
147 | epid_queue = &priv->tx.data_vo_queue; | ||
148 | else | ||
149 | ath_err(common, "Invalid EPID: %d\n", epid); | ||
150 | |||
151 | return epid_queue; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Removes the driver header and returns the TX slot number | ||
156 | */ | ||
157 | static inline int strip_drv_header(struct ath9k_htc_priv *priv, | ||
158 | struct sk_buff *skb) | ||
159 | { | ||
160 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
161 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
162 | int slot; | ||
163 | |||
164 | tx_ctl = HTC_SKB_CB(skb); | ||
165 | |||
166 | if (tx_ctl->epid == priv->mgmt_ep) { | ||
167 | struct tx_mgmt_hdr *tx_mhdr = | ||
168 | (struct tx_mgmt_hdr *)skb->data; | ||
169 | slot = tx_mhdr->cookie; | ||
170 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | ||
171 | } else if ((tx_ctl->epid == priv->data_bk_ep) || | ||
172 | (tx_ctl->epid == priv->data_be_ep) || | ||
173 | (tx_ctl->epid == priv->data_vi_ep) || | ||
174 | (tx_ctl->epid == priv->data_vo_ep) || | ||
175 | (tx_ctl->epid == priv->cab_ep)) { | ||
176 | struct tx_frame_hdr *tx_fhdr = | ||
177 | (struct tx_frame_hdr *)skb->data; | ||
178 | slot = tx_fhdr->cookie; | ||
179 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | ||
180 | } else { | ||
181 | ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); | ||
182 | slot = -EINVAL; | ||
183 | } | ||
184 | |||
185 | return slot; | ||
186 | } | ||
187 | |||
56 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 188 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
57 | struct ath9k_tx_queue_info *qinfo) | 189 | struct ath9k_tx_queue_info *qinfo) |
58 | { | 190 | { |
@@ -79,23 +211,140 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | |||
79 | return error; | 211 | return error; |
80 | } | 212 | } |
81 | 213 | ||
82 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | 214 | static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, |
215 | struct ath9k_htc_vif *avp, | ||
216 | struct sk_buff *skb, | ||
217 | u8 sta_idx, u8 vif_idx, u8 slot) | ||
218 | { | ||
219 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
220 | struct ieee80211_mgmt *mgmt; | ||
221 | struct ieee80211_hdr *hdr; | ||
222 | struct tx_mgmt_hdr mgmt_hdr; | ||
223 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
224 | u8 *tx_fhdr; | ||
225 | |||
226 | tx_ctl = HTC_SKB_CB(skb); | ||
227 | hdr = (struct ieee80211_hdr *) skb->data; | ||
228 | |||
229 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
230 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | ||
231 | |||
232 | /* | ||
233 | * Set the TSF adjust value for probe response | ||
234 | * frame also. | ||
235 | */ | ||
236 | if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { | ||
237 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
238 | mgmt->u.probe_resp.timestamp = avp->tsfadjust; | ||
239 | } | ||
240 | |||
241 | tx_ctl->type = ATH9K_HTC_MGMT; | ||
242 | |||
243 | mgmt_hdr.node_idx = sta_idx; | ||
244 | mgmt_hdr.vif_idx = vif_idx; | ||
245 | mgmt_hdr.tidno = 0; | ||
246 | mgmt_hdr.flags = 0; | ||
247 | mgmt_hdr.cookie = slot; | ||
248 | |||
249 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
250 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
251 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
252 | else | ||
253 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
254 | |||
255 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | ||
256 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | ||
257 | tx_ctl->epid = priv->mgmt_ep; | ||
258 | } | ||
259 | |||
260 | static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, | ||
261 | struct ieee80211_vif *vif, | ||
262 | struct sk_buff *skb, | ||
263 | u8 sta_idx, u8 vif_idx, u8 slot, | ||
264 | bool is_cab) | ||
265 | { | ||
266 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
267 | struct ieee80211_hdr *hdr; | ||
268 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
269 | struct tx_frame_hdr tx_hdr; | ||
270 | u32 flags = 0; | ||
271 | u8 *qc, *tx_fhdr; | ||
272 | u16 qnum; | ||
273 | |||
274 | tx_ctl = HTC_SKB_CB(skb); | ||
275 | hdr = (struct ieee80211_hdr *) skb->data; | ||
276 | |||
277 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
278 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | ||
279 | |||
280 | tx_hdr.node_idx = sta_idx; | ||
281 | tx_hdr.vif_idx = vif_idx; | ||
282 | tx_hdr.cookie = slot; | ||
283 | |||
284 | /* | ||
285 | * This is a bit redundant but it helps to get | ||
286 | * the per-packet index quickly when draining the | ||
287 | * TX queue in the HIF layer. Otherwise we would | ||
288 | * have to parse the packet contents ... | ||
289 | */ | ||
290 | tx_ctl->sta_idx = sta_idx; | ||
291 | |||
292 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
293 | tx_ctl->type = ATH9K_HTC_AMPDU; | ||
294 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | ||
295 | } else { | ||
296 | tx_ctl->type = ATH9K_HTC_NORMAL; | ||
297 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | ||
298 | } | ||
299 | |||
300 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
301 | qc = ieee80211_get_qos_ctl(hdr); | ||
302 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
303 | } | ||
304 | |||
305 | /* Check for RTS protection */ | ||
306 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | ||
307 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
308 | flags |= ATH9K_HTC_TX_RTSCTS; | ||
309 | |||
310 | /* CTS-to-self */ | ||
311 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | ||
312 | (vif && vif->bss_conf.use_cts_prot)) | ||
313 | flags |= ATH9K_HTC_TX_CTSONLY; | ||
314 | |||
315 | tx_hdr.flags = cpu_to_be32(flags); | ||
316 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
317 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
318 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
319 | else | ||
320 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
321 | |||
322 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | ||
323 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | ||
324 | |||
325 | if (is_cab) { | ||
326 | CAB_STAT_INC; | ||
327 | tx_ctl->epid = priv->cab_ep; | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | qnum = skb_get_queue_mapping(skb); | ||
332 | tx_ctl->epid = get_htc_epid(priv, qnum); | ||
333 | } | ||
334 | |||
335 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, | ||
336 | struct sk_buff *skb, | ||
337 | u8 slot, bool is_cab) | ||
83 | { | 338 | { |
84 | struct ieee80211_hdr *hdr; | 339 | struct ieee80211_hdr *hdr; |
85 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 340 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
86 | struct ieee80211_sta *sta = tx_info->control.sta; | 341 | struct ieee80211_sta *sta = tx_info->control.sta; |
87 | struct ieee80211_vif *vif = tx_info->control.vif; | 342 | struct ieee80211_vif *vif = tx_info->control.vif; |
88 | struct ath9k_htc_sta *ista; | 343 | struct ath9k_htc_sta *ista; |
89 | struct ath9k_htc_vif *avp; | 344 | struct ath9k_htc_vif *avp = NULL; |
90 | struct ath9k_htc_tx_ctl tx_ctl; | ||
91 | enum htc_endpoint_id epid; | ||
92 | u16 qnum; | ||
93 | __le16 fc; | ||
94 | u8 *tx_fhdr; | ||
95 | u8 sta_idx, vif_idx; | 345 | u8 sta_idx, vif_idx; |
96 | 346 | ||
97 | hdr = (struct ieee80211_hdr *) skb->data; | 347 | hdr = (struct ieee80211_hdr *) skb->data; |
98 | fc = hdr->frame_control; | ||
99 | 348 | ||
100 | /* | 349 | /* |
101 | * Find out on which interface this packet has to be | 350 | * Find out on which interface this packet has to be |
@@ -124,218 +373,432 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
124 | sta_idx = priv->vif_sta_pos[vif_idx]; | 373 | sta_idx = priv->vif_sta_pos[vif_idx]; |
125 | } | 374 | } |
126 | 375 | ||
127 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | 376 | if (ieee80211_is_data(hdr->frame_control)) |
377 | ath9k_htc_tx_data(priv, vif, skb, | ||
378 | sta_idx, vif_idx, slot, is_cab); | ||
379 | else | ||
380 | ath9k_htc_tx_mgmt(priv, avp, skb, | ||
381 | sta_idx, vif_idx, slot); | ||
128 | 382 | ||
129 | if (ieee80211_is_data(fc)) { | ||
130 | struct tx_frame_hdr tx_hdr; | ||
131 | u32 flags = 0; | ||
132 | u8 *qc; | ||
133 | 383 | ||
134 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | 384 | return htc_send(priv->htc, skb); |
385 | } | ||
135 | 386 | ||
136 | tx_hdr.node_idx = sta_idx; | 387 | static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, |
137 | tx_hdr.vif_idx = vif_idx; | 388 | struct ath9k_htc_sta *ista, u8 tid) |
389 | { | ||
390 | bool ret = false; | ||
138 | 391 | ||
139 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | 392 | spin_lock_bh(&priv->tx.tx_lock); |
140 | tx_ctl.type = ATH9K_HTC_AMPDU; | 393 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) |
141 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | 394 | ret = true; |
142 | } else { | 395 | spin_unlock_bh(&priv->tx.tx_lock); |
143 | tx_ctl.type = ATH9K_HTC_NORMAL; | 396 | |
144 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | 397 | return ret; |
145 | } | 398 | } |
399 | |||
400 | static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | ||
401 | struct ieee80211_vif *vif, | ||
402 | struct sk_buff *skb) | ||
403 | { | ||
404 | struct ieee80211_sta *sta; | ||
405 | struct ieee80211_hdr *hdr; | ||
406 | __le16 fc; | ||
407 | |||
408 | hdr = (struct ieee80211_hdr *) skb->data; | ||
409 | fc = hdr->frame_control; | ||
410 | |||
411 | rcu_read_lock(); | ||
412 | |||
413 | sta = ieee80211_find_sta(vif, hdr->addr1); | ||
414 | if (!sta) { | ||
415 | rcu_read_unlock(); | ||
416 | return; | ||
417 | } | ||
146 | 418 | ||
419 | if (sta && conf_is_ht(&priv->hw->conf) && | ||
420 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
147 | if (ieee80211_is_data_qos(fc)) { | 421 | if (ieee80211_is_data_qos(fc)) { |
422 | u8 *qc, tid; | ||
423 | struct ath9k_htc_sta *ista; | ||
424 | |||
148 | qc = ieee80211_get_qos_ctl(hdr); | 425 | qc = ieee80211_get_qos_ctl(hdr); |
149 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 426 | tid = qc[0] & 0xf; |
427 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | ||
428 | if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { | ||
429 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
430 | spin_lock_bh(&priv->tx.tx_lock); | ||
431 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
432 | spin_unlock_bh(&priv->tx.tx_lock); | ||
433 | } | ||
150 | } | 434 | } |
435 | } | ||
151 | 436 | ||
152 | /* Check for RTS protection */ | 437 | rcu_read_unlock(); |
153 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | 438 | } |
154 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
155 | flags |= ATH9K_HTC_TX_RTSCTS; | ||
156 | 439 | ||
157 | /* CTS-to-self */ | 440 | static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, |
158 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | 441 | struct sk_buff *skb, |
159 | (vif && vif->bss_conf.use_cts_prot)) | 442 | struct __wmi_event_txstatus *txs) |
160 | flags |= ATH9K_HTC_TX_CTSONLY; | 443 | { |
444 | struct ieee80211_vif *vif; | ||
445 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
446 | struct ieee80211_tx_info *tx_info; | ||
447 | struct ieee80211_tx_rate *rate; | ||
448 | struct ieee80211_conf *cur_conf = &priv->hw->conf; | ||
449 | struct ieee80211_supported_band *sband; | ||
450 | bool txok; | ||
451 | int slot; | ||
161 | 452 | ||
162 | tx_hdr.flags = cpu_to_be32(flags); | 453 | slot = strip_drv_header(priv, skb); |
163 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | 454 | if (slot < 0) { |
164 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | 455 | dev_kfree_skb_any(skb); |
165 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | 456 | return; |
166 | else | 457 | } |
167 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
168 | 458 | ||
169 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | 459 | tx_ctl = HTC_SKB_CB(skb); |
170 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | 460 | txok = tx_ctl->txok; |
461 | tx_info = IEEE80211_SKB_CB(skb); | ||
462 | vif = tx_info->control.vif; | ||
463 | rate = &tx_info->status.rates[0]; | ||
464 | sband = priv->hw->wiphy->bands[cur_conf->channel->band]; | ||
171 | 465 | ||
172 | qnum = skb_get_queue_mapping(skb); | 466 | memset(&tx_info->status, 0, sizeof(tx_info->status)); |
173 | 467 | ||
174 | switch (qnum) { | 468 | /* |
175 | case 0: | 469 | * URB submission failed for this frame, it never reached |
176 | TX_QSTAT_INC(WME_AC_VO); | 470 | * the target. |
177 | epid = priv->data_vo_ep; | 471 | */ |
178 | break; | 472 | if (!txok || !vif || !txs) |
179 | case 1: | 473 | goto send_mac80211; |
180 | TX_QSTAT_INC(WME_AC_VI); | ||
181 | epid = priv->data_vi_ep; | ||
182 | break; | ||
183 | case 2: | ||
184 | TX_QSTAT_INC(WME_AC_BE); | ||
185 | epid = priv->data_be_ep; | ||
186 | break; | ||
187 | case 3: | ||
188 | default: | ||
189 | TX_QSTAT_INC(WME_AC_BK); | ||
190 | epid = priv->data_bk_ep; | ||
191 | break; | ||
192 | } | ||
193 | } else { | ||
194 | struct tx_mgmt_hdr mgmt_hdr; | ||
195 | 474 | ||
196 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | 475 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) |
476 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
477 | |||
478 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) | ||
479 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
197 | 480 | ||
198 | tx_ctl.type = ATH9K_HTC_NORMAL; | 481 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS) |
482 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; | ||
199 | 483 | ||
200 | mgmt_hdr.node_idx = sta_idx; | 484 | rate->count = 1; |
201 | mgmt_hdr.vif_idx = vif_idx; | 485 | rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); |
202 | mgmt_hdr.tidno = 0; | ||
203 | mgmt_hdr.flags = 0; | ||
204 | 486 | ||
205 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | 487 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { |
206 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | 488 | rate->flags |= IEEE80211_TX_RC_MCS; |
207 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
208 | else | ||
209 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
210 | 489 | ||
211 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | 490 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40) |
212 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | 491 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
213 | epid = priv->mgmt_ep; | 492 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) |
493 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
494 | } else { | ||
495 | if (cur_conf->channel->band == IEEE80211_BAND_5GHZ) | ||
496 | rate->idx += 4; /* No CCK rates */ | ||
214 | } | 497 | } |
215 | 498 | ||
216 | return htc_send(priv->htc, skb, epid, &tx_ctl); | 499 | ath9k_htc_check_tx_aggr(priv, vif, skb); |
500 | |||
501 | send_mac80211: | ||
502 | spin_lock_bh(&priv->tx.tx_lock); | ||
503 | if (WARN_ON(--priv->tx.queued_cnt < 0)) | ||
504 | priv->tx.queued_cnt = 0; | ||
505 | spin_unlock_bh(&priv->tx.tx_lock); | ||
506 | |||
507 | ath9k_htc_tx_clear_slot(priv, slot); | ||
508 | |||
509 | /* Send status to mac80211 */ | ||
510 | ieee80211_tx_status(priv->hw, skb); | ||
217 | } | 511 | } |
218 | 512 | ||
219 | static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | 513 | static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, |
220 | struct ath9k_htc_sta *ista, u8 tid) | 514 | struct sk_buff_head *queue) |
221 | { | 515 | { |
222 | bool ret = false; | 516 | struct sk_buff *skb; |
223 | 517 | ||
224 | spin_lock_bh(&priv->tx_lock); | 518 | while ((skb = skb_dequeue(queue)) != NULL) { |
225 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) | 519 | ath9k_htc_tx_process(priv, skb, NULL); |
226 | ret = true; | 520 | } |
227 | spin_unlock_bh(&priv->tx_lock); | 521 | } |
228 | 522 | ||
229 | return ret; | 523 | void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) |
524 | { | ||
525 | struct ath9k_htc_tx_event *event, *tmp; | ||
526 | |||
527 | spin_lock_bh(&priv->tx.tx_lock); | ||
528 | priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; | ||
529 | spin_unlock_bh(&priv->tx.tx_lock); | ||
530 | |||
531 | /* | ||
532 | * Ensure that all pending TX frames are flushed, | ||
533 | * and that the TX completion/failed tasklets is killed. | ||
534 | */ | ||
535 | htc_stop(priv->htc); | ||
536 | tasklet_kill(&priv->wmi->wmi_event_tasklet); | ||
537 | tasklet_kill(&priv->tx_failed_tasklet); | ||
538 | |||
539 | ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue); | ||
540 | ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue); | ||
541 | ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue); | ||
542 | ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue); | ||
543 | ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue); | ||
544 | ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); | ||
545 | ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); | ||
546 | |||
547 | /* | ||
548 | * The TX cleanup timer has already been killed. | ||
549 | */ | ||
550 | spin_lock_bh(&priv->wmi->event_lock); | ||
551 | list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { | ||
552 | list_del(&event->list); | ||
553 | kfree(event); | ||
554 | } | ||
555 | spin_unlock_bh(&priv->wmi->event_lock); | ||
556 | |||
557 | spin_lock_bh(&priv->tx.tx_lock); | ||
558 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; | ||
559 | spin_unlock_bh(&priv->tx.tx_lock); | ||
230 | } | 560 | } |
231 | 561 | ||
232 | void ath9k_tx_tasklet(unsigned long data) | 562 | void ath9k_tx_failed_tasklet(unsigned long data) |
233 | { | 563 | { |
234 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 564 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
235 | struct ieee80211_vif *vif; | ||
236 | struct ieee80211_sta *sta; | ||
237 | struct ieee80211_hdr *hdr; | ||
238 | struct ieee80211_tx_info *tx_info; | ||
239 | struct sk_buff *skb = NULL; | ||
240 | __le16 fc; | ||
241 | 565 | ||
242 | while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { | 566 | spin_lock_bh(&priv->tx.tx_lock); |
567 | if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { | ||
568 | spin_unlock_bh(&priv->tx.tx_lock); | ||
569 | return; | ||
570 | } | ||
571 | spin_unlock_bh(&priv->tx.tx_lock); | ||
243 | 572 | ||
244 | hdr = (struct ieee80211_hdr *) skb->data; | 573 | ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); |
245 | fc = hdr->frame_control; | 574 | } |
246 | tx_info = IEEE80211_SKB_CB(skb); | ||
247 | vif = tx_info->control.vif; | ||
248 | 575 | ||
249 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 576 | static inline bool check_cookie(struct ath9k_htc_priv *priv, |
577 | struct sk_buff *skb, | ||
578 | u8 cookie, u8 epid) | ||
579 | { | ||
580 | u8 fcookie = 0; | ||
581 | |||
582 | if (epid == priv->mgmt_ep) { | ||
583 | struct tx_mgmt_hdr *hdr; | ||
584 | hdr = (struct tx_mgmt_hdr *) skb->data; | ||
585 | fcookie = hdr->cookie; | ||
586 | } else if ((epid == priv->data_bk_ep) || | ||
587 | (epid == priv->data_be_ep) || | ||
588 | (epid == priv->data_vi_ep) || | ||
589 | (epid == priv->data_vo_ep) || | ||
590 | (epid == priv->cab_ep)) { | ||
591 | struct tx_frame_hdr *hdr; | ||
592 | hdr = (struct tx_frame_hdr *) skb->data; | ||
593 | fcookie = hdr->cookie; | ||
594 | } | ||
250 | 595 | ||
251 | if (!vif) | 596 | if (fcookie == cookie) |
252 | goto send_mac80211; | 597 | return true; |
253 | 598 | ||
254 | rcu_read_lock(); | 599 | return false; |
600 | } | ||
255 | 601 | ||
256 | sta = ieee80211_find_sta(vif, hdr->addr1); | 602 | static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv, |
257 | if (!sta) { | 603 | struct __wmi_event_txstatus *txs) |
258 | rcu_read_unlock(); | 604 | { |
259 | ieee80211_tx_status(priv->hw, skb); | 605 | struct ath_common *common = ath9k_hw_common(priv->ah); |
260 | continue; | 606 | struct sk_buff_head *epid_queue; |
607 | struct sk_buff *skb, *tmp; | ||
608 | unsigned long flags; | ||
609 | u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID); | ||
610 | |||
611 | epid_queue = get_htc_epid_queue(priv, epid); | ||
612 | if (!epid_queue) | ||
613 | return NULL; | ||
614 | |||
615 | spin_lock_irqsave(&epid_queue->lock, flags); | ||
616 | skb_queue_walk_safe(epid_queue, skb, tmp) { | ||
617 | if (check_cookie(priv, skb, txs->cookie, epid)) { | ||
618 | __skb_unlink(skb, epid_queue); | ||
619 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
620 | return skb; | ||
261 | } | 621 | } |
622 | } | ||
623 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
262 | 624 | ||
263 | /* Check if we need to start aggregation */ | 625 | ath_dbg(common, ATH_DBG_XMIT, |
626 | "No matching packet for cookie: %d, epid: %d\n", | ||
627 | txs->cookie, epid); | ||
264 | 628 | ||
265 | if (sta && conf_is_ht(&priv->hw->conf) && | 629 | return NULL; |
266 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 630 | } |
267 | if (ieee80211_is_data_qos(fc)) { | ||
268 | u8 *qc, tid; | ||
269 | struct ath9k_htc_sta *ista; | ||
270 | 631 | ||
271 | qc = ieee80211_get_qos_ctl(hdr); | 632 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) |
272 | tid = qc[0] & 0xf; | 633 | { |
273 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | 634 | struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; |
635 | struct __wmi_event_txstatus *__txs; | ||
636 | struct sk_buff *skb; | ||
637 | struct ath9k_htc_tx_event *tx_pend; | ||
638 | int i; | ||
274 | 639 | ||
275 | if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { | 640 | for (i = 0; i < txs->cnt; i++) { |
276 | ieee80211_start_tx_ba_session(sta, tid, 0); | 641 | WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); |
277 | spin_lock_bh(&priv->tx_lock); | ||
278 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
279 | spin_unlock_bh(&priv->tx_lock); | ||
280 | } | ||
281 | } | ||
282 | } | ||
283 | 642 | ||
284 | rcu_read_unlock(); | 643 | __txs = &txs->txstatus[i]; |
644 | |||
645 | skb = ath9k_htc_tx_get_packet(priv, __txs); | ||
646 | if (!skb) { | ||
647 | /* | ||
648 | * Store this event, so that the TX cleanup | ||
649 | * routine can check later for the needed packet. | ||
650 | */ | ||
651 | tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event), | ||
652 | GFP_ATOMIC); | ||
653 | if (!tx_pend) | ||
654 | continue; | ||
655 | |||
656 | memcpy(&tx_pend->txs, __txs, | ||
657 | sizeof(struct __wmi_event_txstatus)); | ||
658 | |||
659 | spin_lock(&priv->wmi->event_lock); | ||
660 | list_add_tail(&tx_pend->list, | ||
661 | &priv->wmi->pending_tx_events); | ||
662 | spin_unlock(&priv->wmi->event_lock); | ||
285 | 663 | ||
286 | send_mac80211: | 664 | continue; |
287 | /* Send status to mac80211 */ | 665 | } |
288 | ieee80211_tx_status(priv->hw, skb); | 666 | |
667 | ath9k_htc_tx_process(priv, skb, __txs); | ||
289 | } | 668 | } |
290 | 669 | ||
291 | /* Wake TX queues if needed */ | 670 | /* Wake TX queues if needed */ |
292 | spin_lock_bh(&priv->tx_lock); | 671 | ath9k_htc_check_wake_queues(priv); |
293 | if (priv->tx_queues_stop) { | ||
294 | priv->tx_queues_stop = false; | ||
295 | spin_unlock_bh(&priv->tx_lock); | ||
296 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
297 | "Waking up TX queues\n"); | ||
298 | ieee80211_wake_queues(priv->hw); | ||
299 | return; | ||
300 | } | ||
301 | spin_unlock_bh(&priv->tx_lock); | ||
302 | } | 672 | } |
303 | 673 | ||
304 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, | 674 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, |
305 | enum htc_endpoint_id ep_id, bool txok) | 675 | enum htc_endpoint_id ep_id, bool txok) |
306 | { | 676 | { |
307 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; | 677 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; |
308 | struct ath_common *common = ath9k_hw_common(priv->ah); | 678 | struct ath9k_htc_tx_ctl *tx_ctl; |
309 | struct ieee80211_tx_info *tx_info; | 679 | struct sk_buff_head *epid_queue; |
310 | 680 | ||
311 | if (!skb) | 681 | tx_ctl = HTC_SKB_CB(skb); |
682 | tx_ctl->txok = txok; | ||
683 | tx_ctl->timestamp = jiffies; | ||
684 | |||
685 | if (!txok) { | ||
686 | skb_queue_tail(&priv->tx.tx_failed, skb); | ||
687 | tasklet_schedule(&priv->tx_failed_tasklet); | ||
312 | return; | 688 | return; |
689 | } | ||
313 | 690 | ||
314 | if (ep_id == priv->mgmt_ep) { | 691 | epid_queue = get_htc_epid_queue(priv, ep_id); |
315 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | 692 | if (!epid_queue) { |
316 | } else if ((ep_id == priv->data_bk_ep) || | ||
317 | (ep_id == priv->data_be_ep) || | ||
318 | (ep_id == priv->data_vi_ep) || | ||
319 | (ep_id == priv->data_vo_ep)) { | ||
320 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | ||
321 | } else { | ||
322 | ath_err(common, "Unsupported TX EPID: %d\n", ep_id); | ||
323 | dev_kfree_skb_any(skb); | 693 | dev_kfree_skb_any(skb); |
324 | return; | 694 | return; |
325 | } | 695 | } |
326 | 696 | ||
327 | tx_info = IEEE80211_SKB_CB(skb); | 697 | skb_queue_tail(epid_queue, skb); |
698 | } | ||
328 | 699 | ||
329 | if (txok) | 700 | static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb) |
330 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 701 | { |
702 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
703 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
331 | 704 | ||
332 | skb_queue_tail(&priv->tx_queue, skb); | 705 | tx_ctl = HTC_SKB_CB(skb); |
333 | tasklet_schedule(&priv->tx_tasklet); | 706 | |
707 | if (time_after(jiffies, | ||
708 | tx_ctl->timestamp + | ||
709 | msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) { | ||
710 | ath_dbg(common, ATH_DBG_XMIT, | ||
711 | "Dropping a packet due to TX timeout\n"); | ||
712 | return true; | ||
713 | } | ||
714 | |||
715 | return false; | ||
716 | } | ||
717 | |||
718 | static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv, | ||
719 | struct sk_buff_head *epid_queue) | ||
720 | { | ||
721 | bool process = false; | ||
722 | unsigned long flags; | ||
723 | struct sk_buff *skb, *tmp; | ||
724 | struct sk_buff_head queue; | ||
725 | |||
726 | skb_queue_head_init(&queue); | ||
727 | |||
728 | spin_lock_irqsave(&epid_queue->lock, flags); | ||
729 | skb_queue_walk_safe(epid_queue, skb, tmp) { | ||
730 | if (check_packet(priv, skb)) { | ||
731 | __skb_unlink(skb, epid_queue); | ||
732 | __skb_queue_tail(&queue, skb); | ||
733 | process = true; | ||
734 | } | ||
735 | } | ||
736 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
737 | |||
738 | if (process) { | ||
739 | skb_queue_walk_safe(&queue, skb, tmp) { | ||
740 | __skb_unlink(skb, &queue); | ||
741 | ath9k_htc_tx_process(priv, skb, NULL); | ||
742 | } | ||
743 | } | ||
744 | } | ||
745 | |||
746 | void ath9k_htc_tx_cleanup_timer(unsigned long data) | ||
747 | { | ||
748 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data; | ||
749 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
750 | struct ath9k_htc_tx_event *event, *tmp; | ||
751 | struct sk_buff *skb; | ||
752 | |||
753 | spin_lock(&priv->wmi->event_lock); | ||
754 | list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { | ||
755 | |||
756 | skb = ath9k_htc_tx_get_packet(priv, &event->txs); | ||
757 | if (skb) { | ||
758 | ath_dbg(common, ATH_DBG_XMIT, | ||
759 | "Found packet for cookie: %d, epid: %d\n", | ||
760 | event->txs.cookie, | ||
761 | MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID)); | ||
762 | |||
763 | ath9k_htc_tx_process(priv, skb, &event->txs); | ||
764 | list_del(&event->list); | ||
765 | kfree(event); | ||
766 | continue; | ||
767 | } | ||
768 | |||
769 | if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) { | ||
770 | list_del(&event->list); | ||
771 | kfree(event); | ||
772 | } | ||
773 | } | ||
774 | spin_unlock(&priv->wmi->event_lock); | ||
775 | |||
776 | /* | ||
777 | * Check if status-pending packets have to be cleaned up. | ||
778 | */ | ||
779 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue); | ||
780 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue); | ||
781 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue); | ||
782 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue); | ||
783 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue); | ||
784 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue); | ||
785 | |||
786 | /* Wake TX queues if needed */ | ||
787 | ath9k_htc_check_wake_queues(priv); | ||
788 | |||
789 | mod_timer(&priv->tx.cleanup_timer, | ||
790 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
334 | } | 791 | } |
335 | 792 | ||
336 | int ath9k_tx_init(struct ath9k_htc_priv *priv) | 793 | int ath9k_tx_init(struct ath9k_htc_priv *priv) |
337 | { | 794 | { |
338 | skb_queue_head_init(&priv->tx_queue); | 795 | skb_queue_head_init(&priv->tx.mgmt_ep_queue); |
796 | skb_queue_head_init(&priv->tx.cab_ep_queue); | ||
797 | skb_queue_head_init(&priv->tx.data_be_queue); | ||
798 | skb_queue_head_init(&priv->tx.data_bk_queue); | ||
799 | skb_queue_head_init(&priv->tx.data_vi_queue); | ||
800 | skb_queue_head_init(&priv->tx.data_vo_queue); | ||
801 | skb_queue_head_init(&priv->tx.tx_failed); | ||
339 | return 0; | 802 | return 0; |
340 | } | 803 | } |
341 | 804 | ||
@@ -507,8 +970,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
507 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | 970 | int last_rssi = ATH_RSSI_DUMMY_MARKER; |
508 | __le16 fc; | 971 | __le16 fc; |
509 | 972 | ||
510 | if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { | 973 | if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { |
511 | ath_err(common, "Corrupted RX frame, dropping\n"); | 974 | ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", |
975 | skb->len); | ||
512 | goto rx_next; | 976 | goto rx_next; |
513 | } | 977 | } |
514 | 978 | ||
@@ -522,6 +986,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
522 | goto rx_next; | 986 | goto rx_next; |
523 | } | 987 | } |
524 | 988 | ||
989 | ath9k_htc_err_stat_rx(priv, rxstatus); | ||
990 | |||
525 | /* Get the RX status information */ | 991 | /* Get the RX status information */ |
526 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | 992 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); |
527 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | 993 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 62e139a30a74..cee970fdf652 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | 19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, |
20 | u16 len, u8 flags, u8 epid, | 20 | u16 len, u8 flags, u8 epid) |
21 | struct ath9k_htc_tx_ctl *tx_ctl) | 21 | |
22 | { | 22 | { |
23 | struct htc_frame_hdr *hdr; | 23 | struct htc_frame_hdr *hdr; |
24 | struct htc_endpoint *endpoint = &target->endpoint[epid]; | 24 | struct htc_endpoint *endpoint = &target->endpoint[epid]; |
@@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | |||
30 | hdr->flags = flags; | 30 | hdr->flags = flags; |
31 | hdr->payload_len = cpu_to_be16(len); | 31 | hdr->payload_len = cpu_to_be16(len); |
32 | 32 | ||
33 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, | 33 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); |
34 | tx_ctl); | 34 | |
35 | return status; | 35 | return status; |
36 | } | 36 | } |
37 | 37 | ||
@@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target) | |||
162 | 162 | ||
163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; | 163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; |
164 | 164 | ||
165 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 165 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
166 | if (ret) | 166 | if (ret) |
167 | goto err; | 167 | goto err; |
168 | 168 | ||
@@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target) | |||
197 | 197 | ||
198 | target->htc_flags |= HTC_OP_START_WAIT; | 198 | target->htc_flags |= HTC_OP_START_WAIT; |
199 | 199 | ||
200 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 200 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
201 | if (ret) | 201 | if (ret) |
202 | goto err; | 202 | goto err; |
203 | 203 | ||
@@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target, | |||
268 | conn_msg->dl_pipeid = endpoint->dl_pipeid; | 268 | conn_msg->dl_pipeid = endpoint->dl_pipeid; |
269 | conn_msg->ul_pipeid = endpoint->ul_pipeid; | 269 | conn_msg->ul_pipeid = endpoint->ul_pipeid; |
270 | 270 | ||
271 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 271 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
272 | if (ret) | 272 | if (ret) |
273 | goto err; | 273 | goto err; |
274 | 274 | ||
@@ -286,35 +286,33 @@ err: | |||
286 | return ret; | 286 | return ret; |
287 | } | 287 | } |
288 | 288 | ||
289 | int htc_send(struct htc_target *target, struct sk_buff *skb, | 289 | int htc_send(struct htc_target *target, struct sk_buff *skb) |
290 | enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) | ||
291 | { | 290 | { |
292 | return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); | 291 | struct ath9k_htc_tx_ctl *tx_ctl; |
292 | |||
293 | tx_ctl = HTC_SKB_CB(skb); | ||
294 | return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid); | ||
293 | } | 295 | } |
294 | 296 | ||
295 | void htc_stop(struct htc_target *target) | 297 | int htc_send_epid(struct htc_target *target, struct sk_buff *skb, |
298 | enum htc_endpoint_id epid) | ||
296 | { | 299 | { |
297 | enum htc_endpoint_id epid; | 300 | return htc_issue_send(target, skb, skb->len, 0, epid); |
298 | struct htc_endpoint *endpoint; | 301 | } |
299 | 302 | ||
300 | for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { | 303 | void htc_stop(struct htc_target *target) |
301 | endpoint = &target->endpoint[epid]; | 304 | { |
302 | if (endpoint->service_id != 0) | 305 | target->hif->stop(target->hif_dev); |
303 | target->hif->stop(target->hif_dev, endpoint->ul_pipeid); | ||
304 | } | ||
305 | } | 306 | } |
306 | 307 | ||
307 | void htc_start(struct htc_target *target) | 308 | void htc_start(struct htc_target *target) |
308 | { | 309 | { |
309 | enum htc_endpoint_id epid; | 310 | target->hif->start(target->hif_dev); |
310 | struct htc_endpoint *endpoint; | 311 | } |
311 | 312 | ||
312 | for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { | 313 | void htc_sta_drain(struct htc_target *target, u8 idx) |
313 | endpoint = &target->endpoint[epid]; | 314 | { |
314 | if (endpoint->service_id != 0) | 315 | target->hif->sta_drain(target->hif_dev, idx); |
315 | target->hif->start(target->hif_dev, | ||
316 | endpoint->ul_pipeid); | ||
317 | } | ||
318 | } | 316 | } |
319 | 317 | ||
320 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | 318 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index ecd018798c47..cb9174ade53e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -33,10 +33,10 @@ struct ath9k_htc_hif { | |||
33 | u8 control_dl_pipe; | 33 | u8 control_dl_pipe; |
34 | u8 control_ul_pipe; | 34 | u8 control_ul_pipe; |
35 | 35 | ||
36 | void (*start) (void *hif_handle, u8 pipe); | 36 | void (*start) (void *hif_handle); |
37 | void (*stop) (void *hif_handle, u8 pipe); | 37 | void (*stop) (void *hif_handle); |
38 | int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, | 38 | void (*sta_drain) (void *hif_handle, u8 idx); |
39 | struct ath9k_htc_tx_ctl *tx_ctl); | 39 | int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | enum htc_endpoint_id { | 42 | enum htc_endpoint_id { |
@@ -205,10 +205,12 @@ int htc_init(struct htc_target *target); | |||
205 | int htc_connect_service(struct htc_target *target, | 205 | int htc_connect_service(struct htc_target *target, |
206 | struct htc_service_connreq *service_connreq, | 206 | struct htc_service_connreq *service_connreq, |
207 | enum htc_endpoint_id *conn_rsp_eid); | 207 | enum htc_endpoint_id *conn_rsp_eid); |
208 | int htc_send(struct htc_target *target, struct sk_buff *skb, | 208 | int htc_send(struct htc_target *target, struct sk_buff *skb); |
209 | enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); | 209 | int htc_send_epid(struct htc_target *target, struct sk_buff *skb, |
210 | enum htc_endpoint_id epid); | ||
210 | void htc_stop(struct htc_target *target); | 211 | void htc_stop(struct htc_target *target); |
211 | void htc_start(struct htc_target *target); | 212 | void htc_start(struct htc_target *target); |
213 | void htc_sta_drain(struct htc_target *target, u8 idx); | ||
212 | 214 | ||
213 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, | 215 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, |
214 | struct sk_buff *skb, u32 len, u8 pipe_id); | 216 | struct sk_buff *skb, u32 len, u8 pipe_id); |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 22ee888b0baf..9dd90a85ad63 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | |||
122 | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); | 122 | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); |
123 | } | 123 | } |
124 | 124 | ||
125 | static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
126 | { | ||
127 | ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); | ||
128 | } | ||
129 | |||
125 | /* Private hardware call ops */ | 130 | /* Private hardware call ops */ |
126 | 131 | ||
127 | /* PHY ops */ | 132 | /* PHY ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c8a2d0dae796..045abd557840 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -676,42 +676,55 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) | |||
676 | } | 676 | } |
677 | EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); | 677 | EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); |
678 | 678 | ||
679 | #define DPLL2_KD_VAL 0x3D | 679 | #define DPLL3_PHASE_SHIFT_VAL 0x1 |
680 | #define DPLL2_KI_VAL 0x06 | ||
681 | #define DPLL3_PHASE_SHIFT_VAL 0x1 | ||
682 | |||
683 | static void ath9k_hw_init_pll(struct ath_hw *ah, | 680 | static void ath9k_hw_init_pll(struct ath_hw *ah, |
684 | struct ath9k_channel *chan) | 681 | struct ath9k_channel *chan) |
685 | { | 682 | { |
686 | u32 pll; | 683 | u32 pll; |
687 | 684 | ||
688 | if (AR_SREV_9485(ah)) { | 685 | if (AR_SREV_9485(ah)) { |
689 | REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); | ||
690 | REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); | ||
691 | |||
692 | REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, | ||
693 | AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); | ||
694 | 686 | ||
695 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); | 687 | /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ |
696 | udelay(1000); | 688 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, |
689 | AR_CH0_BB_DPLL2_PLL_PWD, 0x1); | ||
690 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
691 | AR_CH0_DPLL2_KD, 0x40); | ||
692 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
693 | AR_CH0_DPLL2_KI, 0x4); | ||
697 | 694 | ||
698 | REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); | 695 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, |
696 | AR_CH0_BB_DPLL1_REFDIV, 0x5); | ||
697 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, | ||
698 | AR_CH0_BB_DPLL1_NINI, 0x58); | ||
699 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, | ||
700 | AR_CH0_BB_DPLL1_NFRAC, 0x0); | ||
699 | 701 | ||
700 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | 702 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, |
701 | AR_CH0_DPLL2_KD, DPLL2_KD_VAL); | 703 | AR_CH0_BB_DPLL2_OUTDIV, 0x1); |
704 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
705 | AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); | ||
702 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | 706 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, |
703 | AR_CH0_DPLL2_KI, DPLL2_KI_VAL); | 707 | AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); |
704 | 708 | ||
709 | /* program BB PLL phase_shift to 0x6 */ | ||
705 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | 710 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, |
706 | AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); | 711 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); |
707 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); | 712 | |
713 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
714 | AR_CH0_BB_DPLL2_PLL_PWD, 0x0); | ||
708 | udelay(1000); | 715 | udelay(1000); |
716 | |||
717 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | ||
718 | AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); | ||
709 | } | 719 | } |
710 | 720 | ||
711 | pll = ath9k_hw_compute_pll_control(ah, chan); | 721 | pll = ath9k_hw_compute_pll_control(ah, chan); |
712 | 722 | ||
713 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); | 723 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); |
714 | 724 | ||
725 | if (AR_SREV_9485(ah)) | ||
726 | udelay(1000); | ||
727 | |||
715 | /* Switch the core clock for ar9271 to 117Mhz */ | 728 | /* Switch the core clock for ar9271 to 117Mhz */ |
716 | if (AR_SREV_9271(ah)) { | 729 | if (AR_SREV_9271(ah)) { |
717 | udelay(500); | 730 | udelay(500); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a778b66f4438..1018d6cbd530 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -626,6 +626,7 @@ struct ath_hw_ops { | |||
626 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); | 626 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); |
627 | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, | 627 | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, |
628 | u32 burstDuration); | 628 | u32 burstDuration); |
629 | void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); | ||
629 | }; | 630 | }; |
630 | 631 | ||
631 | struct ath_nf_limits { | 632 | struct ath_nf_limits { |
@@ -846,6 +847,14 @@ struct ath_hw { | |||
846 | u32 ent_mode; | 847 | u32 ent_mode; |
847 | }; | 848 | }; |
848 | 849 | ||
850 | struct ath_bus_ops { | ||
851 | enum ath_bus_type ath_bus_type; | ||
852 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
853 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
854 | void (*bt_coex_prep)(struct ath_common *common); | ||
855 | void (*extn_synch_en)(struct ath_common *common); | ||
856 | }; | ||
857 | |||
849 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 858 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) |
850 | { | 859 | { |
851 | return &ah->common; | 860 | return &ah->common; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index c2a59386fb9c..b60c130917f7 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -239,7 +239,6 @@ struct ath_desc { | |||
239 | void *ds_vdata; | 239 | void *ds_vdata; |
240 | } __packed __aligned(4); | 240 | } __packed __aligned(4); |
241 | 241 | ||
242 | #define ATH9K_TXDESC_CLRDMASK 0x0001 | ||
243 | #define ATH9K_TXDESC_NOACK 0x0002 | 242 | #define ATH9K_TXDESC_NOACK 0x0002 |
244 | #define ATH9K_TXDESC_RTSENA 0x0004 | 243 | #define ATH9K_TXDESC_RTSENA 0x0004 |
245 | #define ATH9K_TXDESC_CTSENA 0x0008 | 244 | #define ATH9K_TXDESC_CTSENA 0x0008 |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4c5c9997dac6..a8d9009a76d5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1373,6 +1373,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1373 | if ((iter_data.naps + iter_data.nadhocs) > 0) { | 1373 | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
1374 | sc->sc_flags |= SC_OP_ANI_RUN; | 1374 | sc->sc_flags |= SC_OP_ANI_RUN; |
1375 | ath_start_ani(common); | 1375 | ath_start_ani(common); |
1376 | } else { | ||
1377 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1378 | del_timer_sync(&common->ani.timer); | ||
1376 | } | 1379 | } |
1377 | } | 1380 | } |
1378 | 1381 | ||
@@ -1733,23 +1736,63 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
1733 | struct ieee80211_sta *sta) | 1736 | struct ieee80211_sta *sta) |
1734 | { | 1737 | { |
1735 | struct ath_softc *sc = hw->priv; | 1738 | struct ath_softc *sc = hw->priv; |
1739 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1740 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1741 | struct ieee80211_key_conf ps_key = { }; | ||
1736 | 1742 | ||
1737 | ath_node_attach(sc, sta); | 1743 | ath_node_attach(sc, sta); |
1744 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); | ||
1738 | 1745 | ||
1739 | return 0; | 1746 | return 0; |
1740 | } | 1747 | } |
1741 | 1748 | ||
1749 | static void ath9k_del_ps_key(struct ath_softc *sc, | ||
1750 | struct ieee80211_vif *vif, | ||
1751 | struct ieee80211_sta *sta) | ||
1752 | { | ||
1753 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1754 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1755 | struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; | ||
1756 | |||
1757 | if (!an->ps_key) | ||
1758 | return; | ||
1759 | |||
1760 | ath_key_delete(common, &ps_key); | ||
1761 | } | ||
1762 | |||
1742 | static int ath9k_sta_remove(struct ieee80211_hw *hw, | 1763 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
1743 | struct ieee80211_vif *vif, | 1764 | struct ieee80211_vif *vif, |
1744 | struct ieee80211_sta *sta) | 1765 | struct ieee80211_sta *sta) |
1745 | { | 1766 | { |
1746 | struct ath_softc *sc = hw->priv; | 1767 | struct ath_softc *sc = hw->priv; |
1747 | 1768 | ||
1769 | ath9k_del_ps_key(sc, vif, sta); | ||
1748 | ath_node_detach(sc, sta); | 1770 | ath_node_detach(sc, sta); |
1749 | 1771 | ||
1750 | return 0; | 1772 | return 0; |
1751 | } | 1773 | } |
1752 | 1774 | ||
1775 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | ||
1776 | struct ieee80211_vif *vif, | ||
1777 | enum sta_notify_cmd cmd, | ||
1778 | struct ieee80211_sta *sta) | ||
1779 | { | ||
1780 | struct ath_softc *sc = hw->priv; | ||
1781 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1782 | |||
1783 | switch (cmd) { | ||
1784 | case STA_NOTIFY_SLEEP: | ||
1785 | an->sleeping = true; | ||
1786 | if (ath_tx_aggr_sleep(sc, an)) | ||
1787 | ieee80211_sta_set_tim(sta); | ||
1788 | break; | ||
1789 | case STA_NOTIFY_AWAKE: | ||
1790 | an->sleeping = false; | ||
1791 | ath_tx_aggr_wakeup(sc, an); | ||
1792 | break; | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1753 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1796 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
1754 | const struct ieee80211_tx_queue_params *params) | 1797 | const struct ieee80211_tx_queue_params *params) |
1755 | { | 1798 | { |
@@ -1826,6 +1869,9 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1826 | 1869 | ||
1827 | switch (cmd) { | 1870 | switch (cmd) { |
1828 | case SET_KEY: | 1871 | case SET_KEY: |
1872 | if (sta) | ||
1873 | ath9k_del_ps_key(sc, vif, sta); | ||
1874 | |||
1829 | ret = ath_key_config(common, vif, sta, key); | 1875 | ret = ath_key_config(common, vif, sta, key); |
1830 | if (ret >= 0) { | 1876 | if (ret >= 0) { |
1831 | key->hw_key_idx = ret; | 1877 | key->hw_key_idx = ret; |
@@ -2209,6 +2255,21 @@ out: | |||
2209 | ath9k_ps_restore(sc); | 2255 | ath9k_ps_restore(sc); |
2210 | } | 2256 | } |
2211 | 2257 | ||
2258 | static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) | ||
2259 | { | ||
2260 | struct ath_softc *sc = hw->priv; | ||
2261 | int i; | ||
2262 | |||
2263 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2264 | if (!ATH_TXQ_SETUP(sc, i)) | ||
2265 | continue; | ||
2266 | |||
2267 | if (ath9k_has_pending_frames(sc, &sc->tx.txq[i])) | ||
2268 | return true; | ||
2269 | } | ||
2270 | return false; | ||
2271 | } | ||
2272 | |||
2212 | struct ieee80211_ops ath9k_ops = { | 2273 | struct ieee80211_ops ath9k_ops = { |
2213 | .tx = ath9k_tx, | 2274 | .tx = ath9k_tx, |
2214 | .start = ath9k_start, | 2275 | .start = ath9k_start, |
@@ -2220,6 +2281,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2220 | .configure_filter = ath9k_configure_filter, | 2281 | .configure_filter = ath9k_configure_filter, |
2221 | .sta_add = ath9k_sta_add, | 2282 | .sta_add = ath9k_sta_add, |
2222 | .sta_remove = ath9k_sta_remove, | 2283 | .sta_remove = ath9k_sta_remove, |
2284 | .sta_notify = ath9k_sta_notify, | ||
2223 | .conf_tx = ath9k_conf_tx, | 2285 | .conf_tx = ath9k_conf_tx, |
2224 | .bss_info_changed = ath9k_bss_info_changed, | 2286 | .bss_info_changed = ath9k_bss_info_changed, |
2225 | .set_key = ath9k_set_key, | 2287 | .set_key = ath9k_set_key, |
@@ -2231,4 +2293,5 @@ struct ieee80211_ops ath9k_ops = { | |||
2231 | .rfkill_poll = ath9k_rfkill_poll_state, | 2293 | .rfkill_poll = ath9k_rfkill_poll_state, |
2232 | .set_coverage_class = ath9k_set_coverage_class, | 2294 | .set_coverage_class = ath9k_set_coverage_class, |
2233 | .flush = ath9k_flush, | 2295 | .flush = ath9k_flush, |
2296 | .tx_frames_pending = ath9k_tx_frames_pending, | ||
2234 | }; | 2297 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index f50e2c29f71e..8e5fe9d7f174 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #define CHANSEL_DIV 15 | 20 | #define CHANSEL_DIV 15 |
21 | #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) | 21 | #define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV) |
22 | #define CHANSEL_2G_9485(_freq) ((((_freq) * 0x10000) - 215) / CHANSEL_DIV) | ||
23 | #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) | 22 | #define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV) |
24 | 23 | ||
25 | #define AR_PHY_BASE 0x9800 | 24 | #define AR_PHY_BASE 0x9800 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4c0d36a6980f..18094094b298 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1092,8 +1092,7 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, | |||
1092 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) | 1092 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) |
1093 | return rate->idx; | 1093 | return rate->idx; |
1094 | 1094 | ||
1095 | while (rate->idx > mcs_rix_off[i] && | 1095 | while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { |
1096 | i < ARRAY_SIZE(mcs_rix_off)) { | ||
1097 | rix++; i++; | 1096 | rix++; i++; |
1098 | } | 1097 | } |
1099 | 1098 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index cfaf0a48b939..642504f9638c 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
75 | *sc->rx.rxlink = bf->bf_daddr; | 75 | *sc->rx.rxlink = bf->bf_daddr; |
76 | 76 | ||
77 | sc->rx.rxlink = &ds->ds_link; | 77 | sc->rx.rxlink = &ds->ds_link; |
78 | ath9k_hw_rxena(ah); | ||
79 | } | 78 | } |
80 | 79 | ||
81 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) | 80 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
@@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
426 | else | 425 | else |
427 | rfilt |= ATH9K_RX_FILTER_BEACON; | 426 | rfilt |= ATH9K_RX_FILTER_BEACON; |
428 | 427 | ||
429 | if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || | 428 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
430 | AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && | ||
431 | (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
432 | (sc->rx.rxfilter & FIF_PSPOLL)) | 429 | (sc->rx.rxfilter & FIF_PSPOLL)) |
433 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | 430 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
434 | 431 | ||
@@ -1767,6 +1764,7 @@ requeue: | |||
1767 | } else { | 1764 | } else { |
1768 | list_move_tail(&bf->list, &sc->rx.rxbuf); | 1765 | list_move_tail(&bf->list, &sc->rx.rxbuf); |
1769 | ath_rx_buf_link(sc, bf); | 1766 | ath_rx_buf_link(sc, bf); |
1767 | ath9k_hw_rxena(ah); | ||
1770 | } | 1768 | } |
1771 | } while (1); | 1769 | } while (1); |
1772 | 1770 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 693d543937b5..6acbf0e2240b 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -858,9 +858,7 @@ | |||
858 | #define AR_SREV_9300(_ah) \ | 858 | #define AR_SREV_9300(_ah) \ |
859 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) | 859 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) |
860 | #define AR_SREV_9300_20_OR_LATER(_ah) \ | 860 | #define AR_SREV_9300_20_OR_LATER(_ah) \ |
861 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ | 861 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) |
862 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ | ||
863 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) | ||
864 | 862 | ||
865 | #define AR_SREV_9485(_ah) \ | 863 | #define AR_SREV_9485(_ah) \ |
866 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 864 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
@@ -1088,14 +1086,35 @@ enum { | |||
1088 | #define AR_ENT_OTP 0x40d8 | 1086 | #define AR_ENT_OTP 0x40d8 |
1089 | #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 | 1087 | #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 |
1090 | #define AR_ENT_OTP_MPSD 0x00800000 | 1088 | #define AR_ENT_OTP_MPSD 0x00800000 |
1091 | #define AR_CH0_BB_DPLL2 0x16184 | 1089 | |
1090 | #define AR_CH0_BB_DPLL1 0x16180 | ||
1091 | #define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 | ||
1092 | #define AR_CH0_BB_DPLL1_REFDIV_S 27 | ||
1093 | #define AR_CH0_BB_DPLL1_NINI 0x07FC0000 | ||
1094 | #define AR_CH0_BB_DPLL1_NINI_S 18 | ||
1095 | #define AR_CH0_BB_DPLL1_NFRAC 0x0003FFFF | ||
1096 | #define AR_CH0_BB_DPLL1_NFRAC_S 0 | ||
1097 | |||
1098 | #define AR_CH0_BB_DPLL2 0x16184 | ||
1099 | #define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000 | ||
1100 | #define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30 | ||
1101 | #define AR_CH0_DPLL2_KI 0x3C000000 | ||
1102 | #define AR_CH0_DPLL2_KI_S 26 | ||
1103 | #define AR_CH0_DPLL2_KD 0x03F80000 | ||
1104 | #define AR_CH0_DPLL2_KD_S 19 | ||
1105 | #define AR_CH0_BB_DPLL2_EN_NEGTRIG 0x00040000 | ||
1106 | #define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18 | ||
1107 | #define AR_CH0_BB_DPLL2_PLL_PWD 0x00010000 | ||
1108 | #define AR_CH0_BB_DPLL2_PLL_PWD_S 16 | ||
1109 | #define AR_CH0_BB_DPLL2_OUTDIV 0x0000E000 | ||
1110 | #define AR_CH0_BB_DPLL2_OUTDIV_S 13 | ||
1111 | |||
1092 | #define AR_CH0_BB_DPLL3 0x16188 | 1112 | #define AR_CH0_BB_DPLL3 0x16188 |
1113 | #define AR_CH0_BB_DPLL3_PHASE_SHIFT 0x3F800000 | ||
1114 | #define AR_CH0_BB_DPLL3_PHASE_SHIFT_S 23 | ||
1115 | |||
1093 | #define AR_CH0_DDR_DPLL2 0x16244 | 1116 | #define AR_CH0_DDR_DPLL2 0x16244 |
1094 | #define AR_CH0_DDR_DPLL3 0x16248 | 1117 | #define AR_CH0_DDR_DPLL3 0x16248 |
1095 | #define AR_CH0_DPLL2_KD 0x03F80000 | ||
1096 | #define AR_CH0_DPLL2_KD_S 19 | ||
1097 | #define AR_CH0_DPLL2_KI 0x3C000000 | ||
1098 | #define AR_CH0_DPLL2_KI_S 26 | ||
1099 | #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 | 1118 | #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 |
1100 | #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 | 1119 | #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 |
1101 | #define AR_PHY_CCA_NOM_VAL_2GHZ -118 | 1120 | #define AR_PHY_CCA_NOM_VAL_2GHZ -118 |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index d3d24904f62f..8f095ad0a3db 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -23,20 +23,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
23 | return "WMI_ECHO_CMDID"; | 23 | return "WMI_ECHO_CMDID"; |
24 | case WMI_ACCESS_MEMORY_CMDID: | 24 | case WMI_ACCESS_MEMORY_CMDID: |
25 | return "WMI_ACCESS_MEMORY_CMDID"; | 25 | return "WMI_ACCESS_MEMORY_CMDID"; |
26 | case WMI_GET_FW_VERSION: | ||
27 | return "WMI_GET_FW_VERSION"; | ||
26 | case WMI_DISABLE_INTR_CMDID: | 28 | case WMI_DISABLE_INTR_CMDID: |
27 | return "WMI_DISABLE_INTR_CMDID"; | 29 | return "WMI_DISABLE_INTR_CMDID"; |
28 | case WMI_ENABLE_INTR_CMDID: | 30 | case WMI_ENABLE_INTR_CMDID: |
29 | return "WMI_ENABLE_INTR_CMDID"; | 31 | return "WMI_ENABLE_INTR_CMDID"; |
30 | case WMI_RX_LINK_CMDID: | ||
31 | return "WMI_RX_LINK_CMDID"; | ||
32 | case WMI_ATH_INIT_CMDID: | 32 | case WMI_ATH_INIT_CMDID: |
33 | return "WMI_ATH_INIT_CMDID"; | 33 | return "WMI_ATH_INIT_CMDID"; |
34 | case WMI_ABORT_TXQ_CMDID: | 34 | case WMI_ABORT_TXQ_CMDID: |
35 | return "WMI_ABORT_TXQ_CMDID"; | 35 | return "WMI_ABORT_TXQ_CMDID"; |
36 | case WMI_STOP_TX_DMA_CMDID: | 36 | case WMI_STOP_TX_DMA_CMDID: |
37 | return "WMI_STOP_TX_DMA_CMDID"; | 37 | return "WMI_STOP_TX_DMA_CMDID"; |
38 | case WMI_STOP_DMA_RECV_CMDID: | ||
39 | return "WMI_STOP_DMA_RECV_CMDID"; | ||
40 | case WMI_ABORT_TX_DMA_CMDID: | 38 | case WMI_ABORT_TX_DMA_CMDID: |
41 | return "WMI_ABORT_TX_DMA_CMDID"; | 39 | return "WMI_ABORT_TX_DMA_CMDID"; |
42 | case WMI_DRAIN_TXQ_CMDID: | 40 | case WMI_DRAIN_TXQ_CMDID: |
@@ -51,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
51 | return "WMI_FLUSH_RECV_CMDID"; | 49 | return "WMI_FLUSH_RECV_CMDID"; |
52 | case WMI_SET_MODE_CMDID: | 50 | case WMI_SET_MODE_CMDID: |
53 | return "WMI_SET_MODE_CMDID"; | 51 | return "WMI_SET_MODE_CMDID"; |
54 | case WMI_RESET_CMDID: | ||
55 | return "WMI_RESET_CMDID"; | ||
56 | case WMI_NODE_CREATE_CMDID: | 52 | case WMI_NODE_CREATE_CMDID: |
57 | return "WMI_NODE_CREATE_CMDID"; | 53 | return "WMI_NODE_CREATE_CMDID"; |
58 | case WMI_NODE_REMOVE_CMDID: | 54 | case WMI_NODE_REMOVE_CMDID: |
@@ -61,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
61 | return "WMI_VAP_REMOVE_CMDID"; | 57 | return "WMI_VAP_REMOVE_CMDID"; |
62 | case WMI_VAP_CREATE_CMDID: | 58 | case WMI_VAP_CREATE_CMDID: |
63 | return "WMI_VAP_CREATE_CMDID"; | 59 | return "WMI_VAP_CREATE_CMDID"; |
64 | case WMI_BEACON_UPDATE_CMDID: | ||
65 | return "WMI_BEACON_UPDATE_CMDID"; | ||
66 | case WMI_REG_READ_CMDID: | 60 | case WMI_REG_READ_CMDID: |
67 | return "WMI_REG_READ_CMDID"; | 61 | return "WMI_REG_READ_CMDID"; |
68 | case WMI_REG_WRITE_CMDID: | 62 | case WMI_REG_WRITE_CMDID: |
@@ -71,20 +65,20 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
71 | return "WMI_RC_STATE_CHANGE_CMDID"; | 65 | return "WMI_RC_STATE_CHANGE_CMDID"; |
72 | case WMI_RC_RATE_UPDATE_CMDID: | 66 | case WMI_RC_RATE_UPDATE_CMDID: |
73 | return "WMI_RC_RATE_UPDATE_CMDID"; | 67 | return "WMI_RC_RATE_UPDATE_CMDID"; |
74 | case WMI_DEBUG_INFO_CMDID: | ||
75 | return "WMI_DEBUG_INFO_CMDID"; | ||
76 | case WMI_HOST_ATTACH: | ||
77 | return "WMI_HOST_ATTACH"; | ||
78 | case WMI_TARGET_IC_UPDATE_CMDID: | 68 | case WMI_TARGET_IC_UPDATE_CMDID: |
79 | return "WMI_TARGET_IC_UPDATE_CMDID"; | 69 | return "WMI_TARGET_IC_UPDATE_CMDID"; |
80 | case WMI_TGT_STATS_CMDID: | ||
81 | return "WMI_TGT_STATS_CMDID"; | ||
82 | case WMI_TX_AGGR_ENABLE_CMDID: | 70 | case WMI_TX_AGGR_ENABLE_CMDID: |
83 | return "WMI_TX_AGGR_ENABLE_CMDID"; | 71 | return "WMI_TX_AGGR_ENABLE_CMDID"; |
84 | case WMI_TGT_DETACH_CMDID: | 72 | case WMI_TGT_DETACH_CMDID: |
85 | return "WMI_TGT_DETACH_CMDID"; | 73 | return "WMI_TGT_DETACH_CMDID"; |
86 | case WMI_TGT_TXQ_ENABLE_CMDID: | 74 | case WMI_NODE_UPDATE_CMDID: |
87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; | 75 | return "WMI_NODE_UPDATE_CMDID"; |
76 | case WMI_INT_STATS_CMDID: | ||
77 | return "WMI_INT_STATS_CMDID"; | ||
78 | case WMI_TX_STATS_CMDID: | ||
79 | return "WMI_TX_STATS_CMDID"; | ||
80 | case WMI_RX_STATS_CMDID: | ||
81 | return "WMI_RX_STATS_CMDID"; | ||
88 | case WMI_AGGR_LIMIT_CMD: | 82 | case WMI_AGGR_LIMIT_CMD: |
89 | return "WMI_AGGR_LIMIT_CMD"; | 83 | return "WMI_AGGR_LIMIT_CMD"; |
90 | } | 84 | } |
@@ -102,9 +96,15 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) | |||
102 | 96 | ||
103 | wmi->drv_priv = priv; | 97 | wmi->drv_priv = priv; |
104 | wmi->stopped = false; | 98 | wmi->stopped = false; |
99 | skb_queue_head_init(&wmi->wmi_event_queue); | ||
100 | spin_lock_init(&wmi->wmi_lock); | ||
101 | spin_lock_init(&wmi->event_lock); | ||
105 | mutex_init(&wmi->op_mutex); | 102 | mutex_init(&wmi->op_mutex); |
106 | mutex_init(&wmi->multi_write_mutex); | 103 | mutex_init(&wmi->multi_write_mutex); |
107 | init_completion(&wmi->cmd_wait); | 104 | init_completion(&wmi->cmd_wait); |
105 | INIT_LIST_HEAD(&wmi->pending_tx_events); | ||
106 | tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, | ||
107 | (unsigned long)wmi); | ||
108 | 108 | ||
109 | return wmi; | 109 | return wmi; |
110 | } | 110 | } |
@@ -120,11 +120,65 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) | |||
120 | kfree(priv->wmi); | 120 | kfree(priv->wmi); |
121 | } | 121 | } |
122 | 122 | ||
123 | void ath9k_swba_tasklet(unsigned long data) | 123 | void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv) |
124 | { | 124 | { |
125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 125 | unsigned long flags; |
126 | 126 | ||
127 | ath9k_htc_swba(priv, priv->wmi->beacon_pending); | 127 | tasklet_kill(&priv->wmi->wmi_event_tasklet); |
128 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); | ||
129 | __skb_queue_purge(&priv->wmi->wmi_event_queue); | ||
130 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); | ||
131 | } | ||
132 | |||
133 | void ath9k_wmi_event_tasklet(unsigned long data) | ||
134 | { | ||
135 | struct wmi *wmi = (struct wmi *)data; | ||
136 | struct ath9k_htc_priv *priv = wmi->drv_priv; | ||
137 | struct wmi_cmd_hdr *hdr; | ||
138 | void *wmi_event; | ||
139 | struct wmi_event_swba *swba; | ||
140 | struct sk_buff *skb = NULL; | ||
141 | unsigned long flags; | ||
142 | u16 cmd_id; | ||
143 | |||
144 | do { | ||
145 | spin_lock_irqsave(&wmi->wmi_lock, flags); | ||
146 | skb = __skb_dequeue(&wmi->wmi_event_queue); | ||
147 | if (!skb) { | ||
148 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); | ||
149 | return; | ||
150 | } | ||
151 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); | ||
152 | |||
153 | hdr = (struct wmi_cmd_hdr *) skb->data; | ||
154 | cmd_id = be16_to_cpu(hdr->command_id); | ||
155 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
156 | |||
157 | switch (cmd_id) { | ||
158 | case WMI_SWBA_EVENTID: | ||
159 | swba = (struct wmi_event_swba *) wmi_event; | ||
160 | ath9k_htc_swba(priv, swba); | ||
161 | break; | ||
162 | case WMI_FATAL_EVENTID: | ||
163 | ieee80211_queue_work(wmi->drv_priv->hw, | ||
164 | &wmi->drv_priv->fatal_work); | ||
165 | break; | ||
166 | case WMI_TXSTATUS_EVENTID: | ||
167 | spin_lock_bh(&priv->tx.tx_lock); | ||
168 | if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { | ||
169 | spin_unlock_bh(&priv->tx.tx_lock); | ||
170 | break; | ||
171 | } | ||
172 | spin_unlock_bh(&priv->tx.tx_lock); | ||
173 | |||
174 | ath9k_htc_txstatus(priv, wmi_event); | ||
175 | break; | ||
176 | default: | ||
177 | break; | ||
178 | } | ||
179 | |||
180 | kfree_skb(skb); | ||
181 | } while (1); | ||
128 | } | 182 | } |
129 | 183 | ||
130 | void ath9k_fatal_work(struct work_struct *work) | 184 | void ath9k_fatal_work(struct work_struct *work) |
@@ -153,10 +207,6 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
153 | struct wmi *wmi = (struct wmi *) priv; | 207 | struct wmi *wmi = (struct wmi *) priv; |
154 | struct wmi_cmd_hdr *hdr; | 208 | struct wmi_cmd_hdr *hdr; |
155 | u16 cmd_id; | 209 | u16 cmd_id; |
156 | void *wmi_event; | ||
157 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
158 | __be32 txrate; | ||
159 | #endif | ||
160 | 210 | ||
161 | if (unlikely(wmi->stopped)) | 211 | if (unlikely(wmi->stopped)) |
162 | goto free_skb; | 212 | goto free_skb; |
@@ -165,26 +215,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
165 | cmd_id = be16_to_cpu(hdr->command_id); | 215 | cmd_id = be16_to_cpu(hdr->command_id); |
166 | 216 | ||
167 | if (cmd_id & 0x1000) { | 217 | if (cmd_id & 0x1000) { |
168 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | 218 | spin_lock(&wmi->wmi_lock); |
169 | switch (cmd_id) { | 219 | __skb_queue_tail(&wmi->wmi_event_queue, skb); |
170 | case WMI_SWBA_EVENTID: | 220 | spin_unlock(&wmi->wmi_lock); |
171 | wmi->beacon_pending = *(u8 *)wmi_event; | 221 | tasklet_schedule(&wmi->wmi_event_tasklet); |
172 | tasklet_schedule(&wmi->drv_priv->swba_tasklet); | ||
173 | break; | ||
174 | case WMI_FATAL_EVENTID: | ||
175 | ieee80211_queue_work(wmi->drv_priv->hw, | ||
176 | &wmi->drv_priv->fatal_work); | ||
177 | break; | ||
178 | case WMI_TXRATE_EVENTID: | ||
179 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
180 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
181 | wmi->drv_priv->debug.txrate = be32_to_cpu(txrate); | ||
182 | #endif | ||
183 | break; | ||
184 | default: | ||
185 | break; | ||
186 | } | ||
187 | kfree_skb(skb); | ||
188 | return; | 222 | return; |
189 | } | 223 | } |
190 | 224 | ||
@@ -243,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, | |||
243 | hdr->command_id = cpu_to_be16(cmd); | 277 | hdr->command_id = cpu_to_be16(cmd); |
244 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); | 278 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); |
245 | 279 | ||
246 | return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); | 280 | return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid); |
247 | } | 281 | } |
248 | 282 | ||
249 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | 283 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 42084277522d..02ecb9f06db0 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -17,7 +17,6 @@ | |||
17 | #ifndef WMI_H | 17 | #ifndef WMI_H |
18 | #define WMI_H | 18 | #define WMI_H |
19 | 19 | ||
20 | |||
21 | struct wmi_event_txrate { | 20 | struct wmi_event_txrate { |
22 | __be32 txrate; | 21 | __be32 txrate; |
23 | struct { | 22 | struct { |
@@ -31,18 +30,65 @@ struct wmi_cmd_hdr { | |||
31 | __be16 seq_no; | 30 | __be16 seq_no; |
32 | } __packed; | 31 | } __packed; |
33 | 32 | ||
33 | struct wmi_fw_version { | ||
34 | __be16 major; | ||
35 | __be16 minor; | ||
36 | |||
37 | } __packed; | ||
38 | |||
39 | struct wmi_event_swba { | ||
40 | __be64 tsf; | ||
41 | u8 beacon_pending; | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * 64 - HTC header - WMI header - 1 / txstatus | ||
46 | * And some other hdr. space is also accounted for. | ||
47 | * 12 seems to be the magic number. | ||
48 | */ | ||
49 | #define HTC_MAX_TX_STATUS 12 | ||
50 | |||
51 | #define ATH9K_HTC_TXSTAT_ACK BIT(0) | ||
52 | #define ATH9K_HTC_TXSTAT_FILT BIT(1) | ||
53 | #define ATH9K_HTC_TXSTAT_RTC_CTS BIT(2) | ||
54 | #define ATH9K_HTC_TXSTAT_MCS BIT(3) | ||
55 | #define ATH9K_HTC_TXSTAT_CW40 BIT(4) | ||
56 | #define ATH9K_HTC_TXSTAT_SGI BIT(5) | ||
57 | |||
58 | /* | ||
59 | * Legacy rates are indicated as indices. | ||
60 | * HT rates are indicated as dot11 numbers. | ||
61 | * This allows us to resrict the rate field | ||
62 | * to 4 bits. | ||
63 | */ | ||
64 | #define ATH9K_HTC_TXSTAT_RATE 0x0f | ||
65 | #define ATH9K_HTC_TXSTAT_RATE_S 0 | ||
66 | |||
67 | #define ATH9K_HTC_TXSTAT_EPID 0xf0 | ||
68 | #define ATH9K_HTC_TXSTAT_EPID_S 4 | ||
69 | |||
70 | struct __wmi_event_txstatus { | ||
71 | u8 cookie; | ||
72 | u8 ts_rate; /* Also holds EP ID */ | ||
73 | u8 ts_flags; | ||
74 | }; | ||
75 | |||
76 | struct wmi_event_txstatus { | ||
77 | u8 cnt; | ||
78 | struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; | ||
79 | } __packed; | ||
80 | |||
34 | enum wmi_cmd_id { | 81 | enum wmi_cmd_id { |
35 | WMI_ECHO_CMDID = 0x0001, | 82 | WMI_ECHO_CMDID = 0x0001, |
36 | WMI_ACCESS_MEMORY_CMDID, | 83 | WMI_ACCESS_MEMORY_CMDID, |
37 | 84 | ||
38 | /* Commands to Target */ | 85 | /* Commands to Target */ |
86 | WMI_GET_FW_VERSION, | ||
39 | WMI_DISABLE_INTR_CMDID, | 87 | WMI_DISABLE_INTR_CMDID, |
40 | WMI_ENABLE_INTR_CMDID, | 88 | WMI_ENABLE_INTR_CMDID, |
41 | WMI_RX_LINK_CMDID, | ||
42 | WMI_ATH_INIT_CMDID, | 89 | WMI_ATH_INIT_CMDID, |
43 | WMI_ABORT_TXQ_CMDID, | 90 | WMI_ABORT_TXQ_CMDID, |
44 | WMI_STOP_TX_DMA_CMDID, | 91 | WMI_STOP_TX_DMA_CMDID, |
45 | WMI_STOP_DMA_RECV_CMDID, | ||
46 | WMI_ABORT_TX_DMA_CMDID, | 92 | WMI_ABORT_TX_DMA_CMDID, |
47 | WMI_DRAIN_TXQ_CMDID, | 93 | WMI_DRAIN_TXQ_CMDID, |
48 | WMI_DRAIN_TXQ_ALL_CMDID, | 94 | WMI_DRAIN_TXQ_ALL_CMDID, |
@@ -50,23 +96,21 @@ enum wmi_cmd_id { | |||
50 | WMI_STOP_RECV_CMDID, | 96 | WMI_STOP_RECV_CMDID, |
51 | WMI_FLUSH_RECV_CMDID, | 97 | WMI_FLUSH_RECV_CMDID, |
52 | WMI_SET_MODE_CMDID, | 98 | WMI_SET_MODE_CMDID, |
53 | WMI_RESET_CMDID, | ||
54 | WMI_NODE_CREATE_CMDID, | 99 | WMI_NODE_CREATE_CMDID, |
55 | WMI_NODE_REMOVE_CMDID, | 100 | WMI_NODE_REMOVE_CMDID, |
56 | WMI_VAP_REMOVE_CMDID, | 101 | WMI_VAP_REMOVE_CMDID, |
57 | WMI_VAP_CREATE_CMDID, | 102 | WMI_VAP_CREATE_CMDID, |
58 | WMI_BEACON_UPDATE_CMDID, | ||
59 | WMI_REG_READ_CMDID, | 103 | WMI_REG_READ_CMDID, |
60 | WMI_REG_WRITE_CMDID, | 104 | WMI_REG_WRITE_CMDID, |
61 | WMI_RC_STATE_CHANGE_CMDID, | 105 | WMI_RC_STATE_CHANGE_CMDID, |
62 | WMI_RC_RATE_UPDATE_CMDID, | 106 | WMI_RC_RATE_UPDATE_CMDID, |
63 | WMI_DEBUG_INFO_CMDID, | ||
64 | WMI_HOST_ATTACH, | ||
65 | WMI_TARGET_IC_UPDATE_CMDID, | 107 | WMI_TARGET_IC_UPDATE_CMDID, |
66 | WMI_TGT_STATS_CMDID, | ||
67 | WMI_TX_AGGR_ENABLE_CMDID, | 108 | WMI_TX_AGGR_ENABLE_CMDID, |
68 | WMI_TGT_DETACH_CMDID, | 109 | WMI_TGT_DETACH_CMDID, |
69 | WMI_TGT_TXQ_ENABLE_CMDID, | 110 | WMI_NODE_UPDATE_CMDID, |
111 | WMI_INT_STATS_CMDID, | ||
112 | WMI_TX_STATS_CMDID, | ||
113 | WMI_RX_STATS_CMDID, | ||
70 | WMI_AGGR_LIMIT_CMD = 0x0026, | 114 | WMI_AGGR_LIMIT_CMD = 0x0026, |
71 | }; | 115 | }; |
72 | 116 | ||
@@ -76,9 +120,8 @@ enum wmi_event_id { | |||
76 | WMI_FATAL_EVENTID, | 120 | WMI_FATAL_EVENTID, |
77 | WMI_TXTO_EVENTID, | 121 | WMI_TXTO_EVENTID, |
78 | WMI_BMISS_EVENTID, | 122 | WMI_BMISS_EVENTID, |
79 | WMI_WLAN_TXCOMP_EVENTID, | ||
80 | WMI_DELBA_EVENTID, | 123 | WMI_DELBA_EVENTID, |
81 | WMI_TXRATE_EVENTID, | 124 | WMI_TXSTATUS_EVENTID, |
82 | }; | 125 | }; |
83 | 126 | ||
84 | #define MAX_CMD_NUMBER 62 | 127 | #define MAX_CMD_NUMBER 62 |
@@ -88,6 +131,12 @@ struct register_write { | |||
88 | __be32 val; | 131 | __be32 val; |
89 | }; | 132 | }; |
90 | 133 | ||
134 | struct ath9k_htc_tx_event { | ||
135 | int count; | ||
136 | struct __wmi_event_txstatus txs; | ||
137 | struct list_head list; | ||
138 | }; | ||
139 | |||
91 | struct wmi { | 140 | struct wmi { |
92 | struct ath9k_htc_priv *drv_priv; | 141 | struct ath9k_htc_priv *drv_priv; |
93 | struct htc_target *htc; | 142 | struct htc_target *htc; |
@@ -95,12 +144,16 @@ struct wmi { | |||
95 | struct mutex op_mutex; | 144 | struct mutex op_mutex; |
96 | struct completion cmd_wait; | 145 | struct completion cmd_wait; |
97 | enum wmi_cmd_id last_cmd_id; | 146 | enum wmi_cmd_id last_cmd_id; |
147 | struct sk_buff_head wmi_event_queue; | ||
148 | struct tasklet_struct wmi_event_tasklet; | ||
98 | u16 tx_seq_id; | 149 | u16 tx_seq_id; |
99 | u8 *cmd_rsp_buf; | 150 | u8 *cmd_rsp_buf; |
100 | u32 cmd_rsp_len; | 151 | u32 cmd_rsp_len; |
101 | bool stopped; | 152 | bool stopped; |
102 | 153 | ||
103 | u8 beacon_pending; | 154 | struct list_head pending_tx_events; |
155 | spinlock_t event_lock; | ||
156 | |||
104 | spinlock_t wmi_lock; | 157 | spinlock_t wmi_lock; |
105 | 158 | ||
106 | atomic_t mwrite_cnt; | 159 | atomic_t mwrite_cnt; |
@@ -117,8 +170,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
117 | u8 *cmd_buf, u32 cmd_len, | 170 | u8 *cmd_buf, u32 cmd_len, |
118 | u8 *rsp_buf, u32 rsp_len, | 171 | u8 *rsp_buf, u32 rsp_len, |
119 | u32 timeout); | 172 | u32 timeout); |
120 | void ath9k_swba_tasklet(unsigned long data); | 173 | void ath9k_wmi_event_tasklet(unsigned long data); |
121 | void ath9k_fatal_work(struct work_struct *work); | 174 | void ath9k_fatal_work(struct work_struct *work); |
175 | void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); | ||
122 | 176 | ||
123 | #define WMI_CMD(_wmi_cmd) \ | 177 | #define WMI_CMD(_wmi_cmd) \ |
124 | do { \ | 178 | do { \ |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3cea3f76e373..e9e99f730ca8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
357 | struct ath_frame_info *fi; | 357 | struct ath_frame_info *fi; |
358 | int nframes; | 358 | int nframes; |
359 | u8 tidno; | 359 | u8 tidno; |
360 | bool clear_filter; | ||
360 | 361 | ||
361 | skb = bf->bf_mpdu; | 362 | skb = bf->bf_mpdu; |
362 | hdr = (struct ieee80211_hdr *)skb->data; | 363 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
441 | /* transmit completion */ | 442 | /* transmit completion */ |
442 | acked_cnt++; | 443 | acked_cnt++; |
443 | } else { | 444 | } else { |
444 | if (!(tid->state & AGGR_CLEANUP) && retry) { | 445 | if ((tid->state & AGGR_CLEANUP) || !retry) { |
445 | if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
446 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
447 | txpending = 1; | ||
448 | } else { | ||
449 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
450 | txfail = 1; | ||
451 | sendbar = 1; | ||
452 | txfail_cnt++; | ||
453 | } | ||
454 | } else { | ||
455 | /* | 446 | /* |
456 | * cleanup in progress, just fail | 447 | * cleanup in progress, just fail |
457 | * the un-acked sub-frames | 448 | * the un-acked sub-frames |
458 | */ | 449 | */ |
459 | txfail = 1; | 450 | txfail = 1; |
451 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
452 | if (!(ts->ts_status & ATH9K_TXERR_FILT) || | ||
453 | !an->sleeping) | ||
454 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
455 | |||
456 | clear_filter = true; | ||
457 | txpending = 1; | ||
458 | } else { | ||
459 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
460 | txfail = 1; | ||
461 | sendbar = 1; | ||
462 | txfail_cnt++; | ||
460 | } | 463 | } |
461 | } | 464 | } |
462 | 465 | ||
@@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
496 | !txfail, sendbar); | 499 | !txfail, sendbar); |
497 | } else { | 500 | } else { |
498 | /* retry the un-acked ones */ | 501 | /* retry the un-acked ones */ |
502 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); | ||
499 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 503 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { |
500 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 504 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
501 | struct ath_buf *tbf; | 505 | struct ath_buf *tbf; |
@@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
546 | 550 | ||
547 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 551 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
548 | if (!list_empty(&bf_pending)) { | 552 | if (!list_empty(&bf_pending)) { |
553 | if (an->sleeping) | ||
554 | ieee80211_sta_set_tim(sta); | ||
555 | |||
549 | spin_lock_bh(&txq->axq_lock); | 556 | spin_lock_bh(&txq->axq_lock); |
557 | if (clear_filter) | ||
558 | tid->ac->clear_ps_filter = true; | ||
550 | list_splice(&bf_pending, &tid->buf_q); | 559 | list_splice(&bf_pending, &tid->buf_q); |
551 | ath_tx_queue_tid(txq, tid); | 560 | ath_tx_queue_tid(txq, tid); |
552 | spin_unlock_bh(&txq->axq_lock); | 561 | spin_unlock_bh(&txq->axq_lock); |
@@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
816 | bf = list_first_entry(&bf_q, struct ath_buf, list); | 825 | bf = list_first_entry(&bf_q, struct ath_buf, list); |
817 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); | 826 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); |
818 | 827 | ||
828 | if (tid->ac->clear_ps_filter) { | ||
829 | tid->ac->clear_ps_filter = false; | ||
830 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); | ||
831 | } | ||
832 | |||
819 | /* if only one frame, send as non-aggregate */ | 833 | /* if only one frame, send as non-aggregate */ |
820 | if (bf == bf->bf_lastbf) { | 834 | if (bf == bf->bf_lastbf) { |
821 | fi = get_frame_info(bf->bf_mpdu); | 835 | fi = get_frame_info(bf->bf_mpdu); |
@@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
896 | ath_tx_flush_tid(sc, txtid); | 910 | ath_tx_flush_tid(sc, txtid); |
897 | } | 911 | } |
898 | 912 | ||
913 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | ||
914 | { | ||
915 | struct ath_atx_tid *tid; | ||
916 | struct ath_atx_ac *ac; | ||
917 | struct ath_txq *txq; | ||
918 | bool buffered = false; | ||
919 | int tidno; | ||
920 | |||
921 | for (tidno = 0, tid = &an->tid[tidno]; | ||
922 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
923 | |||
924 | if (!tid->sched) | ||
925 | continue; | ||
926 | |||
927 | ac = tid->ac; | ||
928 | txq = ac->txq; | ||
929 | |||
930 | spin_lock_bh(&txq->axq_lock); | ||
931 | |||
932 | if (!list_empty(&tid->buf_q)) | ||
933 | buffered = true; | ||
934 | |||
935 | tid->sched = false; | ||
936 | list_del(&tid->list); | ||
937 | |||
938 | if (ac->sched) { | ||
939 | ac->sched = false; | ||
940 | list_del(&ac->list); | ||
941 | } | ||
942 | |||
943 | spin_unlock_bh(&txq->axq_lock); | ||
944 | } | ||
945 | |||
946 | return buffered; | ||
947 | } | ||
948 | |||
949 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | ||
950 | { | ||
951 | struct ath_atx_tid *tid; | ||
952 | struct ath_atx_ac *ac; | ||
953 | struct ath_txq *txq; | ||
954 | int tidno; | ||
955 | |||
956 | for (tidno = 0, tid = &an->tid[tidno]; | ||
957 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
958 | |||
959 | ac = tid->ac; | ||
960 | txq = ac->txq; | ||
961 | |||
962 | spin_lock_bh(&txq->axq_lock); | ||
963 | ac->clear_ps_filter = true; | ||
964 | |||
965 | if (!list_empty(&tid->buf_q) && !tid->paused) { | ||
966 | ath_tx_queue_tid(txq, tid); | ||
967 | ath_txq_schedule(sc, txq); | ||
968 | } | ||
969 | |||
970 | spin_unlock_bh(&txq->axq_lock); | ||
971 | } | ||
972 | } | ||
973 | |||
899 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 974 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
900 | { | 975 | { |
901 | struct ath_atx_tid *txtid; | 976 | struct ath_atx_tid *txtid; |
@@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1451 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | 1526 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
1452 | struct ieee80211_hdr *hdr; | 1527 | struct ieee80211_hdr *hdr; |
1453 | struct ath_frame_info *fi = get_frame_info(skb); | 1528 | struct ath_frame_info *fi = get_frame_info(skb); |
1454 | struct ath_node *an; | 1529 | struct ath_node *an = NULL; |
1455 | struct ath_atx_tid *tid; | 1530 | struct ath_atx_tid *tid; |
1456 | enum ath9k_key_type keytype; | 1531 | enum ath9k_key_type keytype; |
1457 | u16 seqno = 0; | 1532 | u16 seqno = 0; |
@@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1459 | 1534 | ||
1460 | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); | 1535 | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
1461 | 1536 | ||
1537 | if (sta) | ||
1538 | an = (struct ath_node *) sta->drv_priv; | ||
1539 | |||
1462 | hdr = (struct ieee80211_hdr *)skb->data; | 1540 | hdr = (struct ieee80211_hdr *)skb->data; |
1463 | if (sta && ieee80211_is_data_qos(hdr->frame_control) && | 1541 | if (an && ieee80211_is_data_qos(hdr->frame_control) && |
1464 | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { | 1542 | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { |
1465 | 1543 | ||
1466 | an = (struct ath_node *) sta->drv_priv; | ||
1467 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 1544 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
1468 | 1545 | ||
1469 | /* | 1546 | /* |
@@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1479 | memset(fi, 0, sizeof(*fi)); | 1556 | memset(fi, 0, sizeof(*fi)); |
1480 | if (hw_key) | 1557 | if (hw_key) |
1481 | fi->keyix = hw_key->hw_key_idx; | 1558 | fi->keyix = hw_key->hw_key_idx; |
1559 | else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) | ||
1560 | fi->keyix = an->ps_key; | ||
1482 | else | 1561 | else |
1483 | fi->keyix = ATH9K_TXKEYIX_INVALID; | 1562 | fi->keyix = ATH9K_TXKEYIX_INVALID; |
1484 | fi->keytype = keytype; | 1563 | fi->keytype = keytype; |
@@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb) | |||
1491 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1570 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1492 | int flags = 0; | 1571 | int flags = 0; |
1493 | 1572 | ||
1494 | flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ | ||
1495 | flags |= ATH9K_TXDESC_INTREQ; | 1573 | flags |= ATH9K_TXDESC_INTREQ; |
1496 | 1574 | ||
1497 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) | 1575 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
@@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1754 | if (txctl->paprd) | 1832 | if (txctl->paprd) |
1755 | bf->bf_state.bfs_paprd_timestamp = jiffies; | 1833 | bf->bf_state.bfs_paprd_timestamp = jiffies; |
1756 | 1834 | ||
1835 | if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) | ||
1836 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); | ||
1837 | |||
1757 | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); | 1838 | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); |
1758 | } | 1839 | } |
1759 | 1840 | ||
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 0d4f39cbdcab..a61ef3d6d89c 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c | |||
@@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *common, | |||
483 | memset(&hk, 0, sizeof(hk)); | 483 | memset(&hk, 0, sizeof(hk)); |
484 | 484 | ||
485 | switch (key->cipher) { | 485 | switch (key->cipher) { |
486 | case 0: | ||
487 | hk.kv_type = ATH_CIPHER_CLR; | ||
488 | break; | ||
486 | case WLAN_CIPHER_SUITE_WEP40: | 489 | case WLAN_CIPHER_SUITE_WEP40: |
487 | case WLAN_CIPHER_SUITE_WEP104: | 490 | case WLAN_CIPHER_SUITE_WEP104: |
488 | hk.kv_type = ATH_CIPHER_WEP; | 491 | hk.kv_type = ATH_CIPHER_WEP; |
@@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *common, | |||
498 | } | 501 | } |
499 | 502 | ||
500 | hk.kv_len = key->keylen; | 503 | hk.kv_len = key->keylen; |
501 | memcpy(hk.kv_val, key->key, key->keylen); | 504 | if (key->keylen) |
505 | memcpy(hk.kv_val, key->key, key->keylen); | ||
502 | 506 | ||
503 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | 507 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
504 | switch (vif->type) { | 508 | switch (vif->type) { |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 0e1b8793c864..028310f263c8 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -97,8 +97,8 @@ static const struct ieee80211_regdomain ath_world_regdom_66_69 = { | |||
97 | } | 97 | } |
98 | }; | 98 | }; |
99 | 99 | ||
100 | /* Can be used by 0x67, 0x6A and 0x68 */ | 100 | /* Can be used by 0x67, 0x68, 0x6A and 0x6C */ |
101 | static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { | 101 | static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { |
102 | .n_reg_rules = 4, | 102 | .n_reg_rules = 4, |
103 | .alpha2 = "99", | 103 | .alpha2 = "99", |
104 | .reg_rules = { | 104 | .reg_rules = { |
@@ -151,7 +151,8 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) | |||
151 | case 0x67: | 151 | case 0x67: |
152 | case 0x68: | 152 | case 0x68: |
153 | case 0x6A: | 153 | case 0x6A: |
154 | return &ath_world_regdom_67_68_6A; | 154 | case 0x6C: |
155 | return &ath_world_regdom_67_68_6A_6C; | ||
155 | default: | 156 | default: |
156 | WARN_ON(1); | 157 | WARN_ON(1); |
157 | return ath_default_world_regdomain(); | 158 | return ath_default_world_regdomain(); |
@@ -333,6 +334,7 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy, | |||
333 | case 0x63: | 334 | case 0x63: |
334 | case 0x66: | 335 | case 0x66: |
335 | case 0x67: | 336 | case 0x67: |
337 | case 0x6C: | ||
336 | ath_reg_apply_beaconing_flags(wiphy, initiator); | 338 | ath_reg_apply_beaconing_flags(wiphy, initiator); |
337 | break; | 339 | break; |
338 | case 0x68: | 340 | case 0x68: |
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 5c2cfe694152..24b53839fc3a 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h | |||
@@ -86,6 +86,7 @@ enum EnumRd { | |||
86 | WOR9_WORLD = 0x69, | 86 | WOR9_WORLD = 0x69, |
87 | WORA_WORLD = 0x6A, | 87 | WORA_WORLD = 0x6A, |
88 | WORB_WORLD = 0x6B, | 88 | WORB_WORLD = 0x6B, |
89 | WORC_WORLD = 0x6C, | ||
89 | 90 | ||
90 | MKK3_MKKB = 0x80, | 91 | MKK3_MKKB = 0x80, |
91 | MKK3_MKKA2 = 0x81, | 92 | MKK3_MKKA2 = 0x81, |
@@ -282,6 +283,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { | |||
282 | {WOR9_WORLD, NO_CTL, NO_CTL}, | 283 | {WOR9_WORLD, NO_CTL, NO_CTL}, |
283 | {WORA_WORLD, NO_CTL, NO_CTL}, | 284 | {WORA_WORLD, NO_CTL, NO_CTL}, |
284 | {WORB_WORLD, NO_CTL, NO_CTL}, | 285 | {WORB_WORLD, NO_CTL, NO_CTL}, |
286 | {WORC_WORLD, NO_CTL, NO_CTL}, | ||
285 | }; | 287 | }; |
286 | 288 | ||
287 | static struct country_code_to_enum_rd allCountries[] = { | 289 | static struct country_code_to_enum_rd allCountries[] = { |