diff options
author | David S. Miller <davem@davemloft.net> | 2009-02-03 15:41:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-03 15:41:58 -0500 |
commit | 1725d409caba16ea5fc694bd50e95e79e8ced11a (patch) | |
tree | 688fe26dd4ceda5364692f0ce307aadb6f04f331 /drivers/net/wireless/ath5k | |
parent | b3ff29d2ccfe3af065a9b393699a8fbf2abd1b15 (diff) | |
parent | b8abde45d7d6ab9e8ceced9b5990eeb1149d0b97 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/ath5k')
-rw-r--r-- | drivers/net/wireless/ath5k/ath5k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 174 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/caps.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/debug.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/debug.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/eeprom.c | 150 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/gpio.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/pcu.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/qcu.c | 47 |
10 files changed, 298 insertions, 159 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 183ffc8e62ca..0eda785fe62f 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -1206,6 +1206,7 @@ extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | |||
1206 | /* Beacon control functions */ | 1206 | /* Beacon control functions */ |
1207 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); | 1207 | extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); |
1208 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1208 | extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1209 | extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | ||
1209 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1210 | extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1210 | extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | 1211 | extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); |
1211 | #if 0 | 1212 | #if 0 |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index a533ed60bb4d..bd2c580d1f19 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -232,13 +232,14 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
232 | int mc_count, struct dev_mc_list *mclist); | 232 | int mc_count, struct dev_mc_list *mclist); |
233 | static int ath5k_set_key(struct ieee80211_hw *hw, | 233 | static int ath5k_set_key(struct ieee80211_hw *hw, |
234 | enum set_key_cmd cmd, | 234 | enum set_key_cmd cmd, |
235 | const u8 *local_addr, const u8 *addr, | 235 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
236 | struct ieee80211_key_conf *key); | 236 | struct ieee80211_key_conf *key); |
237 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 237 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
238 | struct ieee80211_low_level_stats *stats); | 238 | struct ieee80211_low_level_stats *stats); |
239 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | 239 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, |
240 | struct ieee80211_tx_queue_stats *stats); | 240 | struct ieee80211_tx_queue_stats *stats); |
241 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 241 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
242 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | ||
242 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 243 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
243 | static int ath5k_beacon_update(struct ath5k_softc *sc, | 244 | static int ath5k_beacon_update(struct ath5k_softc *sc, |
244 | struct sk_buff *skb); | 245 | struct sk_buff *skb); |
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = { | |||
261 | .conf_tx = NULL, | 262 | .conf_tx = NULL, |
262 | .get_tx_stats = ath5k_get_tx_stats, | 263 | .get_tx_stats = ath5k_get_tx_stats, |
263 | .get_tsf = ath5k_get_tsf, | 264 | .get_tsf = ath5k_get_tsf, |
265 | .set_tsf = ath5k_set_tsf, | ||
264 | .reset_tsf = ath5k_reset_tsf, | 266 | .reset_tsf = ath5k_reset_tsf, |
265 | .bss_info_changed = ath5k_bss_info_changed, | 267 | .bss_info_changed = ath5k_bss_info_changed, |
266 | }; | 268 | }; |
@@ -347,9 +349,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | |||
347 | } | 349 | } |
348 | 350 | ||
349 | /* Interrupt handling */ | 351 | /* Interrupt handling */ |
350 | static int ath5k_init(struct ath5k_softc *sc, bool is_resume); | 352 | static int ath5k_init(struct ath5k_softc *sc); |
351 | static int ath5k_stop_locked(struct ath5k_softc *sc); | 353 | static int ath5k_stop_locked(struct ath5k_softc *sc); |
352 | static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend); | 354 | static int ath5k_stop_hw(struct ath5k_softc *sc); |
353 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | 355 | static irqreturn_t ath5k_intr(int irq, void *dev_id); |
354 | static void ath5k_tasklet_reset(unsigned long data); | 356 | static void ath5k_tasklet_reset(unsigned long data); |
355 | 357 | ||
@@ -653,8 +655,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
653 | 655 | ||
654 | ath5k_led_off(sc); | 656 | ath5k_led_off(sc); |
655 | 657 | ||
656 | ath5k_stop_hw(sc, true); | ||
657 | |||
658 | free_irq(pdev->irq, sc); | 658 | free_irq(pdev->irq, sc); |
659 | pci_save_state(pdev); | 659 | pci_save_state(pdev); |
660 | pci_disable_device(pdev); | 660 | pci_disable_device(pdev); |
@@ -689,14 +689,9 @@ ath5k_pci_resume(struct pci_dev *pdev) | |||
689 | goto err_no_irq; | 689 | goto err_no_irq; |
690 | } | 690 | } |
691 | 691 | ||
692 | err = ath5k_init(sc, true); | ||
693 | if (err) | ||
694 | goto err_irq; | ||
695 | ath5k_led_enable(sc); | 692 | ath5k_led_enable(sc); |
696 | |||
697 | return 0; | 693 | return 0; |
698 | err_irq: | 694 | |
699 | free_irq(pdev->irq, sc); | ||
700 | err_no_irq: | 695 | err_no_irq: |
701 | pci_disable_device(pdev); | 696 | pci_disable_device(pdev); |
702 | return err; | 697 | return err; |
@@ -1098,6 +1093,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1098 | * Buffers setup * | 1093 | * Buffers setup * |
1099 | \***************/ | 1094 | \***************/ |
1100 | 1095 | ||
1096 | static | ||
1097 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | ||
1098 | { | ||
1099 | struct sk_buff *skb; | ||
1100 | unsigned int off; | ||
1101 | |||
1102 | /* | ||
1103 | * Allocate buffer with headroom_needed space for the | ||
1104 | * fake physical layer header at the start. | ||
1105 | */ | ||
1106 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | ||
1107 | |||
1108 | if (!skb) { | ||
1109 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | ||
1110 | sc->rxbufsize + sc->cachelsz - 1); | ||
1111 | return NULL; | ||
1112 | } | ||
1113 | /* | ||
1114 | * Cache-line-align. This is important (for the | ||
1115 | * 5210 at least) as not doing so causes bogus data | ||
1116 | * in rx'd frames. | ||
1117 | */ | ||
1118 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1119 | if (off != 0) | ||
1120 | skb_reserve(skb, sc->cachelsz - off); | ||
1121 | |||
1122 | *skb_addr = pci_map_single(sc->pdev, | ||
1123 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | ||
1124 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { | ||
1125 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | ||
1126 | dev_kfree_skb(skb); | ||
1127 | return NULL; | ||
1128 | } | ||
1129 | return skb; | ||
1130 | } | ||
1131 | |||
1101 | static int | 1132 | static int |
1102 | ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | 1133 | ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) |
1103 | { | 1134 | { |
@@ -1105,37 +1136,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1105 | struct sk_buff *skb = bf->skb; | 1136 | struct sk_buff *skb = bf->skb; |
1106 | struct ath5k_desc *ds; | 1137 | struct ath5k_desc *ds; |
1107 | 1138 | ||
1108 | if (likely(skb == NULL)) { | 1139 | if (!skb) { |
1109 | unsigned int off; | 1140 | skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); |
1110 | 1141 | if (!skb) | |
1111 | /* | ||
1112 | * Allocate buffer with headroom_needed space for the | ||
1113 | * fake physical layer header at the start. | ||
1114 | */ | ||
1115 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | ||
1116 | if (unlikely(skb == NULL)) { | ||
1117 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | ||
1118 | sc->rxbufsize + sc->cachelsz - 1); | ||
1119 | return -ENOMEM; | 1142 | return -ENOMEM; |
1120 | } | ||
1121 | /* | ||
1122 | * Cache-line-align. This is important (for the | ||
1123 | * 5210 at least) as not doing so causes bogus data | ||
1124 | * in rx'd frames. | ||
1125 | */ | ||
1126 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1127 | if (off != 0) | ||
1128 | skb_reserve(skb, sc->cachelsz - off); | ||
1129 | |||
1130 | bf->skb = skb; | 1143 | bf->skb = skb; |
1131 | bf->skbaddr = pci_map_single(sc->pdev, | ||
1132 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | ||
1133 | if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) { | ||
1134 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | ||
1135 | dev_kfree_skb(skb); | ||
1136 | bf->skb = NULL; | ||
1137 | return -ENOMEM; | ||
1138 | } | ||
1139 | } | 1144 | } |
1140 | 1145 | ||
1141 | /* | 1146 | /* |
@@ -1178,6 +1183,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1178 | struct ieee80211_rate *rate; | 1183 | struct ieee80211_rate *rate; |
1179 | unsigned int mrr_rate[3], mrr_tries[3]; | 1184 | unsigned int mrr_rate[3], mrr_tries[3]; |
1180 | int i, ret; | 1185 | int i, ret; |
1186 | u16 hw_rate; | ||
1187 | u16 cts_rate = 0; | ||
1188 | u16 duration = 0; | ||
1189 | u8 rc_flags; | ||
1181 | 1190 | ||
1182 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; | 1191 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; |
1183 | 1192 | ||
@@ -1185,11 +1194,30 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1185 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 1194 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
1186 | PCI_DMA_TODEVICE); | 1195 | PCI_DMA_TODEVICE); |
1187 | 1196 | ||
1197 | rate = ieee80211_get_tx_rate(sc->hw, info); | ||
1198 | |||
1188 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | 1199 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
1189 | flags |= AR5K_TXDESC_NOACK; | 1200 | flags |= AR5K_TXDESC_NOACK; |
1190 | 1201 | ||
1202 | rc_flags = info->control.rates[0].flags; | ||
1203 | hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? | ||
1204 | rate->hw_value_short : rate->hw_value; | ||
1205 | |||
1191 | pktlen = skb->len; | 1206 | pktlen = skb->len; |
1192 | 1207 | ||
1208 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
1209 | flags |= AR5K_TXDESC_RTSENA; | ||
1210 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | ||
1211 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, | ||
1212 | sc->vif, pktlen, info)); | ||
1213 | } | ||
1214 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
1215 | flags |= AR5K_TXDESC_CTSENA; | ||
1216 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | ||
1217 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, | ||
1218 | sc->vif, pktlen, info)); | ||
1219 | } | ||
1220 | |||
1193 | if (info->control.hw_key) { | 1221 | if (info->control.hw_key) { |
1194 | keyidx = info->control.hw_key->hw_key_idx; | 1222 | keyidx = info->control.hw_key->hw_key_idx; |
1195 | pktlen += info->control.hw_key->icv_len; | 1223 | pktlen += info->control.hw_key->icv_len; |
@@ -1197,8 +1225,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1197 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1225 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1198 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1226 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, |
1199 | (sc->power_level * 2), | 1227 | (sc->power_level * 2), |
1200 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 1228 | hw_rate, |
1201 | info->control.rates[0].count, keyidx, 0, flags, 0, 0); | 1229 | info->control.rates[0].count, keyidx, 0, flags, |
1230 | cts_rate, duration); | ||
1202 | if (ret) | 1231 | if (ret) |
1203 | goto err_unmap; | 1232 | goto err_unmap; |
1204 | 1233 | ||
@@ -1664,7 +1693,8 @@ ath5k_tasklet_rx(unsigned long data) | |||
1664 | { | 1693 | { |
1665 | struct ieee80211_rx_status rxs = {}; | 1694 | struct ieee80211_rx_status rxs = {}; |
1666 | struct ath5k_rx_status rs = {}; | 1695 | struct ath5k_rx_status rs = {}; |
1667 | struct sk_buff *skb; | 1696 | struct sk_buff *skb, *next_skb; |
1697 | dma_addr_t next_skb_addr; | ||
1668 | struct ath5k_softc *sc = (void *)data; | 1698 | struct ath5k_softc *sc = (void *)data; |
1669 | struct ath5k_buf *bf, *bf_last; | 1699 | struct ath5k_buf *bf, *bf_last; |
1670 | struct ath5k_desc *ds; | 1700 | struct ath5k_desc *ds; |
@@ -1749,10 +1779,17 @@ ath5k_tasklet_rx(unsigned long data) | |||
1749 | goto next; | 1779 | goto next; |
1750 | } | 1780 | } |
1751 | accept: | 1781 | accept: |
1782 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | ||
1783 | |||
1784 | /* | ||
1785 | * If we can't replace bf->skb with a new skb under memory | ||
1786 | * pressure, just skip this packet | ||
1787 | */ | ||
1788 | if (!next_skb) | ||
1789 | goto next; | ||
1790 | |||
1752 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 1791 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, |
1753 | PCI_DMA_FROMDEVICE); | 1792 | PCI_DMA_FROMDEVICE); |
1754 | bf->skb = NULL; | ||
1755 | |||
1756 | skb_put(skb, rs.rs_datalen); | 1793 | skb_put(skb, rs.rs_datalen); |
1757 | 1794 | ||
1758 | /* The MAC header is padded to have 32-bit boundary if the | 1795 | /* The MAC header is padded to have 32-bit boundary if the |
@@ -1825,6 +1862,9 @@ accept: | |||
1825 | ath5k_check_ibss_tsf(sc, skb, &rxs); | 1862 | ath5k_check_ibss_tsf(sc, skb, &rxs); |
1826 | 1863 | ||
1827 | __ieee80211_rx(sc->hw, skb, &rxs); | 1864 | __ieee80211_rx(sc->hw, skb, &rxs); |
1865 | |||
1866 | bf->skb = next_skb; | ||
1867 | bf->skbaddr = next_skb_addr; | ||
1828 | next: | 1868 | next: |
1829 | list_move_tail(&bf->list, &sc->rxbuf); | 1869 | list_move_tail(&bf->list, &sc->rxbuf); |
1830 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1870 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
@@ -2207,18 +2247,13 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2207 | \********************/ | 2247 | \********************/ |
2208 | 2248 | ||
2209 | static int | 2249 | static int |
2210 | ath5k_init(struct ath5k_softc *sc, bool is_resume) | 2250 | ath5k_init(struct ath5k_softc *sc) |
2211 | { | 2251 | { |
2212 | struct ath5k_hw *ah = sc->ah; | 2252 | struct ath5k_hw *ah = sc->ah; |
2213 | int ret, i; | 2253 | int ret, i; |
2214 | 2254 | ||
2215 | mutex_lock(&sc->lock); | 2255 | mutex_lock(&sc->lock); |
2216 | 2256 | ||
2217 | if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status)) | ||
2218 | goto out_ok; | ||
2219 | |||
2220 | __clear_bit(ATH_STAT_STARTED, sc->status); | ||
2221 | |||
2222 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | 2257 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); |
2223 | 2258 | ||
2224 | /* | 2259 | /* |
@@ -2250,15 +2285,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume) | |||
2250 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | 2285 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) |
2251 | ath5k_hw_reset_key(ah, i); | 2286 | ath5k_hw_reset_key(ah, i); |
2252 | 2287 | ||
2253 | __set_bit(ATH_STAT_STARTED, sc->status); | ||
2254 | |||
2255 | /* Set ack to be sent at low bit-rates */ | 2288 | /* Set ack to be sent at low bit-rates */ |
2256 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2289 | ath5k_hw_set_ack_bitrate_high(ah, false); |
2257 | 2290 | ||
2258 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | 2291 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + |
2259 | msecs_to_jiffies(ath5k_calinterval * 1000))); | 2292 | msecs_to_jiffies(ath5k_calinterval * 1000))); |
2260 | 2293 | ||
2261 | out_ok: | ||
2262 | ret = 0; | 2294 | ret = 0; |
2263 | done: | 2295 | done: |
2264 | mmiowb(); | 2296 | mmiowb(); |
@@ -2313,7 +2345,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) | |||
2313 | * stop is preempted). | 2345 | * stop is preempted). |
2314 | */ | 2346 | */ |
2315 | static int | 2347 | static int |
2316 | ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) | 2348 | ath5k_stop_hw(struct ath5k_softc *sc) |
2317 | { | 2349 | { |
2318 | int ret; | 2350 | int ret; |
2319 | 2351 | ||
@@ -2344,8 +2376,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) | |||
2344 | } | 2376 | } |
2345 | } | 2377 | } |
2346 | ath5k_txbuf_free(sc, sc->bbuf); | 2378 | ath5k_txbuf_free(sc, sc->bbuf); |
2347 | if (!is_suspend) | ||
2348 | __clear_bit(ATH_STAT_STARTED, sc->status); | ||
2349 | 2379 | ||
2350 | mmiowb(); | 2380 | mmiowb(); |
2351 | mutex_unlock(&sc->lock); | 2381 | mutex_unlock(&sc->lock); |
@@ -2598,6 +2628,17 @@ ath5k_init_leds(struct ath5k_softc *sc) | |||
2598 | sc->led_pin = 1; | 2628 | sc->led_pin = 1; |
2599 | sc->led_on = 1; /* active high */ | 2629 | sc->led_on = 1; /* active high */ |
2600 | } | 2630 | } |
2631 | /* | ||
2632 | * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and | ||
2633 | * in emachines notebooks with AMBIT subsystem. | ||
2634 | */ | ||
2635 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || | ||
2636 | pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { | ||
2637 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2638 | sc->led_pin = 3; | ||
2639 | sc->led_on = 0; /* active low */ | ||
2640 | } | ||
2641 | |||
2601 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | 2642 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) |
2602 | goto out; | 2643 | goto out; |
2603 | 2644 | ||
@@ -2745,12 +2786,12 @@ ath5k_reset_wake(struct ath5k_softc *sc) | |||
2745 | 2786 | ||
2746 | static int ath5k_start(struct ieee80211_hw *hw) | 2787 | static int ath5k_start(struct ieee80211_hw *hw) |
2747 | { | 2788 | { |
2748 | return ath5k_init(hw->priv, false); | 2789 | return ath5k_init(hw->priv); |
2749 | } | 2790 | } |
2750 | 2791 | ||
2751 | static void ath5k_stop(struct ieee80211_hw *hw) | 2792 | static void ath5k_stop(struct ieee80211_hw *hw) |
2752 | { | 2793 | { |
2753 | ath5k_stop_hw(hw->priv, false); | 2794 | ath5k_stop_hw(hw->priv); |
2754 | } | 2795 | } |
2755 | 2796 | ||
2756 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2797 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
@@ -2999,8 +3040,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2999 | 3040 | ||
3000 | static int | 3041 | static int |
3001 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 3042 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
3002 | const u8 *local_addr, const u8 *addr, | 3043 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
3003 | struct ieee80211_key_conf *key) | 3044 | struct ieee80211_key_conf *key) |
3004 | { | 3045 | { |
3005 | struct ath5k_softc *sc = hw->priv; | 3046 | struct ath5k_softc *sc = hw->priv; |
3006 | int ret = 0; | 3047 | int ret = 0; |
@@ -3023,7 +3064,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3023 | 3064 | ||
3024 | switch (cmd) { | 3065 | switch (cmd) { |
3025 | case SET_KEY: | 3066 | case SET_KEY: |
3026 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); | 3067 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, |
3068 | sta ? sta->addr : NULL); | ||
3027 | if (ret) { | 3069 | if (ret) { |
3028 | ATH5K_ERR(sc, "can't set the key\n"); | 3070 | ATH5K_ERR(sc, "can't set the key\n"); |
3029 | goto unlock; | 3071 | goto unlock; |
@@ -3083,6 +3125,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw) | |||
3083 | } | 3125 | } |
3084 | 3126 | ||
3085 | static void | 3127 | static void |
3128 | ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | ||
3129 | { | ||
3130 | struct ath5k_softc *sc = hw->priv; | ||
3131 | |||
3132 | ath5k_hw_set_tsf64(sc->ah, tsf); | ||
3133 | } | ||
3134 | |||
3135 | static void | ||
3086 | ath5k_reset_tsf(struct ieee80211_hw *hw) | 3136 | ath5k_reset_tsf(struct ieee80211_hw *hw) |
3087 | { | 3137 | { |
3088 | struct ath5k_softc *sc = hw->priv; | 3138 | struct ath5k_softc *sc = hw->priv; |
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index facc60ddada2..c0fb8b5c42fe 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h | |||
@@ -148,8 +148,7 @@ struct ath5k_softc { | |||
148 | u8 bssidmask[ETH_ALEN]; | 148 | u8 bssidmask[ETH_ALEN]; |
149 | 149 | ||
150 | unsigned int led_pin, /* GPIO pin for driving LED */ | 150 | unsigned int led_pin, /* GPIO pin for driving LED */ |
151 | led_on, /* pin setting for LED on */ | 151 | led_on; /* pin setting for LED on */ |
152 | led_off; /* off time for current blink */ | ||
153 | 152 | ||
154 | struct tasklet_struct restq; /* reset tasklet */ | 153 | struct tasklet_struct restq; /* reset tasklet */ |
155 | 154 | ||
diff --git a/drivers/net/wireless/ath5k/caps.c b/drivers/net/wireless/ath5k/caps.c index 150f5ed204a0..367a6c7d3cc7 100644 --- a/drivers/net/wireless/ath5k/caps.c +++ b/drivers/net/wireless/ath5k/caps.c | |||
@@ -85,7 +85,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
85 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | 85 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is |
86 | * connected */ | 86 | * connected */ |
87 | if (AR5K_EEPROM_HDR_11B(ee_header) || | 87 | if (AR5K_EEPROM_HDR_11B(ee_header) || |
88 | AR5K_EEPROM_HDR_11G(ee_header)) { | 88 | (AR5K_EEPROM_HDR_11G(ee_header) && |
89 | ah->ah_version != AR5K_AR5211)) { | ||
89 | /* 2312 */ | 90 | /* 2312 */ |
90 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; | 91 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; |
91 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | 92 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; |
@@ -94,7 +95,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
94 | __set_bit(AR5K_MODE_11B, | 95 | __set_bit(AR5K_MODE_11B, |
95 | ah->ah_capabilities.cap_mode); | 96 | ah->ah_capabilities.cap_mode); |
96 | 97 | ||
97 | if (AR5K_EEPROM_HDR_11G(ee_header)) | 98 | if (AR5K_EEPROM_HDR_11G(ee_header) && |
99 | ah->ah_version != AR5K_AR5211) | ||
98 | __set_bit(AR5K_MODE_11G, | 100 | __set_bit(AR5K_MODE_11G, |
99 | ah->ah_capabilities.cap_mode); | 101 | ah->ah_capabilities.cap_mode); |
100 | } | 102 | } |
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index d281b6e38629..413ed689cd5f 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -193,43 +193,6 @@ static const struct file_operations fops_registers = { | |||
193 | }; | 193 | }; |
194 | 194 | ||
195 | 195 | ||
196 | /* debugfs: TSF */ | ||
197 | |||
198 | static ssize_t read_file_tsf(struct file *file, char __user *user_buf, | ||
199 | size_t count, loff_t *ppos) | ||
200 | { | ||
201 | struct ath5k_softc *sc = file->private_data; | ||
202 | char buf[100]; | ||
203 | snprintf(buf, sizeof(buf), "0x%016llx\n", | ||
204 | (unsigned long long)ath5k_hw_get_tsf64(sc->ah)); | ||
205 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | ||
206 | } | ||
207 | |||
208 | static ssize_t write_file_tsf(struct file *file, | ||
209 | const char __user *userbuf, | ||
210 | size_t count, loff_t *ppos) | ||
211 | { | ||
212 | struct ath5k_softc *sc = file->private_data; | ||
213 | char buf[20]; | ||
214 | |||
215 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
216 | return -EFAULT; | ||
217 | |||
218 | if (strncmp(buf, "reset", 5) == 0) { | ||
219 | ath5k_hw_reset_tsf(sc->ah); | ||
220 | printk(KERN_INFO "debugfs reset TSF\n"); | ||
221 | } | ||
222 | return count; | ||
223 | } | ||
224 | |||
225 | static const struct file_operations fops_tsf = { | ||
226 | .read = read_file_tsf, | ||
227 | .write = write_file_tsf, | ||
228 | .open = ath5k_debugfs_open, | ||
229 | .owner = THIS_MODULE, | ||
230 | }; | ||
231 | |||
232 | |||
233 | /* debugfs: beacons */ | 196 | /* debugfs: beacons */ |
234 | 197 | ||
235 | static ssize_t read_file_beacon(struct file *file, char __user *user_buf, | 198 | static ssize_t read_file_beacon(struct file *file, char __user *user_buf, |
@@ -423,9 +386,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc) | |||
423 | sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, | 386 | sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, |
424 | sc->debug.debugfs_phydir, sc, &fops_registers); | 387 | sc->debug.debugfs_phydir, sc, &fops_registers); |
425 | 388 | ||
426 | sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO, | ||
427 | sc->debug.debugfs_phydir, sc, &fops_tsf); | ||
428 | |||
429 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, | 389 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, |
430 | sc->debug.debugfs_phydir, sc, &fops_beacon); | 390 | sc->debug.debugfs_phydir, sc, &fops_beacon); |
431 | 391 | ||
@@ -444,7 +404,6 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) | |||
444 | { | 404 | { |
445 | debugfs_remove(sc->debug.debugfs_debug); | 405 | debugfs_remove(sc->debug.debugfs_debug); |
446 | debugfs_remove(sc->debug.debugfs_registers); | 406 | debugfs_remove(sc->debug.debugfs_registers); |
447 | debugfs_remove(sc->debug.debugfs_tsf); | ||
448 | debugfs_remove(sc->debug.debugfs_beacon); | 407 | debugfs_remove(sc->debug.debugfs_beacon); |
449 | debugfs_remove(sc->debug.debugfs_reset); | 408 | debugfs_remove(sc->debug.debugfs_reset); |
450 | debugfs_remove(sc->debug.debugfs_phydir); | 409 | debugfs_remove(sc->debug.debugfs_phydir); |
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index ffc529393306..66f69f04e55e 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h | |||
@@ -72,7 +72,6 @@ struct ath5k_dbg_info { | |||
72 | struct dentry *debugfs_phydir; | 72 | struct dentry *debugfs_phydir; |
73 | struct dentry *debugfs_debug; | 73 | struct dentry *debugfs_debug; |
74 | struct dentry *debugfs_registers; | 74 | struct dentry *debugfs_registers; |
75 | struct dentry *debugfs_tsf; | ||
76 | struct dentry *debugfs_beacon; | 75 | struct dentry *debugfs_beacon; |
77 | struct dentry *debugfs_reset; | 76 | struct dentry *debugfs_reset; |
78 | }; | 77 | }; |
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index 1cb7edfae625..b4ec539c464b 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c | |||
@@ -137,6 +137,18 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
137 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | 137 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { |
138 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | 138 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); |
139 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | 139 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); |
140 | |||
141 | /* XXX: Don't know which versions include these two */ | ||
142 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); | ||
143 | |||
144 | if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) | ||
145 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); | ||
146 | |||
147 | if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { | ||
148 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); | ||
149 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); | ||
150 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); | ||
151 | } | ||
140 | } | 152 | } |
141 | 153 | ||
142 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | 154 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { |
@@ -213,7 +225,8 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | |||
213 | } | 225 | } |
214 | 226 | ||
215 | /* | 227 | /* |
216 | * Read supported modes from eeprom | 228 | * Read supported modes and some mode-specific calibration data |
229 | * from eeprom | ||
217 | */ | 230 | */ |
218 | static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | 231 | static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, |
219 | unsigned int mode) | 232 | unsigned int mode) |
@@ -315,6 +328,9 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
315 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) | 328 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) |
316 | goto done; | 329 | goto done; |
317 | 330 | ||
331 | /* Note: >= v5 have bg freq piers on another location | ||
332 | * so these freq piers are ignored for >= v5 (should be 0xff | ||
333 | * anyway) */ | ||
318 | switch(mode) { | 334 | switch(mode) { |
319 | case AR5K_EEPROM_MODE_11A: | 335 | case AR5K_EEPROM_MODE_11A: |
320 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) | 336 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) |
@@ -442,7 +458,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, | |||
442 | return 0; | 458 | return 0; |
443 | } | 459 | } |
444 | 460 | ||
445 | 461 | /* Read mode-specific data (except power calibration data) */ | |
446 | static int | 462 | static int |
447 | ath5k_eeprom_init_modes(struct ath5k_hw *ah) | 463 | ath5k_eeprom_init_modes(struct ath5k_hw *ah) |
448 | { | 464 | { |
@@ -488,6 +504,16 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah) | |||
488 | return 0; | 504 | return 0; |
489 | } | 505 | } |
490 | 506 | ||
507 | /* Used to match PCDAC steps with power values on RF5111 chips | ||
508 | * (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC | ||
509 | * steps that match with the power values we read from eeprom. On | ||
510 | * older eeprom versions (< 3.2) these steps are equaly spaced at | ||
511 | * 10% of the pcdac curve -until the curve reaches it's maximum- | ||
512 | * (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) | ||
513 | * these 10 steps are spaced in a different way. This function returns | ||
514 | * the pcdac steps based on eeprom version and curve min/max so that we | ||
515 | * can have pcdac/pwr points. | ||
516 | */ | ||
491 | static inline void | 517 | static inline void |
492 | ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) | 518 | ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) |
493 | { | 519 | { |
@@ -507,37 +533,48 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) | |||
507 | *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; | 533 | *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; |
508 | } | 534 | } |
509 | 535 | ||
536 | /* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff | ||
537 | * frequency mask) */ | ||
510 | static inline int | 538 | static inline int |
511 | ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, | 539 | ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, |
512 | struct ath5k_chan_pcal_info *pc, u8 *count) | 540 | struct ath5k_chan_pcal_info *pc, unsigned int mode) |
513 | { | 541 | { |
542 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
514 | int o = *offset; | 543 | int o = *offset; |
515 | int i = 0; | 544 | int i = 0; |
516 | u8 f1, f2; | 545 | u8 freq1, freq2; |
517 | int ret; | 546 | int ret; |
518 | u16 val; | 547 | u16 val; |
519 | 548 | ||
520 | while(i < max) { | 549 | while(i < max) { |
521 | AR5K_EEPROM_READ(o++, val); | 550 | AR5K_EEPROM_READ(o++, val); |
522 | 551 | ||
523 | f1 = (val >> 8) & 0xff; | 552 | freq1 = (val >> 8) & 0xff; |
524 | f2 = val & 0xff; | 553 | freq2 = val & 0xff; |
525 | 554 | ||
526 | if (f1) | 555 | if (freq1) { |
527 | pc[i++].freq = f1; | 556 | pc[i++].freq = ath5k_eeprom_bin2freq(ee, |
557 | freq1, mode); | ||
558 | ee->ee_n_piers[mode]++; | ||
559 | } | ||
528 | 560 | ||
529 | if (f2) | 561 | if (freq2) { |
530 | pc[i++].freq = f2; | 562 | pc[i++].freq = ath5k_eeprom_bin2freq(ee, |
563 | freq2, mode); | ||
564 | ee->ee_n_piers[mode]++; | ||
565 | } | ||
531 | 566 | ||
532 | if (!f1 || !f2) | 567 | if (!freq1 || !freq2) |
533 | break; | 568 | break; |
534 | } | 569 | } |
570 | |||
571 | /* return new offset */ | ||
535 | *offset = o; | 572 | *offset = o; |
536 | *count = i; | ||
537 | 573 | ||
538 | return 0; | 574 | return 0; |
539 | } | 575 | } |
540 | 576 | ||
577 | /* Read frequency piers for 802.11a */ | ||
541 | static int | 578 | static int |
542 | ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) | 579 | ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) |
543 | { | 580 | { |
@@ -550,7 +587,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) | |||
550 | if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { | 587 | if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { |
551 | ath5k_eeprom_read_freq_list(ah, &offset, | 588 | ath5k_eeprom_read_freq_list(ah, &offset, |
552 | AR5K_EEPROM_N_5GHZ_CHAN, pcal, | 589 | AR5K_EEPROM_N_5GHZ_CHAN, pcal, |
553 | &ee->ee_n_piers[AR5K_EEPROM_MODE_11A]); | 590 | AR5K_EEPROM_MODE_11A); |
554 | } else { | 591 | } else { |
555 | mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); | 592 | mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); |
556 | 593 | ||
@@ -577,23 +614,25 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) | |||
577 | 614 | ||
578 | AR5K_EEPROM_READ(offset++, val); | 615 | AR5K_EEPROM_READ(offset++, val); |
579 | pcal[9].freq |= (val >> 10) & 0x3f; | 616 | pcal[9].freq |= (val >> 10) & 0x3f; |
617 | |||
618 | /* Fixed number of piers */ | ||
580 | ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; | 619 | ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; |
581 | } | ||
582 | 620 | ||
583 | for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) { | 621 | for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { |
584 | pcal[i].freq = ath5k_eeprom_bin2freq(ee, | 622 | pcal[i].freq = ath5k_eeprom_bin2freq(ee, |
585 | pcal[i].freq, AR5K_EEPROM_MODE_11A); | 623 | pcal[i].freq, AR5K_EEPROM_MODE_11A); |
624 | } | ||
586 | } | 625 | } |
587 | 626 | ||
588 | return 0; | 627 | return 0; |
589 | } | 628 | } |
590 | 629 | ||
630 | /* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ | ||
591 | static inline int | 631 | static inline int |
592 | ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | 632 | ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) |
593 | { | 633 | { |
594 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 634 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
595 | struct ath5k_chan_pcal_info *pcal; | 635 | struct ath5k_chan_pcal_info *pcal; |
596 | int i; | ||
597 | 636 | ||
598 | switch(mode) { | 637 | switch(mode) { |
599 | case AR5K_EEPROM_MODE_11B: | 638 | case AR5K_EEPROM_MODE_11B: |
@@ -608,23 +647,25 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
608 | 647 | ||
609 | ath5k_eeprom_read_freq_list(ah, &offset, | 648 | ath5k_eeprom_read_freq_list(ah, &offset, |
610 | AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, | 649 | AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, |
611 | &ee->ee_n_piers[mode]); | 650 | mode); |
612 | for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) { | ||
613 | pcal[i].freq = ath5k_eeprom_bin2freq(ee, | ||
614 | pcal[i].freq, mode); | ||
615 | } | ||
616 | 651 | ||
617 | return 0; | 652 | return 0; |
618 | } | 653 | } |
619 | 654 | ||
620 | 655 | /* Read power calibration for RF5111 chips | |
656 | * For RF5111 we have an XPD -eXternal Power Detector- curve | ||
657 | * for each calibrated channel. Each curve has PCDAC steps on | ||
658 | * x axis and power on y axis and looks like a logarithmic | ||
659 | * function. To recreate the curve and pass the power values | ||
660 | * on the pcdac table, we read 10 points here and interpolate later. | ||
661 | */ | ||
621 | static int | 662 | static int |
622 | ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) | 663 | ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) |
623 | { | 664 | { |
624 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 665 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
625 | struct ath5k_chan_pcal_info *pcal; | 666 | struct ath5k_chan_pcal_info *pcal; |
626 | int offset, ret; | 667 | int offset, ret; |
627 | int i, j; | 668 | int i; |
628 | u16 val; | 669 | u16 val; |
629 | 670 | ||
630 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); | 671 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); |
@@ -704,16 +745,22 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) | |||
704 | 745 | ||
705 | ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, | 746 | ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, |
706 | cdata->pcdac_max, cdata->pcdac); | 747 | cdata->pcdac_max, cdata->pcdac); |
707 | |||
708 | for (j = 0; j < AR5K_EEPROM_N_PCDAC; j++) { | ||
709 | cdata->pwr[j] = (u16) | ||
710 | (AR5K_EEPROM_POWER_STEP * cdata->pwr[j]); | ||
711 | } | ||
712 | } | 748 | } |
713 | 749 | ||
714 | return 0; | 750 | return 0; |
715 | } | 751 | } |
716 | 752 | ||
753 | /* Read power calibration for RF5112 chips | ||
754 | * For RF5112 we have 4 XPD -eXternal Power Detector- curves | ||
755 | * for each calibrated channel on 0, -6, -12 and -18dbm but we only | ||
756 | * use the higher (3) and the lower (0) curves. Each curve has PCDAC | ||
757 | * steps on x axis and power on y axis and looks like a linear | ||
758 | * function. To recreate the curve and pass the power values | ||
759 | * on the pcdac table, we read 4 points for xpd 0 and 3 points | ||
760 | * for xpd 3 here and interpolate later. | ||
761 | * | ||
762 | * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. | ||
763 | */ | ||
717 | static int | 764 | static int |
718 | ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | 765 | ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) |
719 | { | 766 | { |
@@ -790,7 +837,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
790 | 837 | ||
791 | /* PCDAC steps | 838 | /* PCDAC steps |
792 | * corresponding to the above power | 839 | * corresponding to the above power |
793 | * measurements (static) */ | 840 | * measurements (fixed) */ |
794 | chan_pcal_info->pcdac_x3[0] = 20; | 841 | chan_pcal_info->pcdac_x3[0] = 20; |
795 | chan_pcal_info->pcdac_x3[1] = 35; | 842 | chan_pcal_info->pcdac_x3[1] = 35; |
796 | chan_pcal_info->pcdac_x3[2] = 63; | 843 | chan_pcal_info->pcdac_x3[2] = 63; |
@@ -814,6 +861,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
814 | return 0; | 861 | return 0; |
815 | } | 862 | } |
816 | 863 | ||
864 | /* For RF2413 power calibration data doesn't start on a fixed location and | ||
865 | * if a mode is not supported, it's section is missing -not zeroed-. | ||
866 | * So we need to calculate the starting offset for each section by using | ||
867 | * these two functions */ | ||
868 | |||
869 | /* Return the size of each section based on the mode and the number of pd | ||
870 | * gains available (maximum 4). */ | ||
817 | static inline unsigned int | 871 | static inline unsigned int |
818 | ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) | 872 | ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) |
819 | { | 873 | { |
@@ -826,6 +880,8 @@ ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) | |||
826 | return sz; | 880 | return sz; |
827 | } | 881 | } |
828 | 882 | ||
883 | /* Return the starting offset for a section based on the modes supported | ||
884 | * and each section's size. */ | ||
829 | static unsigned int | 885 | static unsigned int |
830 | ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) | 886 | ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) |
831 | { | 887 | { |
@@ -834,11 +890,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) | |||
834 | switch(mode) { | 890 | switch(mode) { |
835 | case AR5K_EEPROM_MODE_11G: | 891 | case AR5K_EEPROM_MODE_11G: |
836 | if (AR5K_EEPROM_HDR_11B(ee->ee_header)) | 892 | if (AR5K_EEPROM_HDR_11B(ee->ee_header)) |
837 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2; | 893 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + |
894 | AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; | ||
838 | /* fall through */ | 895 | /* fall through */ |
839 | case AR5K_EEPROM_MODE_11B: | 896 | case AR5K_EEPROM_MODE_11B: |
840 | if (AR5K_EEPROM_HDR_11A(ee->ee_header)) | 897 | if (AR5K_EEPROM_HDR_11A(ee->ee_header)) |
841 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5; | 898 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + |
899 | AR5K_EEPROM_N_5GHZ_CHAN / 2; | ||
842 | /* fall through */ | 900 | /* fall through */ |
843 | case AR5K_EEPROM_MODE_11A: | 901 | case AR5K_EEPROM_MODE_11A: |
844 | break; | 902 | break; |
@@ -849,6 +907,17 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) | |||
849 | return offset; | 907 | return offset; |
850 | } | 908 | } |
851 | 909 | ||
910 | /* Read power calibration for RF2413 chips | ||
911 | * For RF2413 we have a PDDAC table (Power Detector) instead | ||
912 | * of a PCDAC and 4 pd gain curves for each calibrated channel. | ||
913 | * Each curve has PDDAC steps on x axis and power on y axis and | ||
914 | * looks like an exponential function. To recreate the curves | ||
915 | * we read here the points and interpolate later. Note that | ||
916 | * in most cases only higher and lower curves are used (like | ||
917 | * RF5112) but vendors have the oportunity to include all 4 | ||
918 | * curves on eeprom. The final curve (higher power) has an extra | ||
919 | * point for better accuracy like RF5112. | ||
920 | */ | ||
852 | static int | 921 | static int |
853 | ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | 922 | ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) |
854 | { | 923 | { |
@@ -868,6 +937,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | |||
868 | ee->ee_pd_gains[mode] = pd_gains; | 937 | ee->ee_pd_gains[mode] = pd_gains; |
869 | 938 | ||
870 | offset = ath5k_cal_data_offset_2413(ee, mode); | 939 | offset = ath5k_cal_data_offset_2413(ee, mode); |
940 | ee->ee_n_piers[mode] = 0; | ||
871 | switch (mode) { | 941 | switch (mode) { |
872 | case AR5K_EEPROM_MODE_11A: | 942 | case AR5K_EEPROM_MODE_11A: |
873 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | 943 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) |
@@ -1163,6 +1233,20 @@ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned | |||
1163 | return 0; | 1233 | return 0; |
1164 | } | 1234 | } |
1165 | 1235 | ||
1236 | /* | ||
1237 | * Read per channel calibration info from EEPROM | ||
1238 | * | ||
1239 | * This info is used to calibrate the baseband power table. Imagine | ||
1240 | * that for each channel there is a power curve that's hw specific | ||
1241 | * (depends on amplifier etc) and we try to "correct" this curve using | ||
1242 | * offests we pass on to phy chip (baseband -> before amplifier) so that | ||
1243 | * it can use accurate power values when setting tx power (takes amplifier's | ||
1244 | * performance on each channel into account). | ||
1245 | * | ||
1246 | * EEPROM provides us with the offsets for some pre-calibrated channels | ||
1247 | * and we have to interpolate to create the full table for these channels and | ||
1248 | * also the table for any channel. | ||
1249 | */ | ||
1166 | static int | 1250 | static int |
1167 | ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | 1251 | ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) |
1168 | { | 1252 | { |
@@ -1193,7 +1277,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | |||
1193 | return 0; | 1277 | return 0; |
1194 | } | 1278 | } |
1195 | 1279 | ||
1196 | /* Read conformance test limits */ | 1280 | /* Read conformance test limits used for regulatory control */ |
1197 | static int | 1281 | static int |
1198 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | 1282 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) |
1199 | { | 1283 | { |
diff --git a/drivers/net/wireless/ath5k/gpio.c b/drivers/net/wireless/ath5k/gpio.c index b77205adc180..64a27e73d02e 100644 --- a/drivers/net/wireless/ath5k/gpio.c +++ b/drivers/net/wireless/ath5k/gpio.c | |||
@@ -83,7 +83,7 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) | |||
83 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | 83 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) |
84 | { | 84 | { |
85 | ATH5K_TRACE(ah->ah_sc); | 85 | ATH5K_TRACE(ah->ah_sc); |
86 | if (gpio > AR5K_NUM_GPIO) | 86 | if (gpio >= AR5K_NUM_GPIO) |
87 | return -EINVAL; | 87 | return -EINVAL; |
88 | 88 | ||
89 | ath5k_hw_reg_write(ah, | 89 | ath5k_hw_reg_write(ah, |
@@ -99,7 +99,7 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) | |||
99 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | 99 | int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) |
100 | { | 100 | { |
101 | ATH5K_TRACE(ah->ah_sc); | 101 | ATH5K_TRACE(ah->ah_sc); |
102 | if (gpio > AR5K_NUM_GPIO) | 102 | if (gpio >= AR5K_NUM_GPIO) |
103 | return -EINVAL; | 103 | return -EINVAL; |
104 | 104 | ||
105 | ath5k_hw_reg_write(ah, | 105 | ath5k_hw_reg_write(ah, |
@@ -115,7 +115,7 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) | |||
115 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) | 115 | u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) |
116 | { | 116 | { |
117 | ATH5K_TRACE(ah->ah_sc); | 117 | ATH5K_TRACE(ah->ah_sc); |
118 | if (gpio > AR5K_NUM_GPIO) | 118 | if (gpio >= AR5K_NUM_GPIO) |
119 | return 0xffffffff; | 119 | return 0xffffffff; |
120 | 120 | ||
121 | /* GPIO input magic */ | 121 | /* GPIO input magic */ |
@@ -131,7 +131,7 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) | |||
131 | u32 data; | 131 | u32 data; |
132 | ATH5K_TRACE(ah->ah_sc); | 132 | ATH5K_TRACE(ah->ah_sc); |
133 | 133 | ||
134 | if (gpio > AR5K_NUM_GPIO) | 134 | if (gpio >= AR5K_NUM_GPIO) |
135 | return -EINVAL; | 135 | return -EINVAL; |
136 | 136 | ||
137 | /* GPIO output magic */ | 137 | /* GPIO output magic */ |
@@ -154,7 +154,7 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | |||
154 | u32 data; | 154 | u32 data; |
155 | 155 | ||
156 | ATH5K_TRACE(ah->ah_sc); | 156 | ATH5K_TRACE(ah->ah_sc); |
157 | if (gpio > AR5K_NUM_GPIO) | 157 | if (gpio >= AR5K_NUM_GPIO) |
158 | return; | 158 | return; |
159 | 159 | ||
160 | /* | 160 | /* |
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 75eb9f43c741..f8a4a6960270 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c | |||
@@ -646,6 +646,23 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
646 | } | 646 | } |
647 | 647 | ||
648 | /** | 648 | /** |
649 | * ath5k_hw_set_tsf64 - Set a new 64bit TSF | ||
650 | * | ||
651 | * @ah: The &struct ath5k_hw | ||
652 | * @tsf64: The new 64bit TSF | ||
653 | * | ||
654 | * Sets the new TSF | ||
655 | */ | ||
656 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) | ||
657 | { | ||
658 | ATH5K_TRACE(ah->ah_sc); | ||
659 | |||
660 | ath5k_hw_reg_write(ah, 0x00000000, AR5K_TSF_L32); | ||
661 | ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); | ||
662 | ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); | ||
663 | } | ||
664 | |||
665 | /** | ||
649 | * ath5k_hw_reset_tsf - Force a TSF reset | 666 | * ath5k_hw_reset_tsf - Force a TSF reset |
650 | * | 667 | * |
651 | * @ah: The &struct ath5k_hw | 668 | * @ah: The &struct ath5k_hw |
@@ -1026,6 +1043,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key) | |||
1026 | return AR5K_KEYTABLE_TYPE_40; | 1043 | return AR5K_KEYTABLE_TYPE_40; |
1027 | else if (key->keylen == LEN_WEP104) | 1044 | else if (key->keylen == LEN_WEP104) |
1028 | return AR5K_KEYTABLE_TYPE_104; | 1045 | return AR5K_KEYTABLE_TYPE_104; |
1046 | return -EINVAL; | ||
1047 | default: | ||
1048 | return -EINVAL; | ||
1029 | } | 1049 | } |
1030 | return -EINVAL; | 1050 | return -EINVAL; |
1031 | } | 1051 | } |
@@ -1041,7 +1061,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
1041 | __le32 key_v[5] = {}; | 1061 | __le32 key_v[5] = {}; |
1042 | __le32 key0 = 0, key1 = 0; | 1062 | __le32 key0 = 0, key1 = 0; |
1043 | __le32 *rxmic, *txmic; | 1063 | __le32 *rxmic, *txmic; |
1044 | u32 keytype; | 1064 | int keytype; |
1045 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | 1065 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; |
1046 | bool is_tkip; | 1066 | bool is_tkip; |
1047 | const u8 *key_ptr; | 1067 | const u8 *key_ptr; |
@@ -1139,7 +1159,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1139 | 1159 | ||
1140 | /* MAC may be NULL if it's a broadcast key. In this case no need to | 1160 | /* MAC may be NULL if it's a broadcast key. In this case no need to |
1141 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | 1161 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ |
1142 | if (unlikely(mac == NULL)) { | 1162 | if (!mac) { |
1143 | low_id = 0xffffffff; | 1163 | low_id = 0xffffffff; |
1144 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | 1164 | high_id = 0xffff | AR5K_KEYTABLE_VALID; |
1145 | } else { | 1165 | } else { |
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c index 1b7bc50ea8eb..5094c394a4b2 100644 --- a/drivers/net/wireless/ath5k/qcu.c +++ b/drivers/net/wireless/ath5k/qcu.c | |||
@@ -148,6 +148,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
148 | */ | 148 | */ |
149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | 149 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) |
150 | { | 150 | { |
151 | u32 pending; | ||
151 | ATH5K_TRACE(ah->ah_sc); | 152 | ATH5K_TRACE(ah->ah_sc); |
152 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 153 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
153 | 154 | ||
@@ -159,7 +160,15 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | |||
159 | if (ah->ah_version == AR5K_AR5210) | 160 | if (ah->ah_version == AR5K_AR5210) |
160 | return false; | 161 | return false; |
161 | 162 | ||
162 | return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT; | 163 | pending = (AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT); |
164 | |||
165 | /* It's possible to have no frames pending even if TXE | ||
166 | * is set. To indicate that q has not stopped return | ||
167 | * true */ | ||
168 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
169 | return true; | ||
170 | |||
171 | return pending; | ||
163 | } | 172 | } |
164 | 173 | ||
165 | /* | 174 | /* |
@@ -324,8 +333,18 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
324 | /* | 333 | /* |
325 | * Set misc registers | 334 | * Set misc registers |
326 | */ | 335 | */ |
327 | ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY, | 336 | /* Enable DCU early termination for this queue */ |
328 | AR5K_QUEUE_MISC(queue)); | 337 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
338 | AR5K_QCU_MISC_DCU_EARLY); | ||
339 | |||
340 | /* Enable DCU to wait for next fragment from QCU */ | ||
341 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
342 | AR5K_DCU_MISC_FRAG_WAIT); | ||
343 | |||
344 | /* On Maui and Spirit use the global seqnum on DCU */ | ||
345 | if (ah->ah_mac_version < AR5K_SREV_AR5211) | ||
346 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
347 | AR5K_DCU_MISC_SEQNUM_CTL); | ||
329 | 348 | ||
330 | if (tq->tqi_cbr_period) { | 349 | if (tq->tqi_cbr_period) { |
331 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | 350 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, |
@@ -341,7 +360,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
341 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | 360 | AR5K_QCU_MISC_CBR_THRES_ENABLE); |
342 | } | 361 | } |
343 | 362 | ||
344 | if (tq->tqi_ready_time) | 363 | if (tq->tqi_ready_time && |
364 | (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) | ||
345 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | 365 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, |
346 | AR5K_QCU_RDYTIMECFG_INTVAL) | | 366 | AR5K_QCU_RDYTIMECFG_INTVAL) | |
347 | AR5K_QCU_RDYTIMECFG_ENABLE, | 367 | AR5K_QCU_RDYTIMECFG_ENABLE, |
@@ -383,13 +403,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
383 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | 403 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | |
384 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | 404 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | |
385 | AR5K_DCU_MISC_BCN_ENABLE); | 405 | AR5K_DCU_MISC_BCN_ENABLE); |
386 | |||
387 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
388 | (AR5K_TUNE_SW_BEACON_RESP - | ||
389 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
390 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
391 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
392 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
393 | break; | 406 | break; |
394 | 407 | ||
395 | case AR5K_TX_QUEUE_CAB: | 408 | case AR5K_TX_QUEUE_CAB: |
@@ -398,6 +411,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
398 | AR5K_QCU_MISC_CBREXP_DIS | | 411 | AR5K_QCU_MISC_CBREXP_DIS | |
399 | AR5K_QCU_MISC_CBREXP_BCN_DIS); | 412 | AR5K_QCU_MISC_CBREXP_BCN_DIS); |
400 | 413 | ||
414 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | ||
415 | (AR5K_TUNE_SW_BEACON_RESP - | ||
416 | AR5K_TUNE_DMA_BEACON_RESP) - | ||
417 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | ||
418 | AR5K_QCU_RDYTIMECFG_ENABLE, | ||
419 | AR5K_QUEUE_RDYTIMECFG(queue)); | ||
420 | |||
401 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | 421 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
402 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | 422 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << |
403 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | 423 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); |
@@ -413,6 +433,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
413 | break; | 433 | break; |
414 | } | 434 | } |
415 | 435 | ||
436 | /* TODO: Handle frame compression */ | ||
437 | |||
416 | /* | 438 | /* |
417 | * Enable interrupts for this tx queue | 439 | * Enable interrupts for this tx queue |
418 | * in the secondary interrupt mask registers | 440 | * in the secondary interrupt mask registers |
@@ -483,6 +505,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
483 | * by setting AR5K_TXNOFRM to zero */ | 505 | * by setting AR5K_TXNOFRM to zero */ |
484 | if (ah->ah_txq_imr_nofrm == 0) | 506 | if (ah->ah_txq_imr_nofrm == 0) |
485 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); | 507 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); |
508 | |||
509 | /* Set QCU mask for this DCU to save power */ | ||
510 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); | ||
486 | } | 511 | } |
487 | 512 | ||
488 | return 0; | 513 | return 0; |