From: John W. Linville Date: Wed, 8 Dec 2010 21:23:31 +0000 (-0500) Subject: Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel... X-Git-Tag: v2.6.38-rc1~476^2~169^2^2~2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=393934c6b5c8d00f9d1ae20670d4a770f07a418a;hp=-c;p=karo-tx-linux.git Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 Conflicts: drivers/net/wireless/ath/ath9k/ath9k.h drivers/net/wireless/ath/ath9k/main.c drivers/net/wireless/ath/ath9k/xmit.c --- 393934c6b5c8d00f9d1ae20670d4a770f07a418a diff --combined drivers/net/wireless/ath/ath5k/base.c index bccea7450c38,42ed923cdb1a..4e3b97c3d7c2 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@@ -47,6 -47,8 +47,6 @@@ #include #include #include -#include -#include #include #include #include @@@ -60,6 -62,7 +60,6 @@@ #include "reg.h" #include "debug.h" #include "ani.h" -#include "../debug.h" static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); @@@ -75,25 -78,39 +75,25 @@@ MODULE_AUTHOR("Nick Kossifidis") MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); +static int ath5k_init(struct ieee80211_hw *hw); +static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu); static int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); -/* Known PCI ids */ -static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { - { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); - /* Known SREVs */ static const struct ath5k_srev_name srev_names[] = { +#ifdef CONFIG_ATHEROS_AR231X + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 }, + { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 }, + { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 }, + { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 }, + { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 }, +#else { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, @@@ -112,7 -129,6 +112,7 @@@ { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, +#endif { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, @@@ -126,12 -142,10 +126,12 @@@ { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, - { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, - { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, +#ifdef CONFIG_ATHEROS_AR231X + { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, + { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, +#endif { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, }; @@@ -183,8 -197,8 +183,8 @@@ static inline void ath5k_txbuf_free_skb BUG_ON(!bf); if (!bf->skb) return; - pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, - PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; bf->skbaddr = 0; @@@ -200,8 -214,8 +200,8 @@@ static inline void ath5k_rxbuf_free_skb BUG_ON(!bf); if (!bf->skb) return; - pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, + DMA_FROM_DEVICE); dev_kfree_skb_any(bf->skb); bf->skb = NULL; bf->skbaddr = 0; @@@ -219,7 -233,7 +219,7 @@@ static inline u64 ath5k_extend_tsf(stru return (tsf & ~0x7fff) | rstamp; } -static const char * +const char * ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) { const char *name = "xxxxx"; @@@ -313,12 -327,14 +313,12 @@@ ath5k_copy_channels(struct ath5k_hw *ah switch (mode) { case AR5K_MODE_11A: - case AR5K_MODE_11A_TURBO: /* 1..220, but 2GHz frequencies are filtered by check_channel */ size = 220 ; chfreq = CHANNEL_5GHZ; break; case AR5K_MODE_11B: case AR5K_MODE_11G: - case AR5K_MODE_11G_TURBO: size = 26; chfreq = CHANNEL_2GHZ; break; @@@ -347,6 -363,11 +347,6 @@@ case AR5K_MODE_11G: channels[count].hw_value = chfreq | CHANNEL_OFDM; break; - case AR5K_MODE_11A_TURBO: - case AR5K_MODE_11G_TURBO: - channels[count].hw_value = chfreq | - CHANNEL_OFDM | CHANNEL_TURBO; - break; case AR5K_MODE_11B: channels[count].hw_value = CHANNEL_B; } @@@ -475,7 -496,7 +475,7 @@@ ath5k_chan_set(struct ath5k_softc *sc, * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - return ath5k_reset(sc, chan); + return ath5k_reset(sc, chan, true); } static void @@@ -528,7 -549,7 +528,7 @@@ static void ath_vif_iter(void *data, u /* Calculate combined mode - when APs are active, operate in AP mode. * Otherwise use the mode of the new interface. This can currently * only deal with combinations of APs and STAs. Only one ad-hoc - * interfaces is allowed above. + * interfaces is allowed. */ if (avf->opmode == NL80211_IFTYPE_AP) iter_data->opmode = NL80211_IFTYPE_AP; @@@ -537,8 -558,16 +537,8 @@@ iter_data->opmode = avf->opmode; } -static void ath_do_set_opmode(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - ath5k_hw_set_opmode(ah, sc->opmode); - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", - sc->opmode, ath_opmode_to_string(sc->opmode)); -} - -void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, - struct ieee80211_vif *vif) +static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, + struct ieee80211_vif *vif) { struct ath_common *common = ath5k_hw_common(sc->ah); struct ath_vif_iter_data iter_data; @@@ -566,9 -595,7 +566,9 @@@ /* Nothing active, default to station mode */ sc->opmode = NL80211_IFTYPE_STATION; - ath_do_set_opmode(sc); + ath5k_hw_set_opmode(sc->ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", + sc->opmode, ath_opmode_to_string(sc->opmode)); if (iter_data.need_set_hw_addr && iter_data.found_active) ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); @@@ -632,11 -659,10 +632,11 @@@ struct sk_buff *ath5k_rx_skb_alloc(stru return NULL; } - *skb_addr = pci_map_single(sc->pdev, + *skb_addr = dma_map_single(sc->dev, skb->data, common->rx_bufsize, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { + DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) { ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); dev_kfree_skb(skb); return NULL; @@@ -732,8 -758,8 +732,8 @@@ ath5k_txbuf_setup(struct ath5k_softc *s flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; /* XXX endianness */ - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); if (!rate) { @@@ -813,7 -839,7 +813,7 @@@ return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@@ -822,7 -848,7 +822,7 @@@ \*******************/ static int -ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_alloc(struct ath5k_softc *sc) { struct ath5k_desc *ds; struct ath5k_buf *bf; @@@ -833,9 -859,7 +833,9 @@@ /* allocate descriptors */ sc->desc_len = sizeof(struct ath5k_desc) * (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); + + sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len, + &sc->desc_daddr, GFP_KERNEL); if (sc->desc == NULL) { ATH5K_ERR(sc, "can't allocate descriptors\n"); ret = -ENOMEM; @@@ -881,14 -905,14 +881,14 @@@ return 0; err_free: - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); err: sc->desc = NULL; return ret; } static void -ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) +ath5k_desc_free(struct ath5k_softc *sc) { struct ath5k_buf *bf; @@@ -900,7 -924,7 +900,7 @@@ ath5k_txbuf_free_skb(sc, bf); /* Free memory associated with all descriptors */ - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); + dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); sc->desc = NULL; sc->desc_daddr = 0; @@@ -1045,44 -1069,62 +1045,44 @@@ err return ret; } +/** + * ath5k_drain_tx_buffs - Empty tx buffers + * + * @sc The &struct ath5k_softc + * + * Empty tx buffers from all queues in preparation + * of a reset or during shutdown. + * + * NB: this assumes output has been stopped and + * we do not need to block ath5k_tx_tasklet + */ static void -ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) +ath5k_drain_tx_buffs(struct ath5k_softc *sc) { + struct ath5k_txq *txq; struct ath5k_buf *bf, *bf0; + int i; - /* - * NB: this assumes output has been stopped and - * we do not need to block ath5k_tx_tasklet - */ - spin_lock_bh(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); - - ath5k_txbuf_free_skb(sc, bf); - - spin_lock_bh(&sc->txbuflock); - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - txq->txq_len--; - spin_unlock_bh(&sc->txbuflock); - } - txq->link = NULL; - txq->txq_poll_mark = false; - spin_unlock_bh(&txq->lock); -} + for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { + if (sc->txqs[i].setup) { + txq = &sc->txqs[i]; + spin_lock_bh(&txq->lock); + list_for_each_entry_safe(bf, bf0, &txq->q, list) { + ath5k_debug_printtxbuf(sc, bf); -/* - * Drain the transmit queues and reclaim resources. - */ -static void -ath5k_txq_cleanup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned int i; + ath5k_txbuf_free_skb(sc, bf); - /* XXX return value */ - if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { - /* don't touch the hardware if marked invalid */ - ath5k_hw_stop_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", - ath5k_hw_get_txdp(ah, sc->bhalq)); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) { - ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " - "link %p\n", - sc->txqs[i].qnum, - ath5k_hw_get_txdp(ah, - sc->txqs[i].qnum), - sc->txqs[i].link); + spin_lock_bh(&sc->txbuflock); + list_move_tail(&bf->list, &sc->txbuf); + sc->txbuf_len++; + txq->txq_len--; + spin_unlock_bh(&sc->txbuflock); } + txq->link = NULL; + txq->txq_poll_mark = false; + spin_unlock_bh(&txq->lock); + } } - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) - ath5k_txq_drainq(sc, &sc->txqs[i]); } static void @@@ -1142,19 -1184,16 +1142,19 @@@ err } /* - * Disable the receive h/w in preparation for a reset. + * Disable the receive logic on PCU (DRU) + * In preparation for a shutdown. + * + * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop + * does. */ static void ath5k_rx_stop(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; - ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ - ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ + ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ ath5k_debug_printrxbuffs(sc, ah); } @@@ -1268,7 -1307,8 +1268,7 @@@ ath5k_update_beacon_rssi(struct ath5k_s memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) return; - ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, - rssi); + ewma_add(&ah->ah_beacon_rssi_avg, rssi); /* in IBSS mode we should keep RSSI statistics per neighbour */ /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ @@@ -1511,9 -1551,9 +1511,9 @@@ ath5k_tasklet_rx(unsigned long data if (!next_skb) goto next; - pci_unmap_single(sc->pdev, bf->skbaddr, + dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, - PCI_DMA_FROMDEVICE); + DMA_FROM_DEVICE); skb_put(skb, rs.rs_datalen); @@@ -1676,9 -1716,8 +1676,9 @@@ ath5k_tx_processq(struct ath5k_softc *s skb = bf->skb; bf->skb = NULL; - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); + + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, + DMA_TO_DEVICE); ath5k_tx_frame_completed(sc, skb, &ts); } @@@ -1732,13 -1771,12 +1732,13 @@@ ath5k_beacon_setup(struct ath5k_softc * u32 flags; const int padsize = 0; - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); + bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, + DMA_TO_DEVICE); ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " "skbaddr %llx\n", skb, skb->data, skb->len, (unsigned long long)bf->skbaddr); - if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { + + if (dma_mapping_error(sc->dev, bf->skbaddr)) { ATH5K_ERR(sc, "beacon DMA mapping failed\n"); return -EIO; } @@@ -1790,7 -1828,7 +1790,7 @@@ return 0; err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); + dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); return ret; } @@@ -1879,7 -1917,8 +1879,8 @@@ ath5k_beacon_send(struct ath5k_softc *s sc->bmisscount = 0; } - if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) { + if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) || + sc->opmode == NL80211_IFTYPE_MESH_POINT) { u64 tsf = ath5k_hw_get_tsf64(ah); u32 tsftu = TSF_TO_TU(tsf); int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval; @@@ -1906,13 -1945,14 +1907,14 @@@ * This should never fail since we check above that no frames * are still pending on the queue. */ - if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { + if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) { ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); /* NB: hw still stops DMA, so proceed */ } - /* refresh the beacon for AP mode */ - if (sc->opmode == NL80211_IFTYPE_AP) + /* refresh the beacon for AP or MESH mode */ + if (sc->opmode == NL80211_IFTYPE_AP || + sc->opmode == NL80211_IFTYPE_MESH_POINT) ath5k_beacon_update(sc->hw, vif); ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); @@@ -2075,7 -2115,7 +2077,7 @@@ ath5k_beacon_config(struct ath5k_softc } else ath5k_beacon_update_timers(sc, -1); } else { - ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); + ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq); } ath5k_hw_set_imr(ah, sc->imask); @@@ -2137,7 -2177,7 +2139,7 @@@ ath5k_intr_calibration_poll(struct ath5 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ } -static irqreturn_t +irqreturn_t ath5k_intr(int irq, void *dev_id) { struct ath5k_softc *sc = dev_id; @@@ -2146,8 -2186,7 +2148,8 @@@ unsigned int counter = 1000; if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || - !ath5k_hw_is_intr_pending(ah))) + ((ath5k_get_bus_type(ah) != ATH_AHB) && + !ath5k_hw_is_intr_pending(ah)))) return IRQ_NONE; do { @@@ -2213,10 -2252,6 +2215,10 @@@ tasklet_schedule(&sc->rf_kill.toggleq); } + + if (ath5k_get_bus_type(ah) == ATH_AHB) + break; + } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); if (unlikely(!counter)) @@@ -2316,7 -2351,7 +2318,7 @@@ ath5k_tx_complete_poll_work(struct work if (needreset) { ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "TX queues stuck, resetting\n"); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@@ -2328,159 -2363,6 +2330,159 @@@ * Initialization routines * \*************************/ +int +ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_common *common; + int ret; + int csz; + + /* Initialize driver private data */ + SET_IEEE80211_DEV(hw, sc->dev); + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->extra_tx_headroom = 2; + hw->channel_change_time = 5000; + + /* + * Mark the device as detached to avoid processing + * interrupts until setup is complete. + */ + __set_bit(ATH_STAT_INVALID, sc->status); + + sc->opmode = NL80211_IFTYPE_STATION; + sc->bintval = 1000; + mutex_init(&sc->lock); + spin_lock_init(&sc->rxbuflock); + spin_lock_init(&sc->txbuflock); + spin_lock_init(&sc->block); + + + /* Setup interrupt handler */ + ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); + if (ret) { + ATH5K_ERR(sc, "request_irq failed\n"); + goto err; + } + + /* If we passed the test, malloc an ath5k_hw struct */ + sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); + if (!sc->ah) { + ret = -ENOMEM; + ATH5K_ERR(sc, "out of memory\n"); + goto err_irq; + } + + sc->ah->ah_sc = sc; + sc->ah->ah_iobase = sc->iobase; + common = ath5k_hw_common(sc->ah); + common->ops = &ath5k_common_ops; + common->bus_ops = bus_ops; + common->ah = sc->ah; + common->hw = hw; + common->priv = sc; + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath5k_read_cachesize(common, &csz); + common->cachelsz = csz << 2; /* convert to bytes */ + + spin_lock_init(&common->cc_lock); + + /* Initialize device */ + ret = ath5k_hw_init(sc); + if (ret) + goto err_free_ah; + + /* set up multi-rate retry capabilities */ + if (sc->ah->ah_version == AR5K_AR5212) { + hw->max_rates = 4; + hw->max_rate_tries = 11; + } + + hw->vif_data_size = sizeof(struct ath5k_vif); + + /* Finish private driver data initialization */ + ret = ath5k_init(hw); + if (ret) + goto err_ah; + + ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", + ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), + sc->ah->ah_mac_srev, + sc->ah->ah_phy_revision); + + if (!sc->ah->ah_single_chip) { + /* Single chip radio (!RF5111) */ + if (sc->ah->ah_radio_5ghz_revision && + !sc->ah->ah_radio_2ghz_revision) { + /* No 5GHz support -> report 2GHz radio */ + if (!test_bit(AR5K_MODE_11A, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* No 2GHz support (5110 and some + * 5Ghz only cards) -> report 5Ghz radio */ + } else if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) { + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* Multiband radio */ + } else { + ATH5K_INFO(sc, "RF%s multiband radio found" + " (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + } + } + /* Multi chip radio (RF5111 - RF2111) -> + * report both 2GHz/5GHz radios */ + else if (sc->ah->ah_radio_5ghz_revision && + sc->ah->ah_radio_2ghz_revision){ + ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_2ghz_revision), + sc->ah->ah_radio_2ghz_revision); + } + } + + ath5k_debug_init_device(sc); + + /* ready to process interrupts */ + __clear_bit(ATH_STAT_INVALID, sc->status); + + return 0; +err_ah: + ath5k_hw_deinit(sc->ah); +err_free_ah: + kfree(sc->ah); +err_irq: + free_irq(sc->irq, sc); +err: + return ret; +} + static int ath5k_stop_locked(struct ath5k_softc *sc) { @@@ -2509,10 -2391,11 +2511,10 @@@ if (!test_bit(ATH_STAT_INVALID, sc->status)) { ath5k_led_off(sc); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); - } - ath5k_txq_cleanup(sc); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { + synchronize_irq(sc->irq); ath5k_rx_stop(sc); + ath5k_hw_dma_stop(ah); + ath5k_drain_tx_buffs(sc); ath5k_hw_phy_disable(ah); } @@@ -2520,7 -2403,7 +2522,7 @@@ } static int -ath5k_init(struct ath5k_softc *sc) +ath5k_init_hw(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; struct ath_common *common = ath5k_hw_common(ah); @@@ -2549,7 -2432,7 +2551,7 @@@ AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; - ret = ath5k_reset(sc, NULL); + ret = ath5k_reset(sc, NULL, false); if (ret) goto done; @@@ -2562,9 -2445,7 +2564,9 @@@ for (i = 0; i < common->keymax; i++) ath_hw_keyreset(common, (u16) i); - ath5k_hw_set_ack_bitrate_high(ah, true); + /* Use higher rates for acks instead of base + * rate */ + ah->ah_ack_bitrate_high = true; for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) sc->bslot[i] = NULL; @@@ -2648,34 -2529,25 +2650,34 @@@ ath5k_stop_hw(struct ath5k_softc *sc * This should be called with sc->lock. */ static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) +ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + bool skip_pcu) { struct ath5k_hw *ah = sc->ah; - int ret; + int ret, ani_mode; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); + synchronize_irq(sc->irq); stop_tasklets(sc); - if (chan) { - ath5k_txq_cleanup(sc); - ath5k_rx_stop(sc); + /* Save ani mode and disable ANI durring + * reset. If we don't we might get false + * PHY error interrupts. */ + ani_mode = ah->ah_sc->ani_state.ani_mode; + ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); + /* We are going to empty hw queues + * so we should also free any remaining + * tx buffers */ + ath5k_drain_tx_buffs(sc); + if (chan) { sc->curchan = chan; sc->curband = &sc->sbands[chan->band]; } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + skip_pcu); if (ret) { ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); goto err; @@@ -2687,12 -2559,11 +2689,12 @@@ goto err; } - ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); + ath5k_ani_init(ah, ani_mode); ah->ah_cal_next_full = jiffies; ah->ah_cal_next_ani = jiffies; ah->ah_cal_next_nf = jiffies; + ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); /* * Change channels and update the h/w rate map if we're switching; @@@ -2721,14 -2592,13 +2723,14 @@@ static void ath5k_reset_work(struct wor reset_work); mutex_lock(&sc->lock); - ath5k_reset(sc, sc->curchan); + ath5k_reset(sc, NULL, true); mutex_unlock(&sc->lock); } static int -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) +ath5k_init(struct ieee80211_hw *hw) { + struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); @@@ -2736,6 -2606,7 +2738,6 @@@ u8 mac[ETH_ALEN] = {}; int ret; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); /* * Check if the MAC has multi-rate retry support. @@@ -2772,7 -2643,7 +2774,7 @@@ /* * Allocate tx+rx descriptors and populate the lists. */ - ret = ath5k_desc_alloc(sc, pdev); + ret = ath5k_desc_alloc(sc); if (ret) { ATH5K_ERR(sc, "can't allocate descriptors\n"); goto err; @@@ -2797,46 -2668,33 +2799,46 @@@ goto err_bhal; } - /* This order matches mac80211's queue priority, so we can - * directly use the mac80211 queue number without any mapping */ - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; - } - txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); - if (IS_ERR(txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(txq); - goto err_queues; + /* 5211 and 5212 usually support 10 queues but we better rely on the + * capability information */ + if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) { + /* This order matches mac80211's queue priority, so we can + * directly use the mac80211 queue number without any mapping */ + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + hw->queues = 4; + } else { + /* older hardware (5210) can only support one data queue */ + txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); + if (IS_ERR(txq)) { + ATH5K_ERR(sc, "can't setup xmit queue\n"); + ret = PTR_ERR(txq); + goto err_queues; + } + hw->queues = 1; } - hw->queues = 4; tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); @@@ -2849,7 -2707,8 +2851,7 @@@ ret = ath5k_eeprom_read_mac(ah, mac); if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", - sc->pdev->device); + ATH5K_ERR(sc, "unable to read address from EEPROM\n"); goto err_queues; } @@@ -2884,15 -2743,15 +2886,15 @@@ err_queues err_bhal: ath5k_hw_release_tx_queue(ah, sc->bhalq); err_desc: - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); err: return ret; } -static void -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) +void +ath5k_deinit_softc(struct ath5k_softc *sc) { - struct ath5k_softc *sc = hw->priv; + struct ieee80211_hw *hw = sc->hw; /* * NB: the order of these is important: @@@ -2907,9 -2766,8 +2909,9 @@@ * XXX: ??? detach ath5k_hw ??? * Other than that, it's straightforward... */ + ath5k_debug_finish_device(sc); ieee80211_unregister_hw(hw); - ath5k_desc_free(sc, pdev); + ath5k_desc_free(sc); ath5k_txq_release(sc); ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); ath5k_unregister_leds(sc); @@@ -2920,8 -2778,6 +2922,8 @@@ * returns because we'll get called back to reclaim node * state and potentially want to use them. */ + ath5k_hw_deinit(sc->ah); + free_irq(sc->irq, sc); } /********************\ @@@ -2944,7 -2800,7 +2946,7 @@@ ath5k_tx(struct ieee80211_hw *hw, struc static int ath5k_start(struct ieee80211_hw *hw) { - return ath5k_init(hw->priv); + return ath5k_init_hw(hw->priv); } static void ath5k_stop(struct ieee80211_hw *hw) @@@ -2997,7 -2853,8 +2999,8 @@@ static int ath5k_add_interface(struct i /* Assign the vap/adhoc to a beacon xmit slot. */ if ((avf->opmode == NL80211_IFTYPE_AP) || - (avf->opmode == NL80211_IFTYPE_ADHOC)) { + (avf->opmode == NL80211_IFTYPE_ADHOC) || + (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { int slot; WARN_ON(list_empty(&sc->bcbuf)); @@@ -3016,7 -2873,7 +3019,7 @@@ sc->bslot[avf->bslot] = vif; if (avf->opmode == NL80211_IFTYPE_AP) sc->num_ap_vifs++; - else + else if (avf->opmode == NL80211_IFTYPE_ADHOC) sc->num_adhoc_vifs++; } @@@ -3352,32 -3209,14 +3355,32 @@@ static int ath5k_get_survey(struct ieee { struct ath5k_softc *sc = hw->priv; struct ieee80211_conf *conf = &hw->conf; + struct ath_common *common = ath5k_hw_common(sc->ah); + struct ath_cycle_counters *cc = &common->cc_survey; + unsigned int div = common->clockrate * 1000; - if (idx != 0) + if (idx != 0) return -ENOENT; survey->channel = conf->channel; survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = sc->ah->ah_noise_floor; + spin_lock_bh(&common->cc_lock); + ath_hw_cycle_counters_update(common); + if (cc->cycles > 0) { + survey->filled |= SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | + SURVEY_INFO_CHANNEL_TIME_TX; + survey->channel_time += cc->cycles / div; + survey->channel_time_busy += cc->rx_busy / div; + survey->channel_time_rx += cc->rx_frame / div; + survey->channel_time_tx += cc->tx_frame / div; + } + memset(cc, 0, sizeof(*cc)); + spin_unlock_bh(&common->cc_lock); + return 0; } @@@ -3559,37 -3398,7 +3562,37 @@@ static int ath5k_conf_tx(struct ieee802 return ret; } -static const struct ieee80211_ops ath5k_hw_ops = { +static int ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + if (tx_ant == 1 && rx_ant == 1) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); + else if (tx_ant == 2 && rx_ant == 2) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); + else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) + ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); + else + return -EINVAL; + return 0; +} + +static int ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ + struct ath5k_softc *sc = hw->priv; + + switch (sc->ah->ah_ant_mode) { + case AR5K_ANTMODE_FIXED_A: + *tx_ant = 1; *rx_ant = 1; break; + case AR5K_ANTMODE_FIXED_B: + *tx_ant = 2; *rx_ant = 2; break; + case AR5K_ANTMODE_DEFAULT: + *tx_ant = 3; *rx_ant = 3; break; + } + return 0; +} + +const struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, .start = ath5k_start, .stop = ath5k_stop, @@@ -3609,6 -3418,341 +3612,6 @@@ .sw_scan_start = ath5k_sw_scan_start, .sw_scan_complete = ath5k_sw_scan_complete, .set_coverage_class = ath5k_set_coverage_class, + .set_antenna = ath5k_set_antenna, + .get_antenna = ath5k_get_antenna, }; - -/********************\ -* PCI Initialization * -\********************/ - -static int __devinit -ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath5k_softc *sc; - struct ath_common *common; - struct ieee80211_hw *hw; - int ret; - u8 csz; - - /* - * L0s needs to be disabled on all ath5k cards. - * - * For distributions shipping with CONFIG_PCIEASPM (this will be enabled - * by default in the future in 2.6.36) this will also mean both L1 and - * L0s will be disabled when a pre 1.1 PCIe device is detected. We do - * know L1 works correctly even for all ath5k pre 1.1 PCIe devices - * though but cannot currently undue the effect of a blacklist, for - * details you can read pcie_aspm_sanity_check() and see how it adjusts - * the device link capability. - * - * It may be possible in the future to implement some PCI API to allow - * drivers to override blacklists for pre 1.1 PCIe but for now it is - * best to accept that both L0s and L1 will be disabled completely for - * distributions shipping with CONFIG_PCIEASPM rather than having this - * issue present. Motivation for adding this new API will be to help - * with power consumption for some of these devices. - */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device\n"); - goto err; - } - - /* XXX 32-bit addressing only */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "32-bit DMA not available\n"); - goto err_dis; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES >> 2; - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_write_config_byte(pdev, 0x41, 0); - - ret = pci_request_region(pdev, 0, "ath5k"); - if (ret) { - dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); - goto err_dis; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; - ret = -EIO; - goto err_reg; - } - - /* - * Allocate hw (mac80211 main struct) - * and hw->priv (driver private data) - */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); - ret = -ENOMEM; - goto err_map; - } - - dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - - /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, &pdev->dev); - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->extra_tx_headroom = 2; - hw->channel_change_time = 5000; - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - - /* - * Mark the device as detached to avoid processing - * interrupts until setup is complete. - */ - __set_bit(ATH_STAT_INVALID, sc->status); - - sc->iobase = mem; /* So we can unmap it on detach */ - sc->opmode = NL80211_IFTYPE_STATION; - sc->bintval = 1000; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - - /* Set private data */ - pci_set_drvdata(pdev, sc); - - /* Setup interrupt handler */ - ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_free; - } - - /* If we passed the test, malloc an ath5k_hw struct */ - sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (!sc->ah) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err_irq; - } - - sc->ah->ah_sc = sc; - sc->ah->ah_iobase = sc->iobase; - common = ath5k_hw_common(sc->ah); - common->ops = &ath5k_common_ops; - common->ah = sc->ah; - common->hw = hw; - common->cachelsz = csz << 2; /* convert to bytes */ - spin_lock_init(&common->cc_lock); - - /* Initialize device */ - ret = ath5k_hw_attach(sc); - if (ret) { - goto err_free_ah; - } - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_rates = 4; - hw->max_rate_tries = 11; - } - - hw->vif_data_size = sizeof(struct ath5k_vif); - - /* Finish private driver data initialization */ - ret = ath5k_attach(pdev, hw); - if (ret) - goto err_ah; - - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); - - if (!sc->ah->ah_single_chip) { - /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { - /* No 5GHz support -> report 2GHz radio */ - if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ - } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* Multiband radio */ - } else { - ATH5K_INFO(sc, "RF%s multiband radio found" - " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - } - } - /* Multi chip radio (RF5111 - RF2111) -> - * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); - } - } - - ath5k_debug_init_device(sc); - - /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); - - return 0; -err_ah: - ath5k_hw_detach(sc->ah); -err_free_ah: - kfree(sc->ah); -err_irq: - free_irq(pdev->irq, sc); -err_free: - ieee80211_free_hw(hw); -err_map: - pci_iounmap(pdev, mem); -err_reg: - pci_release_region(pdev, 0); -err_dis: - pci_disable_device(pdev); -err: - return ret; -} - -static void __devexit -ath5k_pci_remove(struct pci_dev *pdev) -{ - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - ath5k_debug_finish_device(sc); - ath5k_detach(pdev, sc->hw); - ath5k_hw_detach(sc->ah); - kfree(sc->ah); - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->iobase); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(sc->hw); -} - -#ifdef CONFIG_PM_SLEEP -static int ath5k_pci_suspend(struct device *dev) -{ - struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); - - ath5k_led_off(sc); - return 0; -} - -static int ath5k_pci_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct ath5k_softc *sc = pci_get_drvdata(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_write_config_byte(pdev, 0x41, 0); - - ath5k_led_enable(sc); - return 0; -} - -static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); -#define ATH5K_PM_OPS (&ath5k_pm_ops) -#else -#define ATH5K_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - -static struct pci_driver ath5k_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = ath5k_pci_id_table, - .probe = ath5k_pci_probe, - .remove = __devexit_p(ath5k_pci_remove), - .driver.pm = ATH5K_PM_OPS, -}; - -/* - * Module init/exit functions - */ -static int __init -init_ath5k_pci(void) -{ - int ret; - - ret = pci_register_driver(&ath5k_pci_driver); - if (ret) { - printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); - return ret; - } - - return 0; -} - -static void __exit -exit_ath5k_pci(void) -{ - pci_unregister_driver(&ath5k_pci_driver); -} - -module_init(init_ath5k_pci); -module_exit(exit_ath5k_pci); diff --combined drivers/net/wireless/ath/ath9k/ath9k.h index 4210a9306955,0963071e8f90..9b5501f90010 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@@ -87,19 -87,33 +87,19 @@@ struct ath_config /** * enum buffer_type - Buffer type flags * - * @BUF_HT: Send this buffer using HT capabilities * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) * @BUF_AGGR: Indicates whether the buffer can be aggregated * (used in aggregation scheduling) - * @BUF_RETRY: Indicates whether the buffer is retried * @BUF_XRETRY: To denote excessive retries of the buffer */ enum buffer_type { - BUF_HT = BIT(1), BUF_AMPDU = BIT(2), BUF_AGGR = BIT(3), - BUF_RETRY = BIT(4), BUF_XRETRY = BIT(5), }; -#define bf_nframes bf_state.bfs_nframes -#define bf_al bf_state.bfs_al -#define bf_frmlen bf_state.bfs_frmlen -#define bf_retries bf_state.bfs_retries -#define bf_seqno bf_state.bfs_seqno -#define bf_tidno bf_state.bfs_tidno -#define bf_keyix bf_state.bfs_keyix -#define bf_keytype bf_state.bfs_keytype -#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) -#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) #define ATH_TXSTATUS_RING_SIZE 64 @@@ -164,8 -178,8 +164,8 @@@ void ath_descdma_cleanup(struct ath_sof /* returns delimiter padding required given the packet length */ #define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) + (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ + DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ)) #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) @@@ -182,6 -196,7 +182,6 @@@ enum ATH_AGGR_STATUS #define ATH_TXFIFO_DEPTH 8 struct ath_txq { - int axq_class; u32 axq_qnum; u32 *axq_link; struct list_head axq_q; @@@ -194,28 -209,27 +194,28 @@@ struct list_head txq_fifo_pending; u8 txq_headidx; u8 txq_tailidx; + int pending_frames; }; struct ath_atx_ac { + struct ath_txq *txq; int sched; - int qnum; struct list_head list; struct list_head tid_q; }; +struct ath_frame_info { + int framelen; + u32 keyix; + enum ath9k_key_type keytype; + u8 retries; + u16 seqno; +}; + struct ath_buf_state { - int bfs_nframes; - u16 bfs_al; - u16 bfs_frmlen; - int bfs_seqno; - int bfs_tidno; - int bfs_retries; u8 bf_type; u8 bfs_paprd; - unsigned long bfs_paprd_timestamp; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; + enum ath9k_internal_frame_type bfs_ftype; }; struct ath_buf { @@@ -228,6 -242,7 +228,6 @@@ dma_addr_t bf_daddr; /* physical addr of desc */ dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ bool bf_stale; - bool bf_tx_aborted; u16 bf_flags; struct ath_buf_state bf_state; struct ath_wiphy *aphy; @@@ -256,6 -271,7 +256,6 @@@ struct ath_node struct ath_atx_ac ac[WME_NUM_AC]; u16 maxampdu; u8 mpdudensity; - int last_rssi; }; #define AGGR_CLEANUP BIT(1) @@@ -264,7 -280,6 +264,7 @@@ struct ath_tx_control { struct ath_txq *txq; + struct ath_node *an; int if_id; enum ath9k_internal_frame_type frame_type; u8 paprd; @@@ -277,11 -292,12 +277,11 @@@ struct ath_tx { u16 seq_no; u32 txqsetup; - int hwq_map[WME_NUM_AC]; spinlock_t txbuflock; struct list_head txbuf; struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; struct ath_descdma txdma; - int pending_frames[WME_NUM_AC]; + struct ath_txq *txq_map[WME_NUM_AC]; }; struct ath_rx_edma { @@@ -295,6 -311,7 +295,6 @@@ struct ath_rx u8 rxotherant; u32 *rxlink; unsigned int rxfilter; - spinlock_t pcu_lock; spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; @@@ -311,7 -328,8 +311,7 @@@ void ath_rx_cleanup(struct ath_softc *s int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); - void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); -int ath_tx_setup(struct ath_softc *sc, int haltype); + bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx); void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); @@@ -325,6 -343,7 +325,6 @@@ int ath_tx_start(struct ieee80211_hw *h struct ath_tx_control *txctl); void ath_tx_tasklet(struct ath_softc *sc); void ath_tx_edma_tasklet(struct ath_softc *sc); -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, u16 *ssn); void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); @@@ -545,7 -564,6 +545,7 @@@ struct ath_ant_comb #define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_SCAN BIT(13) #define SC_OP_ANI_RUN BIT(14) +#define SC_OP_ENABLE_APM BIT(15) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@@ -583,14 -601,13 +583,14 @@@ struct ath_softc struct ath_hw *sc_ah; void __iomem *mem; int irq; - spinlock_t sc_resetlock; spinlock_t sc_serial_rw; spinlock_t sc_pm_lock; + spinlock_t sc_pcu_lock; struct mutex mutex; struct work_struct paprd_work; struct work_struct hw_check_work; struct completion paprd_complete; + bool paprd_pending; u32 intrstatus; u32 sc_flags; /* SC_OP_* */ @@@ -648,11 -665,11 +648,11 @@@ struct ath_wiphy bool idle; int chan_idx; int chan_is_ht; + int last_rssi; }; void ath9k_tasklet(unsigned long data); int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); static inline void ath_read_cachesize(struct ath_common *common, int *csz) @@@ -698,12 -715,10 +698,12 @@@ static inline void ath_ahb_exit(void) { void ath9k_ps_wakeup(struct ath_softc *sc); void ath9k_ps_restore(struct ath_softc *sc); +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); + void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int ath9k_wiphy_add(struct ath_softc *sc); int ath9k_wiphy_del(struct ath_wiphy *aphy); -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); +void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype); int ath9k_wiphy_pause(struct ath_wiphy *aphy); int ath9k_wiphy_unpause(struct ath_wiphy *aphy); int ath9k_wiphy_select(struct ath_wiphy *aphy); diff --combined drivers/net/wireless/ath/ath9k/eeprom_def.c index c2b4bba7410c,a3ccb1b9638d..5bfa031545f4 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@@ -96,8 -96,8 +96,8 @@@ static bool ath9k_hw_def_fill_eeprom(st for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, eep_data)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "Unable to read eeprom region\n"); + ath_err(ath9k_hw_common(ah), + "Unable to read eeprom region\n"); return false; } eep_data++; @@@ -117,13 -117,13 +117,13 @@@ static int ath9k_hw_def_check_eeprom(st int i, addr, size; if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n"); + ath_err(common, "Reading Magic # failed\n"); return false; } if (!ath9k_hw_use_flash(ah)) { - ath_print(common, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); + ath_dbg(common, ATH_DBG_EEPROM, + "Read Magic = 0x%04X\n", magic); if (magic != AR5416_EEPROM_MAGIC) { magic2 = swab16(magic); @@@ -139,15 -139,16 +139,15 @@@ eepdata++; } } else { - ath_print(common, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "Endianness mismatch.\n"); + ath_err(common, + "Invalid EEPROM Magic. Endianness mismatch.\n"); return -EINVAL; } } } - ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); + ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", + need_swap ? "True" : "False"); if (need_swap) el = swab16(ah->eeprom.def.baseEepHeader.length); @@@ -168,8 -169,8 +168,8 @@@ u32 integer, j; u16 word; - ath_print(common, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing.\n"); + ath_dbg(common, ATH_DBG_EEPROM, + "EEPROM Endianness is not native.. Changing.\n"); word = swab16(eep->baseEepHeader.length); eep->baseEepHeader.length = word; @@@ -215,7 -216,8 +215,7 @@@ if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - ath_print(common, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", + ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", sum, ah->eep_ops->get_eeprom_ver(ah)); return -EINVAL; } @@@ -964,19 -966,20 +964,19 @@@ static void ath9k_hw_set_def_power_cal_ ((pdadcValues[4 * j + 3] & 0xFF) << 24); REG_WRITE(ah, regOffset, reg32); - ath_print(common, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - ath_print(common, ATH_DBG_EEPROM, - "PDADC: Chain %d | PDADC %3d " - "Value %3d | PDADC %3d Value %3d | " - "PDADC %3d Value %3d | PDADC %3d " - "Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, pdadcValues[4 * j + 1], - 4 * j + 2, pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); + ath_dbg(common, ATH_DBG_EEPROM, + "PDADC (%d,%4x): %4.4x %8.8x\n", + i, regChainOffset, regOffset, + reg32); + ath_dbg(common, ATH_DBG_EEPROM, + "PDADC: Chain %d | PDADC %3d " + "Value %3d | PDADC %3d Value %3d | " + "PDADC %3d Value %3d | PDADC %3d " + "Value %3d |\n", + i, 4 * j, pdadcValues[4 * j], + 4 * j + 1, pdadcValues[4 * j + 1], + 4 * j + 2, pdadcValues[4 * j + 2], + 4 * j + 3, pdadcValues[4 * j + 3]); regOffset += 4; } @@@ -1019,16 -1022,13 +1019,16 @@@ static void ath9k_hw_set_def_power_per_ 0, {0, 0, 0, 0} }; u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = - { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; + static const u16 ctlModesFor11a[] = { + CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 + }; + static const u16 ctlModesFor11g[] = { + CTL_11B, CTL_11G, CTL_2GHT20, + CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 + }; + u16 numCtlModes; + const u16 *pCtlMode; + u16 ctlMode, freq; struct chan_centers centers; int tx_chainmask; u16 twiceMinEdgePower; @@@ -1063,15 -1063,19 +1063,19 @@@ case 1: break; case 2: - scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) + scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; + else + scaledPower = 0; break; case 3: - scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; + if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) + scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; + else + scaledPower = 0; break; } - scaledPower = max((u16)0, scaledPower); - if (IS_CHAN_2GHZ(chan)) { numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; @@@ -1259,7 -1263,7 +1263,7 @@@ static void ath9k_hw_def_set_txpower(st u16 cfgCtl, u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, - u8 powerLimit) + u8 powerLimit, bool test) { #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); @@@ -1286,44 -1290,12 +1290,44 @@@ ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); + regulatory->max_power_level = 0; for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); if (ratesArray[i] > AR5416_MAX_RATE_POWER) ratesArray[i] = AR5416_MAX_RATE_POWER; + if (ratesArray[i] > regulatory->max_power_level) + regulatory->max_power_level = ratesArray[i]; + } + + if (!test) { + i = rate6mb; + + if (IS_CHAN_HT40(chan)) + i = rateHt40_0; + else if (IS_CHAN_HT20(chan)) + i = rateHt20_0; + + regulatory->max_power_level = ratesArray[i]; + } + + switch(ar5416_get_ntxchains(ah->txchainmask)) { + case 1: + break; + case 2: + regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; + break; + case 3: + regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; + break; + default: + ath_dbg(ath9k_hw_common(ah), ATH_DBG_EEPROM, + "Invalid chainmask configuration\n"); + break; } + if (test) + return; + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) { int8_t pwr_table_offset; @@@ -1420,6 -1392,34 +1424,6 @@@ REG_WRITE(ah, AR_PHY_POWER_TX_SUB, ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_20_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; - - switch(ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } } static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, @@@ -1458,17 -1458,17 +1462,17 @@@ static u16 ath9k_hw_def_get_spur_channe u16 spur_val = AR_NO_SPUR; - ath_print(common, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur idx:%d is2Ghz:%d val:%x\n", + i, is2GHz, ah->config.spurchans[i][is2GHz]); switch (ah->config.spurmode) { case SPUR_DISABLE: break; case SPUR_ENABLE_IOCTL: spur_val = ah->config.spurchans[i][is2GHz]; - ath_print(common, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); + ath_dbg(common, ATH_DBG_ANI, + "Getting spur val from new loc. %d\n", spur_val); break; case SPUR_ENABLE_EEPROM: spur_val = EEP_DEF_SPURCHAN; diff --combined drivers/net/wireless/ath/ath9k/hif_usb.c index 45d4b2403a52,0de3c3d3c245..d0918bd23b8e --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@@ -28,7 -28,10 +28,7 @@@ MODULE_FIRMWARE(FIRMWARE_AR9271) static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ - { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ - { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ @@@ -37,20 -40,9 +37,20 @@@ { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */ { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ - { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ - { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */ + + { USB_DEVICE(0x0cf3, 0x7015), + .driver_info = AR9287_USB }, /* Atheros */ + { USB_DEVICE(0x1668, 0x1200), + .driver_info = AR9287_USB }, /* Verizon */ + + { USB_DEVICE(0x0cf3, 0x7010), + .driver_info = AR9280_USB }, /* Atheros */ + { USB_DEVICE(0x0846, 0x9018), + .driver_info = AR9280_USB }, /* Netgear WNDA3200 */ + { USB_DEVICE(0x083A, 0xA704), + .driver_info = AR9280_USB }, /* SMC Networks */ + { }, }; @@@ -361,9 -353,9 +361,9 @@@ static void ath9k_hif_usb_rx_stream(str struct sk_buff *skb) { struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; - int index = 0, i = 0, chk_idx, len = skb->len; - int rx_remain_len = 0, rx_pkt_len = 0; - u16 pkt_len, pkt_tag, pool_index = 0; + int index = 0, i = 0, len = skb->len; + int rx_remain_len, rx_pkt_len; + u16 pool_index = 0; u8 *ptr; spin_lock(&hif_dev->rx_lock); @@@ -397,64 -389,64 +397,64 @@@ spin_unlock(&hif_dev->rx_lock); while (index < len) { + u16 pkt_len; + u16 pkt_tag; + u16 pad_len; + int chk_idx; + ptr = (u8 *) skb->data; pkt_len = ptr[index] + (ptr[index+1] << 8); pkt_tag = ptr[index+2] + (ptr[index+3] << 8); - if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { - u16 pad_len; - - pad_len = 4 - (pkt_len & 0x3); - if (pad_len == 4) - pad_len = 0; - - chk_idx = index; - index = index + 4 + pkt_len + pad_len; - - if (index > MAX_RX_BUF_SIZE) { - spin_lock(&hif_dev->rx_lock); - hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; - hif_dev->rx_transfer_len = - MAX_RX_BUF_SIZE - chk_idx - 4; - hif_dev->rx_pad_len = pad_len; - - nskb = __dev_alloc_skb(pkt_len + 32, - GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - spin_unlock(&hif_dev->rx_lock); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), - hif_dev->rx_transfer_len); - - /* Record the buffer pointer */ - hif_dev->remain_skb = nskb; + if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { + RX_STAT_INC(skb_dropped); + return; + } + + pad_len = 4 - (pkt_len & 0x3); + if (pad_len == 4) + pad_len = 0; + + chk_idx = index; + index = index + 4 + pkt_len + pad_len; + + if (index > MAX_RX_BUF_SIZE) { + spin_lock(&hif_dev->rx_lock); + hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; + hif_dev->rx_transfer_len = + MAX_RX_BUF_SIZE - chk_idx - 4; + hif_dev->rx_pad_len = pad_len; + + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); spin_unlock(&hif_dev->rx_lock); - } else { - nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); - if (!nskb) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: RX memory allocation" - " error\n"); - goto err; - } - skb_reserve(nskb, 32); - RX_STAT_INC(skb_allocated); - - memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); - skb_put(nskb, pkt_len); - skb_pool[pool_index++] = nskb; + goto err; } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), + hif_dev->rx_transfer_len); + + /* Record the buffer pointer */ + hif_dev->remain_skb = nskb; + spin_unlock(&hif_dev->rx_lock); } else { - RX_STAT_INC(skb_dropped); - return; + nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); + if (!nskb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: RX memory allocation error\n"); + goto err; + } + skb_reserve(nskb, 32); + RX_STAT_INC(skb_allocated); + + memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); + skb_put(nskb, pkt_len); + skb_pool[pool_index++] = nskb; } } @@@ -469,7 -461,7 +469,7 @@@ err static void ath9k_hif_usb_rx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *) urb->context; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@@ -516,7 -508,7 +516,7 @@@ static void ath9k_hif_usb_reg_in_cb(str { struct sk_buff *skb = (struct sk_buff *) urb->context; struct sk_buff *nskb; - struct hif_device_usb *hif_dev = (struct hif_device_usb *) + struct hif_device_usb *hif_dev = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); int ret; @@@ -784,8 -776,7 +784,8 @@@ static void ath9k_hif_usb_dealloc_urbs( ath9k_hif_usb_dealloc_rx_urbs(hif_dev); } -static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev, + u32 drv_info) { int transfer, err; const void *data = hif_dev->firmware->data; @@@ -816,10 -807,18 +816,10 @@@ } kfree(buf); - switch (hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(drv_info)) firm_offset = AR7010_FIRMWARE_TEXT; - break; - default: + else firm_offset = AR9271_FIRMWARE_TEXT; - break; - } /* * Issue FW download complete command to firmware. @@@ -837,7 -836,7 +837,7 @@@ return 0; } -static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) +static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) { int ret, idx; struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; @@@ -853,7 -852,7 +853,7 @@@ } /* Download firmware */ - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, drv_info); if (ret) { dev_err(&hif_dev->udev->dev, "ath9k_htc: Firmware - %s download failed\n", @@@ -885,9 -884,9 +885,9 @@@ return 0; -err_fw_download: - ath9k_hif_usb_dealloc_urbs(hif_dev); err_urb: + ath9k_hif_usb_dealloc_urbs(hif_dev); +err_fw_download: release_firmware(hif_dev->firmware); err_fw_req: hif_dev->firmware = NULL; @@@ -932,15 -931,23 +932,15 @@@ static int ath9k_hif_usb_probe(struct u /* Find out which firmware to load */ - switch(hif_dev->device_id) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(id->driver_info)) if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) hif_dev->fw_name = FIRMWARE_AR7010_1_1; else hif_dev->fw_name = FIRMWARE_AR7010; - break; - default: + else hif_dev->fw_name = FIRMWARE_AR9271; - break; - } - ret = ath9k_hif_usb_dev_init(hif_dev); + ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info); if (ret) { ret = -EINVAL; goto err_hif_init_usb; @@@ -948,7 -955,7 +948,7 @@@ ret = ath9k_htc_hw_init(hif_dev->htc_handle, &hif_dev->udev->dev, hif_dev->device_id, - hif_dev->udev->product); + hif_dev->udev->product, id->driver_info); if (ret) { ret = -EINVAL; goto err_htc_hw_init; @@@ -991,7 -998,8 +991,7 @@@ static void ath9k_hif_usb_reboot(struc static void ath9k_hif_usb_disconnect(struct usb_interface *interface) { struct usb_device *udev = interface_to_usbdev(interface); - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); if (hif_dev) { ath9k_htc_hw_deinit(hif_dev->htc_handle, @@@ -1013,8 -1021,16 +1013,15 @@@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, pm_message_t message) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); + /* + * The device has to be set to FULLSLEEP mode in case no + * interface is up. + */ + if (!(hif_dev->flags & HIF_USB_START)) + ath9k_htc_suspend(hif_dev->htc_handle); + ath9k_hif_usb_dealloc_urbs(hif_dev); return 0; @@@ -1022,8 -1038,8 +1029,8 @@@ static int ath9k_hif_usb_resume(struct usb_interface *interface) { - struct hif_device_usb *hif_dev = - (struct hif_device_usb *) usb_get_intfdata(interface); + struct hif_device_usb *hif_dev = usb_get_intfdata(interface); + struct htc_target *htc_handle = hif_dev->htc_handle; int ret; ret = ath9k_hif_usb_alloc_urbs(hif_dev); @@@ -1031,8 -1047,7 +1038,8 @@@ return ret; if (hif_dev->firmware) { - ret = ath9k_hif_usb_download_fw(hif_dev); + ret = ath9k_hif_usb_download_fw(hif_dev, + htc_handle->drv_priv->ah->hw_version.usbdev); if (ret) goto fail_resume; } else { @@@ -1042,7 -1057,7 +1049,7 @@@ mdelay(100); - ret = ath9k_htc_resume(hif_dev->htc_handle); + ret = ath9k_htc_resume(htc_handle); if (ret) goto fail_resume; diff --combined drivers/net/wireless/ath/ath9k/htc.h index afe39a911906,c3b561daa6c1..fdf9d5fe8cc0 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@@ -368,7 -368,7 +368,7 @@@ struct ath9k_htc_priv u16 seq_no; u32 bmiss_cnt; - struct ath9k_hw_cal_data caldata[38]; + struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS]; spinlock_t beacon_lock; @@@ -455,15 -455,18 +455,18 @@@ u32 ath9k_htc_calcrxfilter(struct ath9k void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); void ath9k_ps_work(struct work_struct *work); + bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, + enum ath9k_power_mode mode); void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); void ath9k_init_leds(struct ath9k_htc_priv *priv); void ath9k_deinit_leds(struct ath9k_htc_priv *priv); int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product); + u16 devid, char *product, u32 drv_info); void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); #ifdef CONFIG_PM + void ath9k_htc_suspend(struct htc_target *htc_handle); int ath9k_htc_resume(struct htc_target *htc_handle); #endif #ifdef CONFIG_ATH9K_HTC_DEBUGFS diff --combined drivers/net/wireless/ath/ath9k/htc_drv_init.c index 93f3f615218b,8776f49ffd41..0f6be350fd3c --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@@ -181,8 -181,7 +181,8 @@@ static inline int ath9k_htc_connect_svc return htc_connect_service(priv->htc, &req, ep_id); } -static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) +static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, + u32 drv_info) { int ret; @@@ -246,10 -245,17 +246,10 @@@ * the HIF layer, shouldn't matter much. */ - switch(devid) { - case 0x7010: - case 0x7015: - case 0x9018: - case 0xA704: - case 0x1200: + if (IS_AR7010_DEVICE(drv_info)) priv->htc->credits = 45; - break; - default: + else priv->htc->credits = 33; - } ret = htc_init(priv->htc); if (ret) @@@ -288,9 -294,9 +288,9 @@@ static unsigned int ath9k_regread(void (u8 *) &val, sizeof(val), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER READ FAILED: (0x%04x, %d)\n", - reg_offset, r); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER READ FAILED: (0x%04x, %d)\n", + reg_offset, r); return -EIO; } @@@ -302,7 -308,7 +302,7 @@@ static void ath9k_regwrite_single(void struct ath_hw *ah = (struct ath_hw *) hw_priv; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; - __be32 buf[2] = { + const __be32 buf[2] = { cpu_to_be32(reg_offset), cpu_to_be32(val), }; @@@ -313,9 -319,9 +313,9 @@@ (u8 *) &val, sizeof(val), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED:(0x%04x, %d)\n", - reg_offset, r); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED:(0x%04x, %d)\n", + reg_offset, r); } } @@@ -345,9 -351,9 +345,9 @@@ static void ath9k_regwrite_buffer(void (u8 *) &rsp_status, sizeof(rsp_status), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED, multi len: %d\n", - priv->wmi->multi_write_idx); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); } priv->wmi->multi_write_idx = 0; } @@@ -395,9 -401,9 +395,9 @@@ static void ath9k_regwrite_flush(void * (u8 *) &rsp_status, sizeof(rsp_status), 100); if (unlikely(r)) { - ath_print(common, ATH_DBG_WMI, - "REGISTER WRITE FAILED, multi len: %d\n", - priv->wmi->multi_write_idx); + ath_dbg(common, ATH_DBG_WMI, + "REGISTER WRITE FAILED, multi len: %d\n", + priv->wmi->multi_write_idx); } priv->wmi->multi_write_idx = 0; } @@@ -469,9 -475,9 +469,9 @@@ static void setup_ht_cap(struct ath9k_h tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); - ath_print(common, ATH_DBG_CONFIG, - "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); + ath_dbg(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); if (tx_streams != rx_streams) { ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; @@@ -495,31 -501,37 +495,31 @@@ static int ath9k_init_queues(struct ath priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); if (priv->beaconq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup BEACON xmit queue\n"); + ath_err(common, "Unable to setup BEACON xmit queue\n"); goto err; } priv->cabq = ath9k_htc_cabq_setup(priv); if (priv->cabq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); + ath_err(common, "Unable to setup CAB xmit queue\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); + ath_err(common, "Unable to setup xmit queue for BE traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); + ath_err(common, "Unable to setup xmit queue for BK traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); + ath_err(common, "Unable to setup xmit queue for VI traffic\n"); goto err; } if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); + ath_err(common, "Unable to setup xmit queue for VO traffic\n"); goto err; } @@@ -537,9 -549,9 +537,9 @@@ static void ath9k_init_crypto(struct at /* Get the hardware key cache size. */ common->keymax = priv->ah->caps.keycache_size; if (common->keymax > ATH_KEYMAX) { - ath_print(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); + ath_dbg(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); common->keymax = ATH_KEYMAX; } @@@ -615,8 -627,7 +615,8 @@@ static void ath9k_init_btcoex(struct at } static int ath9k_init_priv(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, + u32 drv_info) { struct ath_hw *ah = NULL; struct ath_common *common; @@@ -630,8 -641,6 +630,8 @@@ ah->hw_version.devid = devid; ah->hw_version.subsysid = 0; /* FIXME */ + ah->hw_version.usbdev = drv_info; + ah->ah_flags |= AH_USE_EEPROM; priv->ah = ah; common = ath9k_hw_common(ah); @@@ -664,15 -673,16 +664,15 @@@ ret = ath9k_hw_init(ah); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", ret); + ath_err(common, + "Unable to initialize hardware; initialization status: %d\n", + ret); goto err_hw; } ret = ath9k_htc_init_debug(ah); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); + ath_err(common, "Unable to create debugfs files\n"); goto err_debug; } @@@ -714,8 -724,7 +714,8 @@@ static void ath9k_set_hw_capab(struct a IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_NEED_DTIM_PERIOD; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | @@@ -753,7 -762,7 +753,7 @@@ } static int ath9k_init_device(struct ath9k_htc_priv *priv, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw = priv->hw; struct ath_common *common; @@@ -762,7 -771,7 +762,7 @@@ struct ath_regulatory *reg; /* Bring up device */ - error = ath9k_init_priv(priv, devid, product); + error = ath9k_init_priv(priv, devid, product, drv_info); if (error != 0) goto err_init; @@@ -820,7 -829,7 +820,7 @@@ err_init } int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, - u16 devid, char *product) + u16 devid, char *product, u32 drv_info) { struct ieee80211_hw *hw; struct ath9k_htc_priv *priv; @@@ -847,14 -856,14 +847,14 @@@ goto err_free; } - ret = ath9k_init_htc_services(priv, devid); + ret = ath9k_init_htc_services(priv, devid, drv_info); if (ret) goto err_init; /* The device may have been unplugged earlier. */ priv->op_flags &= ~OP_UNPLUGGED; - ret = ath9k_init_device(priv, devid, product); + ret = ath9k_init_device(priv, devid, product, drv_info); if (ret) goto err_init; @@@ -882,17 -891,22 +882,23 @@@ void ath9k_htc_disconnect_device(struc } #ifdef CONFIG_PM + + void ath9k_htc_suspend(struct htc_target *htc_handle) + { + ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP); + } + int ath9k_htc_resume(struct htc_target *htc_handle) { + struct ath9k_htc_priv *priv = htc_handle->drv_priv; int ret; - ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); + ret = ath9k_htc_wait_for_target(priv); if (ret) return ret; - ret = ath9k_init_htc_services(htc_handle->drv_priv, - htc_handle->drv_priv->ah->hw_version.devid); + ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, + priv->ah->hw_version.usbdev); return ret; } #endif diff --combined drivers/net/wireless/ath/ath9k/htc_drv_main.c index fe82e5e30d82,51977caca47f..20ea75a44e52 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@@ -29,7 -29,7 +29,7 @@@ static void ath_update_txpow(struct ath struct ath_hw *ah = priv->ah; if (priv->curtxpow != priv->txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); + ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); /* read back in case value is clamped */ priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@@ -63,8 -63,8 +63,8 @@@ static enum htc_phymode ath9k_htc_get_c return mode; } - static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, - enum ath9k_power_mode mode) + bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, + enum ath9k_power_mode mode) { bool ret; @@@ -143,18 -143,18 +143,18 @@@ static int ath9k_htc_set_channel(struc WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); - ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", - priv->ah->curchan->channel, - channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), - fastcc); + ath_dbg(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", + priv->ah->curchan->channel, + channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), + fastcc); caldata = &priv->caldata[channel->hw_value]; ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %d\n", channel->center_freq, ret); + ath_err(common, + "Unable to reset channel (%u Mhz) reset status %d\n", + channel->center_freq, ret); goto err; } @@@ -263,16 -263,15 +263,16 @@@ static int ath9k_htc_add_station(struc WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); if (ret) { if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to add station entry for: %pM\n", sta->addr); + ath_err(common, + "Unable to add station entry for: %pM\n", + sta->addr); return ret; } if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Added a station entry for: %pM (idx: %d)\n", - sta->addr, tsta.sta_index); + ath_dbg(common, ATH_DBG_CONFIG, + "Added a station entry for: %pM (idx: %d)\n", + sta->addr, tsta.sta_index); priv->nstations++; return 0; @@@ -297,16 -296,16 +297,16 @@@ static int ath9k_htc_remove_station(str WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); if (ret) { if (sta) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove station entry for: %pM\n", - sta->addr); + ath_err(common, + "Unable to remove station entry for: %pM\n", + sta->addr); return ret; } if (sta) - ath_print(common, ATH_DBG_CONFIG, - "Removed a station entry for: %pM (idx: %d)\n", - sta->addr, sta_idx); + ath_dbg(common, ATH_DBG_CONFIG, + "Removed a station entry for: %pM (idx: %d)\n", + sta->addr, sta_idx); priv->nstations--; return 0; @@@ -391,8 -390,8 +391,8 @@@ static int ath9k_htc_send_rate_cmd(stru WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize Rate information on target\n"); + ath_err(common, + "Unable to initialize Rate information on target\n"); } return ret; @@@ -409,9 -408,9 +409,9 @@@ static void ath9k_htc_init_rate(struct ath9k_htc_setup_rate(priv, sta, &trate); ret = ath9k_htc_send_rate_cmd(priv, &trate); if (!ret) - ath_print(common, ATH_DBG_CONFIG, - "Updated target sta: %pM, rate caps: 0x%X\n", - sta->addr, be32_to_cpu(trate.capflags)); + ath_dbg(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + sta->addr, be32_to_cpu(trate.capflags)); } static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, @@@ -436,9 -435,9 +436,9 @@@ ret = ath9k_htc_send_rate_cmd(priv, &trate); if (!ret) - ath_print(common, ATH_DBG_CONFIG, - "Updated target sta: %pM, rate caps: 0x%X\n", - bss_conf->bssid, be32_to_cpu(trate.capflags)); + ath_dbg(common, ATH_DBG_CONFIG, + "Updated target sta: %pM, rate caps: 0x%X\n", + bss_conf->bssid, be32_to_cpu(trate.capflags)); } static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, @@@ -465,14 -464,14 +465,14 @@@ WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); if (ret) - ath_print(common, ATH_DBG_CONFIG, - "Unable to %s TX aggregation for (%pM, %d)\n", - (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); + ath_dbg(common, ATH_DBG_CONFIG, + "Unable to %s TX aggregation for (%pM, %d)\n", + (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); else - ath_print(common, ATH_DBG_CONFIG, - "%s TX aggregation for (%pM, %d)\n", - (aggr.aggr_enable) ? "Starting" : "Stopping", - sta->addr, tid); + ath_dbg(common, ATH_DBG_CONFIG, + "%s TX aggregation for (%pM, %d)\n", + (aggr.aggr_enable) ? "Starting" : "Stopping", + sta->addr, tid); spin_lock_bh(&priv->tx_lock); ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; @@@ -725,7 -724,7 +725,7 @@@ void ath9k_ani_work(struct work_struct /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { longcal = true; - ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@@ -734,8 -733,8 +734,8 @@@ if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - ath_print(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@@ -896,8 -895,8 +896,8 @@@ static int ath9k_register_led(struct at ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); if (ret) - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Failed to register led:%s", led->name); + ath_err(ath9k_hw_common(priv->ah), + "Failed to register led:%s", led->name); else led->registered = 1; @@@ -1025,9 -1024,9 +1025,9 @@@ static void ath9k_htc_radio_enable(stru /* Reset the HW */ ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, ah->curchan->channel); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, ah->curchan->channel); } ath_update_txpow(priv); @@@ -1088,9 -1087,9 +1088,9 @@@ static void ath9k_htc_radio_disable(str /* Reset the HW */ ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, ah->curchan->channel); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, ah->curchan->channel); } /* Disable the PHY */ @@@ -1125,15 -1124,15 +1125,15 @@@ static int ath9k_htc_tx(struct ieee8021 ret = ath9k_htc_tx_start(priv, skb); if (ret != 0) { if (ret == -ENOMEM) { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Stopping TX queues\n"); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Stopping TX queues\n"); ieee80211_stop_queues(hw); spin_lock_bh(&priv->tx_lock); priv->tx_queues_stop = true; spin_unlock_bh(&priv->tx_lock); } else { - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, - "Tx failed"); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, + "Tx failed\n"); } goto fail_tx; } @@@ -1159,9 -1158,9 +1159,9 @@@ static int ath9k_htc_start(struct ieee8 mutex_lock(&priv->mutex); - ath_print(common, ATH_DBG_CONFIG, - "Starting driver with initial channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); /* Ensure that HW is awake before flushing RX */ ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); @@@ -1176,9 -1175,9 +1176,9 @@@ ath9k_hw_htc_resetinit(ah); ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (ret) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", ret, curchan->center_freq); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + ret, curchan->center_freq); mutex_unlock(&priv->mutex); return ret; } @@@ -1224,7 -1223,7 +1224,7 @@@ static void ath9k_htc_stop(struct ieee8 mutex_lock(&priv->mutex); if (priv->op_flags & OP_INVALID) { - ath_print(common, ATH_DBG_ANY, "Device not present\n"); + ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&priv->mutex); return; } @@@ -1244,10 -1243,11 +1244,10 @@@ /* Remove monitor interface here */ if (ah->opmode == NL80211_IFTYPE_MONITOR) { if (ath9k_htc_remove_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Unable to remove monitor interface\n"); + ath_err(common, "Unable to remove monitor interface\n"); else - ath_print(common, ATH_DBG_CONFIG, - "Monitor interface removed\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor interface removed\n"); } if (ah->btcoex_hw.enabled) { @@@ -1264,7 -1264,7 +1264,7 @@@ priv->op_flags |= OP_INVALID; - ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); mutex_unlock(&priv->mutex); } @@@ -1298,14 -1298,14 +1298,14 @@@ static int ath9k_htc_add_interface(stru hvif.opmode = cpu_to_be32(HTC_M_IBSS); break; default: - ath_print(common, ATH_DBG_FATAL, + ath_err(common, "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } - ath_print(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", vif->type); + ath_dbg(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", vif->type); priv->ah->opmode = vif->type; @@@ -1328,8 -1328,8 +1328,8 @@@ ret = ath9k_htc_update_cap_target(priv); if (ret) - ath_print(common, ATH_DBG_CONFIG, "Failed to update" - " capability in target \n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Failed to update capability in target\n"); priv->vif = vif; out: @@@ -1349,7 -1349,7 +1349,7 @@@ static void ath9k_htc_remove_interface( int ret = 0; u8 cmd_rsp; - ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); @@@ -1386,8 -1386,8 +1386,8 @@@ static int ath9k_htc_config(struct ieee mutex_unlock(&priv->htc_pm_lock); if (enable_radio) { - ath_print(common, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); ath9k_htc_radio_enable(hw); } @@@ -1397,21 -1397,19 +1397,21 @@@ struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; - ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); - ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); + ath9k_cmn_update_ichannel(&priv->ah->channels[pos], + hw->conf.channel, + hw->conf.channel_type); if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to set channel\n"); + ath_err(common, "Unable to set channel\n"); mutex_unlock(&priv->mutex); return -EINVAL; } } + if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); @@@ -1423,18 -1421,14 +1423,18 @@@ } } + if (changed & IEEE80211_CONF_CHANGE_POWER) { + priv->txpowlimit = 2 * conf->power_level; + ath_update_txpow(priv); + } + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (conf->flags & IEEE80211_CONF_MONITOR) { if (ath9k_htc_add_monitor_interface(priv)) - ath_print(common, ATH_DBG_FATAL, - "Failed to set monitor mode\n"); + ath_err(common, "Failed to set monitor mode\n"); else - ath_print(common, ATH_DBG_CONFIG, - "HW opmode set to Monitor mode\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "HW opmode set to Monitor mode\n"); } } @@@ -1446,8 -1440,8 +1446,8 @@@ } mutex_unlock(&priv->htc_pm_lock); - ath_print(common, ATH_DBG_CONFIG, - "idle: disabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "idle: disabling radio\n"); ath9k_htc_radio_disable(hw); } @@@ -1484,8 -1478,8 +1484,8 @@@ static void ath9k_htc_configure_filter( rfilt = ath9k_htc_calcrxfilter(priv); ath9k_hw_setrxfilter(priv->ah, rfilt); - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, - "Set HW RX filter: 0x%x\n", rfilt); + ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); @@@ -1548,14 -1542,15 +1548,14 @@@ static int ath9k_htc_conf_tx(struct iee qnum = get_hw_qnum(queue, priv->hwq_map); - ath_print(common, ATH_DBG_CONFIG, - "Configure tx [queue/hwq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); + ath_dbg(common, ATH_DBG_CONFIG, + "Configure tx [queue/hwq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); ret = ath_htc_txq_update(priv, qnum, &qi); if (ret) { - ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + ath_err(common, "TXQ Update failed\n"); goto out; } @@@ -1583,7 -1578,7 +1583,7 @@@ static int ath9k_htc_set_key(struct iee return -ENOSPC; mutex_lock(&priv->mutex); - ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); ath9k_htc_ps_wakeup(priv); switch (cmd) { @@@ -1629,7 -1624,7 +1629,7 @@@ static void ath9k_htc_bss_info_changed( if (changed & BSS_CHANGED_ASSOC) { common->curaid = bss_conf->assoc ? bss_conf->aid : 0; - ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); if (bss_conf->assoc) { @@@ -1646,9 -1641,9 +1646,9 @@@ memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); ath9k_hw_write_associd(ah); - ath_print(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath_dbg(common, ATH_DBG_CONFIG, + "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); } if ((changed & BSS_CHANGED_BEACON_INT) || @@@ -1666,8 -1661,8 +1666,8 @@@ } if (changed & BSS_CHANGED_ERP_PREAMBLE) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) priv->op_flags |= OP_PREAMBLE_SHORT; else @@@ -1675,8 -1670,8 +1675,8 @@@ } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) priv->op_flags |= OP_PROTECT_ENABLE; @@@ -1767,7 -1762,8 +1767,7 @@@ static int ath9k_htc_ampdu_action(struc spin_unlock_bh(&priv->tx_lock); break; default: - ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); + ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); } return ret; diff --combined drivers/net/wireless/ath/ath9k/mac.c index f05462ace4e8,c996963ab339..e3d2ebf00e2e --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@@ -20,11 -20,11 +20,11 @@@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, struct ath9k_tx_queue_info *qi) { - ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, - "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", - ah->txok_interrupt_mask, ah->txerr_interrupt_mask, - ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, - ah->txurn_interrupt_mask); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, + "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", + ah->txok_interrupt_mask, ah->txerr_interrupt_mask, + ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, + ah->txurn_interrupt_mask); ENABLE_REGWRITE_BUFFER(ah); @@@ -56,8 -56,8 +56,8 @@@ EXPORT_SYMBOL(ath9k_hw_puttxbuf) void ath9k_hw_txstart(struct ath_hw *ah, u32 q) { - ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, - "Enable TXE on queue: %u\n", q); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE, + "Enable TXE on queue: %u\n", q); REG_WRITE(ah, AR_Q_TXE, 1 << q); } EXPORT_SYMBOL(ath9k_hw_txstart); @@@ -117,11 -117,12 +117,11 @@@ EXPORT_SYMBOL(ath9k_hw_numtxpending) bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) { u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; if (ah->tx_trig_level >= ah->config.max_txtrig_level) return false; - omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); + ath9k_hw_disable_interrupts(ah); txcfg = REG_READ(ah, AR_TXCFG); curLevel = MS(txcfg, AR_FTRIG); @@@ -135,7 -136,7 +135,7 @@@ REG_WRITE(ah, AR_TXCFG, (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - ath9k_hw_set_interrupts(ah, omask); + ath9k_hw_enable_interrupts(ah); ah->tx_trig_level = newLevel; @@@ -154,15 -155,15 +154,15 @@@ bool ath9k_hw_stoptxdma(struct ath_hw * u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Stopping TX DMA, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Stopping TX DMA, inactive queue: %u\n", q); return false; } @@@ -175,9 -176,9 +175,9 @@@ } if (ath9k_hw_numtxpending(ah, q)) { - ath_print(common, ATH_DBG_QUEUE, - "%s: Num of pending TX Frames %d on Q %d\n", - __func__, ath9k_hw_numtxpending(ah, q), q); + ath_dbg(common, ATH_DBG_QUEUE, + "%s: Num of pending TX Frames %d on Q %d\n", + __func__, ath9k_hw_numtxpending(ah, q), q); for (j = 0; j < 2; j++) { tsfLow = REG_READ(ah, AR_TSF_L32); @@@ -191,9 -192,9 +191,9 @@@ if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) break; - ath_print(common, ATH_DBG_QUEUE, - "TSF has moved while trying to set " - "quiet time TSF: 0x%08x\n", tsfLow); + ath_dbg(common, ATH_DBG_QUEUE, + "TSF has moved while trying to set quiet time TSF: 0x%08x\n", + tsfLow); } REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); @@@ -204,8 -205,9 +204,8 @@@ wait = wait_time; while (ath9k_hw_numtxpending(ah, q)) { if ((--wait) == 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to stop TX DMA in 100 " - "msec after killing last frame\n"); + ath_err(common, + "Failed to stop TX DMA in 100 msec after killing last frame\n"); break; } udelay(ATH9K_TIME_QUANTUM); @@@ -238,19 -240,19 +238,19 @@@ bool ath9k_hw_set_txq_props(struct ath_ struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Set TXQ properties, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Set TXQ properties, inactive queue: %u\n", q); return false; } - ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); qi->tqi_ver = qinfo->tqi_ver; qi->tqi_subtype = qinfo->tqi_subtype; @@@ -309,15 -311,15 +309,15 @@@ bool ath9k_hw_get_txq_props(struct ath_ struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Get TXQ properties, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Get TXQ properties, inactive queue: %u\n", q); return false; } @@@ -367,20 -369,23 +367,20 @@@ int ath9k_hw_setuptxqueue(struct ath_h ATH9K_TX_QUEUE_INACTIVE) break; if (q == pCap->total_queues) { - ath_print(common, ATH_DBG_FATAL, - "No available TX queue\n"); + ath_err(common, "No available TX queue\n"); return -1; } break; default: - ath_print(common, ATH_DBG_FATAL, - "Invalid TX queue type: %u\n", type); + ath_err(common, "Invalid TX queue type: %u\n", type); return -1; } - ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); qi = &ah->txq[q]; if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_FATAL, - "TX queue: %u already active\n", q); + ath_err(common, "TX queue: %u already active\n", q); return -1; } memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); @@@ -412,18 -417,18 +412,18 @@@ bool ath9k_hw_releasetxqueue(struct ath struct ath9k_tx_queue_info *qi; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Release TXQ, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Release TXQ, inactive queue: %u\n", q); return false; } - ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; ah->txok_interrupt_mask &= ~(1 << q); @@@ -446,19 -451,19 +446,19 @@@ bool ath9k_hw_resettxqueue(struct ath_h u32 cwMin, chanCwMin, value; if (q >= pCap->total_queues) { - ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " - "invalid queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Reset TXQ, invalid queue: %u\n", q); return false; } qi = &ah->txq[q]; if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " - "inactive queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, + "Reset TXQ, inactive queue: %u\n", q); return true; } - ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); + ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { if (chan && IS_CHAN_B(chan)) @@@ -698,8 -703,7 +698,7 @@@ int ath9k_hw_rxprocdesc(struct ath_hw * rs->rs_phyerr = phyerr; } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) rs->rs_status |= ATH9K_RXERR_DECRYPT; - else if ((ads.ds_rxstatus8 & AR_MichaelErr) && - rs->rs_keyix != ATH9K_RXKEYIX_INVALID) + else if (ads.ds_rxstatus8 & AR_MichaelErr) rs->rs_status |= ATH9K_RXERR_MIC; else if (ads.ds_rxstatus8 & AR_KeyMiss) rs->rs_status |= ATH9K_RXERR_DECRYPT; @@@ -731,9 -735,9 +730,9 @@@ bool ath9k_hw_setrxabort(struct ath_hw AR_DIAG_RX_ABORT)); reg = REG_READ(ah, AR_OBS_BUS_1); - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, - "RX failed to go idle in 10 ms RXSM=0x%x\n", - reg); + ath_err(ath9k_hw_common(ah), + "RX failed to go idle in 10 ms RXSM=0x%x\n", + reg); return false; } @@@ -762,6 -766,14 +761,6 @@@ void ath9k_hw_startpcureceive(struct at } EXPORT_SYMBOL(ath9k_hw_startpcureceive); -void ath9k_hw_stoppcurecv(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - - ath9k_hw_disable_mib_counters(ah); -} -EXPORT_SYMBOL(ath9k_hw_stoppcurecv); - void ath9k_hw_abortpcurecv(struct ath_hw *ah) { REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); @@@ -787,11 -799,12 +786,11 @@@ bool ath9k_hw_stopdmarecv(struct ath_h } if (i == 0) { - ath_print(common, ATH_DBG_FATAL, - "DMA failed to stop in %d ms " - "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", - AH_RX_STOP_DMA_TIMEOUT / 1000, - REG_READ(ah, AR_CR), - REG_READ(ah, AR_DIAG_SW)); + ath_err(common, + "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", + AH_RX_STOP_DMA_TIMEOUT / 1000, + REG_READ(ah, AR_CR), + REG_READ(ah, AR_DIAG_SW)); return false; } else { return true; @@@ -835,59 -848,28 +834,59 @@@ bool ath9k_hw_intrpend(struct ath_hw *a } EXPORT_SYMBOL(ath9k_hw_intrpend); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, - enum ath9k_int ints) +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_DISABLE); + (void) REG_READ(ah, AR_IER); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); + (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); + } +} +EXPORT_SYMBOL(ath9k_hw_disable_interrupts); + +void ath9k_hw_enable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); + REG_WRITE(ah, AR_IER, AR_IER_ENABLE); + if (!AR_SREV_9100(ah)) { + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, + AR_INTR_SYNC_DEFAULT); + REG_WRITE(ah, AR_INTR_SYNC_MASK, + AR_INTR_SYNC_DEFAULT); + } + ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", + REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); +} +EXPORT_SYMBOL(ath9k_hw_enable_interrupts); + +void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) { enum ath9k_int omask = ah->imask; u32 mask, mask2; struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); - ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + if (!(ints & ATH9K_INT_GLOBAL)) + ath9k_hw_enable_interrupts(ah); - if (omask & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } + ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); /* TODO: global int Ref count */ mask = ints & ATH9K_INT_COMMON; @@@ -948,7 -930,7 +947,7 @@@ mask2 |= AR_IMR_S2_CST; } - ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); + ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); REG_WRITE(ah, AR_IMR, mask); ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | @@@ -963,8 -945,24 +962,8 @@@ REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); } - if (ints & ATH9K_INT_GLOBAL) { - ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } + ath9k_hw_enable_interrupts(ah); - return omask; + return; } EXPORT_SYMBOL(ath9k_hw_set_interrupts); diff --combined drivers/net/wireless/ath/ath9k/main.c index 41a312a3d401,c0c3464d3a86..daa3c9feca66 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@@ -23,7 -23,7 +23,7 @@@ static void ath_update_txpow(struct ath struct ath_hw *ah = sc->sc_ah; if (sc->curtxpow != sc->config.txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); /* read back in case value is clamped */ sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; } @@@ -234,8 -234,6 +234,8 @@@ int ath_set_channel(struct ath_softc *s ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + /* * This is only performed if the channel settings have * actually changed. @@@ -245,10 -243,13 +245,11 @@@ * hardware at the new frequency, and then re-enable * the relevant bits of the h/w. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); - ath_drain_all_txq(sc, false); + stopped = ath_drain_all_txq(sc, false); - stopped = ath_stoprecv(sc); - spin_lock_bh(&sc->rx.pcu_lock); - + if (!ath_stoprecv(sc)) + stopped = false; /* XXX: do not flush receive queue here. We don't want * to flush data frames already in queue because of @@@ -260,26 -261,36 +261,26 @@@ if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) caldata = &aphy->caldata; - ath_print(common, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", - sc->sc_ah->curchan->channel, - channel->center_freq, conf_is_ht40(conf), - fastcc); - - spin_lock_bh(&sc->sc_resetlock); + ath_dbg(common, ATH_DBG_CONFIG, + "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", + sc->sc_ah->curchan->channel, + channel->center_freq, conf_is_ht40(conf), + fastcc); r = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); goto ps_restore; } - spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); + ath_err(common, "Unable to restart recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); goto ps_restore; } - spin_unlock_bh(&sc->rx.pcu_lock); - ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, ah->imask); @@@ -290,8 -301,6 +291,8 @@@ } ps_restore: + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); return r; } @@@ -332,7 -341,7 +333,7 @@@ void ath_paprd_calibrate(struct work_st struct ath_tx_control txctl; struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath_common *common = ath9k_hw_common(ah); - int qnum, ftype; + int ftype; int chain_ok = 0; int chain; int len = 1800; @@@ -359,7 -368,8 +360,7 @@@ memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); memset(&txctl, 0, sizeof(txctl)); - qnum = sc->tx.hwq_map[WME_AC_BE]; - txctl.txq = &sc->tx.txq[qnum]; + txctl.txq = sc->tx.txq_map[WME_AC_BE]; ath9k_ps_wakeup(sc); ar9003_paprd_init_table(ah); @@@ -377,7 -387,6 +378,7 @@@ } init_completion(&sc->paprd_complete); + sc->paprd_pending = true; ar9003_paprd_setup_gain_table(ah, chain); txctl.paprd = BIT(chain); if (ath_tx_start(hw, skb, &txctl) != 0) @@@ -385,11 -394,11 +386,11 @@@ time_left = wait_for_completion_timeout(&sc->paprd_complete, msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); + sc->paprd_pending = false; if (!time_left) { - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, - "Timeout waiting for paprd training on " - "TX chain %d\n", - chain); + ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, + "Timeout waiting for paprd training on TX chain %d\n", + chain); goto fail_paprd; } @@@ -448,7 -457,7 +449,7 @@@ void ath_ani_calibrate(unsigned long da /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { longcal = true; - ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@@ -456,8 -465,8 +457,8 @@@ if (!common->ani.caldone) { if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; - ath_print(common, ATH_DBG_ANI, - "shortcal @%lu\n", jiffies); + ath_dbg(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@@ -541,26 -550,24 +542,26 @@@ void ath_update_chainmask(struct ath_so common->rx_chainmask = 1; } - ath_print(common, ATH_DBG_CONFIG, - "tx chmask: %d, rx chmask: %d\n", - common->tx_chainmask, - common->rx_chainmask); + ath_dbg(common, ATH_DBG_CONFIG, + "tx chmask: %d, rx chmask: %d\n", + common->tx_chainmask, + common->rx_chainmask); } static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an; - + struct ath_hw *ah = sc->sc_ah; an = (struct ath_node *)sta->drv_priv; + if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) + sc->sc_flags |= SC_OP_ENABLE_APM; + if (sc->sc_flags & SC_OP_TXAGGR) { ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); - an->last_rssi = ATH_RSSI_DUMMY_MARKER; } } @@@ -608,8 -615,6 +609,8 @@@ void ath9k_tasklet(unsigned long data return; } + spin_lock_bh(&sc->sc_pcu_lock); + if (!ath9k_hw_check_alive(ah)) ieee80211_queue_work(sc->hw, &sc->hw_check_work); @@@ -620,12 -625,15 +621,12 @@@ rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); if (status & rxmask) { - spin_lock_bh(&sc->rx.pcu_lock); - /* Check for high priority Rx first */ if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && (status & ATH9K_INT_RXHP)) ath_rx_tasklet(sc, 0, true); ath_rx_tasklet(sc, 0, false); - spin_unlock_bh(&sc->rx.pcu_lock); } if (status & ATH9K_INT_TX) { @@@ -640,8 -648,8 +641,8 @@@ * TSF sync does not look correct; remain awake to sync with * the next Beacon. */ - ath_print(common, ATH_DBG_PS, - "TSFOOR - Sync with next Beacon\n"); + ath_dbg(common, ATH_DBG_PS, + "TSFOOR - Sync with next Beacon\n"); sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; } @@@ -650,9 -658,7 +651,9 @@@ ath_gen_timer_isr(sc->sc_ah); /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); + + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); } @@@ -751,7 -757,7 +752,7 @@@ irqreturn_t ath_isr(int irq, void *dev * interrupt; otherwise it will continue to * fire. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); /* * Let the hal handle the event. We assume * it will clear whatever condition caused @@@ -760,13 -766,11 +761,13 @@@ spin_lock(&common->cc_lock); ath9k_hw_proc_mib_event(ah); spin_unlock(&common->cc_lock); - ath9k_hw_set_interrupts(ah, ah->imask); + ath9k_hw_enable_interrupts(ah); } if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) if (status & ATH9K_INT_TIM_TIMER) { + if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) + goto chip_reset; /* Clear RxAbort bit so that we can * receive frames */ ath9k_setpower(sc, ATH9K_PM_AWAKE); @@@ -779,8 -783,8 +780,8 @@@ chip_reset ath_debug_stat_interrupt(sc, status); if (sched) { - /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); + /* turn off every interrupt */ + ath9k_hw_disable_interrupts(ah); tasklet_schedule(&sc->intr_tq); } @@@ -832,18 -836,16 +833,18 @@@ static u32 ath_get_extchanmode(struct a } static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); if (bss_conf->assoc) { - ath_print(common, ATH_DBG_CONFIG, - "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, common->curbssid); + ath_dbg(common, ATH_DBG_CONFIG, + "Bss Info ASSOC %d, bssid: %pM\n", + bss_conf->aid, common->curbssid); /* New association, store aid */ common->curaid = bss_conf->aid; @@@ -860,13 -862,12 +861,13 @@@ ath_beacon_config(sc, vif); /* Reset rssi stats */ + aphy->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } else { - ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); common->curaid = 0; /* Stop ANI */ sc->sc_flags &= ~SC_OP_ANI_RUN; @@@ -882,26 -883,31 +883,26 @@@ void ath_radio_enable(struct ath_softc int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ath9k_hw_configpcipowersave(ah, 0, 0); if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, sc->hw); - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath_update_txpow(sc); if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, "Unable to restart recv logic\n"); + spin_unlock_bh(&sc->sc_pcu_lock); return; } - spin_unlock_bh(&sc->rx.pcu_lock); - if (sc->sc_flags & SC_OP_BEACONS) ath_beacon_config(sc, NULL); /* restart beacons */ @@@ -914,8 -920,6 +915,8 @@@ ath9k_hw_set_gpio(ah, ah->led_pin, 0); ieee80211_wake_queues(hw); + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); } @@@ -926,8 -930,6 +927,8 @@@ void ath_radio_disable(struct ath_soft int r; ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); /* @@@ -940,30 -942,34 +941,30 @@@ } /* Disable interrupts */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, false); /* clear pending tx frames */ - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); /* turn off frame recv */ ath_flushrecv(sc); /* flush recv queue */ if (!ah->curchan) ah->curchan = ath_get_curchannel(sc, hw); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (r) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to reset channel (%u MHz), " - "reset status %d\n", - channel->center_freq, r); + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); } - spin_unlock_bh(&sc->sc_resetlock); ath9k_hw_phy_disable(ah); - spin_unlock_bh(&sc->rx.pcu_lock); - ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); ath9k_ps_restore(sc); + ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } @@@ -977,23 -983,28 +978,23 @@@ int ath_reset(struct ath_softc *sc, boo /* Stop ANI */ del_timer_sync(&common->ani.timer); + spin_lock_bh(&sc->sc_pcu_lock); + ieee80211_stop_queues(hw); - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); ath_drain_all_txq(sc, retry_tx); - spin_lock_bh(&sc->rx.pcu_lock); - ath_stoprecv(sc); ath_flushrecv(sc); - spin_lock_bh(&sc->sc_resetlock); r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); if (r) - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d\n", r); - spin_unlock_bh(&sc->sc_resetlock); + ath_err(common, + "Unable to reset hardware; reset status %d\n", r); if (ath_startrecv(sc) != 0) - ath_print(common, ATH_DBG_FATAL, - "Unable to start recv logic\n"); - - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, "Unable to start recv logic\n"); /* * We may be doing a reset in response to a request @@@ -1019,7 -1030,6 +1020,7 @@@ } ieee80211_wake_queues(hw); + spin_unlock_bh(&sc->sc_pcu_lock); /* Start ANI */ ath_start_ani(common); @@@ -1027,6 -1037,56 +1028,6 @@@ return r; } -static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case 0: - qnum = sc->tx.hwq_map[WME_AC_VO]; - break; - case 1: - qnum = sc->tx.hwq_map[WME_AC_VI]; - break; - case 2: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - case 3: - qnum = sc->tx.hwq_map[WME_AC_BK]; - break; - default: - qnum = sc->tx.hwq_map[WME_AC_BE]; - break; - } - - return qnum; -} - -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case WME_AC_VO: - qnum = 0; - break; - case WME_AC_VI: - qnum = 1; - break; - case WME_AC_BE: - qnum = 2; - break; - case WME_AC_BK: - qnum = 3; - break; - default: - qnum = -1; - break; - } - - return qnum; -} - /* XXX: Remove me once we don't depend on ath9k_channel for all * this redundant data */ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, @@@ -1065,9 -1125,9 +1066,9 @@@ static int ath9k_start(struct ieee80211 struct ath9k_channel *init_channel; int r; - ath_print(common, ATH_DBG_CONFIG, - "Starting driver with initial channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, + "Starting driver with initial channel: %d MHz\n", + curchan->center_freq); mutex_lock(&sc->mutex); @@@ -1108,15 -1168,19 +1109,15 @@@ * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - spin_lock_bh(&sc->rx.pcu_lock); - spin_lock_bh(&sc->sc_resetlock); + spin_lock_bh(&sc->sc_pcu_lock); r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", r, - curchan->center_freq); - spin_unlock_bh(&sc->sc_resetlock); - spin_unlock_bh(&sc->rx.pcu_lock); + ath_err(common, + "Unable to reset hardware; reset status %d (freq %u MHz)\n", + r, curchan->center_freq); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->sc_resetlock); /* * This is needed only to setup initial state @@@ -1132,12 -1196,13 +1133,12 @@@ * here except setup the interrupt mask. */ if (ath_startrecv(sc) != 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to start recv logic\n"); + ath_err(common, "Unable to start recv logic\n"); r = -EIO; - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); goto mutex_unlock; } - spin_unlock_bh(&sc->rx.pcu_lock); + spin_unlock_bh(&sc->sc_pcu_lock); /* Setup our intr mask. */ ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | @@@ -1181,9 -1246,6 +1182,9 @@@ pm_qos_update_request(&sc->pm_qos_req, 55); + if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) + common->bus_ops->extn_synch_en(common); + mutex_unlock: mutex_unlock(&sc->mutex); @@@ -1193,16 -1255,19 +1194,16 @@@ static int ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_tx_control txctl; - int padpos, padsize; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int qnum; if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { - ath_print(common, ATH_DBG_XMIT, - "ath9k: %s: TX in unexpected wiphy state " - "%d\n", wiphy_name(hw->wiphy), aphy->state); + ath_dbg(common, ATH_DBG_XMIT, + "ath9k: %s: TX in unexpected wiphy state %d\n", + wiphy_name(hw->wiphy), aphy->state); goto exit; } @@@ -1214,8 -1279,8 +1215,8 @@@ if (ieee80211_is_data(hdr->frame_control) && !ieee80211_is_nullfunc(hdr->frame_control) && !ieee80211_has_pm(hdr->frame_control)) { - ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame " - "while in PS mode\n"); + ath_dbg(common, ATH_DBG_PS, + "Add PM=1 for a TX frame while in PS mode\n"); hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); } } @@@ -1230,12 -1295,12 +1231,12 @@@ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) ath9k_hw_setrxabort(sc->sc_ah, 0); if (ieee80211_is_pspoll(hdr->frame_control)) { - ath_print(common, ATH_DBG_PS, - "Sending PS-Poll to pick a buffered frame\n"); + ath_dbg(common, ATH_DBG_PS, + "Sending PS-Poll to pick a buffered frame\n"); sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; } else { - ath_print(common, ATH_DBG_PS, - "Wake up to complete TX\n"); + ath_dbg(common, ATH_DBG_PS, + "Wake up to complete TX\n"); sc->ps_flags |= PS_WAIT_FOR_TX_ACK; } /* @@@ -1247,12 -1312,36 +1248,12 @@@ } memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)]; - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, padpos); - } - - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txctl.txq = &sc->tx.txq[qnum]; - - ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); + ath_dbg(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_print(common, ATH_DBG_XMIT, "TX failed\n"); + ath_dbg(common, ATH_DBG_XMIT, "TX failed\n"); goto exit; } @@@ -1292,7 -1381,7 +1293,7 @@@ static void ath9k_stop(struct ieee80211 } if (sc->sc_flags & SC_OP_INVALID) { - ath_print(common, ATH_DBG_ANY, "Device not present\n"); + ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); mutex_unlock(&sc->mutex); return; } @@@ -1311,25 -1400,22 +1312,25 @@@ ath9k_btcoex_timer_pause(sc); } + spin_lock_bh(&sc->sc_pcu_lock); + /* make sure h/w will not generate any interrupt * before setting the invalid flag. */ - ath9k_hw_set_interrupts(ah, 0); + ath9k_hw_disable_interrupts(ah); - spin_lock_bh(&sc->rx.pcu_lock); if (!(sc->sc_flags & SC_OP_INVALID)) { ath_drain_all_txq(sc, false); ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else sc->rx.rxlink = NULL; - spin_unlock_bh(&sc->rx.pcu_lock); /* disable HAL and put h/w to sleep */ ath9k_hw_disable(ah); ath9k_hw_configpcipowersave(ah, 1, 1); + + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); /* Finally, put the chip in FULL SLEEP mode */ @@@ -1341,7 -1427,7 +1342,7 @@@ mutex_unlock(&sc->mutex); - ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); } static int ath9k_add_interface(struct ieee80211_hw *hw, @@@ -1374,14 -1460,14 +1375,14 @@@ ic_opmode = vif->type; break; default: - ath_print(common, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", vif->type); + ath_err(common, "Interface type %d not yet supported\n", + vif->type); ret = -EOPNOTSUPP; goto out; } - ath_print(common, ATH_DBG_CONFIG, - "Attach a VIF of type: %d\n", ic_opmode); + ath_dbg(common, ATH_DBG_CONFIG, + "Attach a VIF of type: %d\n", ic_opmode); /* Set the VIF opmode */ avp->av_opmode = ic_opmode; @@@ -1434,10 -1520,8 +1435,8 @@@ static void ath9k_remove_interface(stru struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_vif *avp = (void *)vif->drv_priv; - bool bs_valid = false; - int i; - ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); mutex_lock(&sc->mutex); @@@ -1449,26 -1533,21 +1448,21 @@@ if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { + /* Disable SWBA interrupt */ + sc->sc_ah->imask &= ~ATH9K_INT_SWBA; ath9k_ps_wakeup(sc); + ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); ath9k_ps_restore(sc); + tasklet_kill(&sc->bcon_tasklet); } ath_beacon_return(sc, avp); sc->sc_flags &= ~SC_OP_BEACONS; - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - if (sc->beacon.bslot[i] == vif) { - printk(KERN_DEBUG "%s: vif had allocated beacon " - "slot\n", __func__); - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } else if (sc->beacon.bslot[i]) - bs_valid = true; - } - if (!bs_valid && (sc->sc_ah->imask & ATH9K_INT_SWBA)) { - /* Disable SWBA interrupt */ - sc->sc_ah->imask &= ~ATH9K_INT_SWBA; + if (sc->nbcnvifs) { + /* Re-enable SWBA interrupt */ + sc->sc_ah->imask |= ATH9K_INT_SWBA; ath9k_ps_wakeup(sc); ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); ath9k_ps_restore(sc); @@@ -1552,8 -1631,8 +1546,8 @@@ static int ath9k_config(struct ieee8021 if (enable_radio) { sc->ps_idle = false; ath_radio_enable(sc, hw); - ath_print(common, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); } } @@@ -1575,12 -1654,12 +1569,12 @@@ if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (conf->flags & IEEE80211_CONF_MONITOR) { - ath_print(common, ATH_DBG_CONFIG, - "Monitor mode is enabled\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor mode is enabled\n"); sc->sc_ah->is_monitoring = true; } else { - ath_print(common, ATH_DBG_CONFIG, - "Monitor mode is disabled\n"); + ath_dbg(common, ATH_DBG_CONFIG, + "Monitor mode is disabled\n"); sc->sc_ah->is_monitoring = false; } } @@@ -1612,8 -1691,8 +1606,8 @@@ goto skip_chan_change; } - ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); + ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", + curchan->center_freq); /* XXX: remove me eventualy */ ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); @@@ -1646,7 -1725,8 +1640,7 @@@ } if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to set channel\n"); + ath_err(common, "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } @@@ -1671,7 -1751,7 +1665,7 @@@ skip_chan_change spin_unlock_bh(&sc->wiphy_lock); if (disable_radio) { - ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); + ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); sc->ps_idle = true; ath_radio_disable(sc, hw); } @@@ -1710,8 -1790,8 +1704,8 @@@ static void ath9k_configure_filter(stru ath9k_hw_setrxfilter(sc->sc_ah, rfilt); ath9k_ps_restore(sc); - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, - "Set HW RX filter: 0x%x\n", rfilt); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, + "Set HW RX filter: 0x%x\n", rfilt); } static int ath9k_sta_add(struct ieee80211_hw *hw, @@@ -1744,15 -1824,12 +1738,15 @@@ static int ath9k_conf_tx(struct ieee802 struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_txq *txq; struct ath9k_tx_queue_info qi; - int ret = 0, qnum; + int ret = 0; if (queue >= WME_NUM_AC) return 0; + txq = sc->tx.txq_map[queue]; + mutex_lock(&sc->mutex); memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); @@@ -1761,18 -1838,20 +1755,18 @@@ qi.tqi_cwmin = params->cw_min; qi.tqi_cwmax = params->cw_max; qi.tqi_burstTime = params->txop; - qnum = ath_get_hal_qnum(queue, sc); - ath_print(common, ATH_DBG_CONFIG, - "Configure tx [queue/halq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); + ath_dbg(common, ATH_DBG_CONFIG, + "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", + queue, txq->axq_qnum, params->aifs, params->cw_min, + params->cw_max, params->txop); - ret = ath_txq_update(sc, qnum, &qi); + ret = ath_txq_update(sc, txq->axq_qnum, &qi); if (ret) - ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); + ath_err(common, "TXQ Update failed\n"); if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) - if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) + if (queue == WME_AC_BE && !ret) ath_beaconq_config(sc); mutex_unlock(&sc->mutex); @@@ -1796,7 -1875,7 +1790,7 @@@ static int ath9k_set_key(struct ieee802 mutex_lock(&sc->mutex); ath9k_ps_wakeup(sc); - ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); + ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); switch (cmd) { case SET_KEY: @@@ -1855,8 -1934,9 +1849,8 @@@ static void ath9k_bss_info_changed(stru if (vif->type == NL80211_IFTYPE_ADHOC) ath_update_chainmask(sc, 0); - ath_print(common, ATH_DBG_CONFIG, - "BSSID: %pM aid: 0x%x\n", - common->curbssid, common->curaid); + ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", + common->curbssid, common->curaid); /* need to reconfigure the beacon */ sc->sc_flags &= ~SC_OP_BEACONS ; @@@ -1912,8 -1992,8 +1906,8 @@@ } if (changed & BSS_CHANGED_ERP_PREAMBLE) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) sc->sc_flags |= SC_OP_PREAMBLE_SHORT; else @@@ -1921,8 -2001,8 +1915,8 @@@ } if (changed & BSS_CHANGED_ERP_CTS_PROT) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", + bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) sc->sc_flags |= SC_OP_PROTECT_ENABLE; @@@ -1931,9 -2011,9 +1925,9 @@@ } if (changed & BSS_CHANGED_ASSOC) { - ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", + ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", bss_conf->assoc); - ath9k_bss_assoc_info(sc, vif, bss_conf); + ath9k_bss_assoc_info(sc, hw, vif, bss_conf); } mutex_unlock(&sc->mutex); @@@ -1996,9 -2076,6 +1990,9 @@@ static int ath9k_ampdu_action(struct ie case IEEE80211_AMPDU_RX_STOP: break; case IEEE80211_AMPDU_TX_START: + if (!(sc->sc_flags & SC_OP_TXAGGR)) + return -EOPNOTSUPP; + ath9k_ps_wakeup(sc); ret = ath_tx_aggr_start(sc, sta, tid, ssn); if (!ret) @@@ -2017,7 -2094,8 +2011,7 @@@ ath9k_ps_restore(sc); break; default: - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unknown AMPDU action\n"); + ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n"); } local_bh_enable(); diff --combined drivers/net/wireless/ath/ath9k/recv.c index c3129db7828f,fdc2ec52b42f..00ebed3f9158 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@@ -165,7 -165,7 +165,7 @@@ static void ath_rx_addbuffer_edma(struc u32 nbuf = 0; if (list_empty(&sc->rx.rxbuf)) { - ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); + ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n"); return; } @@@ -269,7 -269,7 +269,7 @@@ static int ath_rx_edma_init(struct ath_ dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, + ath_err(common, "dma_mapping_error() on RX init\n"); error = -ENOMEM; goto rx_init_fail; @@@ -317,7 -317,7 +317,7 @@@ int ath_rx_init(struct ath_softc *sc, i struct ath_buf *bf; int error = 0; - spin_lock_init(&sc->rx.pcu_lock); + spin_lock_init(&sc->sc_pcu_lock); sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->rx.rxbuflock); @@@ -327,17 -327,17 +327,17 @@@ common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, min(common->cachelsz, (u16)64)); - ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - common->cachelsz, common->rx_bufsize); + ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", + common->cachelsz, common->rx_bufsize); /* Initialize rx descriptors */ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, "rx", nbufs, 1, 0); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", - error); + ath_err(common, + "failed to allocate rx descriptors: %d\n", + error); goto err; } @@@ -358,8 -358,8 +358,8 @@@ dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); + ath_err(common, + "dma_mapping_error() on RX init\n"); error = -ENOMEM; goto err; } @@@ -528,12 -528,6 +528,12 @@@ bool ath_stoprecv(struct ath_softc *sc sc->rx.rxlink = NULL; spin_unlock_bh(&sc->rx.rxbuflock); + if (unlikely(!stopped)) { + ath_err(ath9k_hw_common(sc->sc_ah), + "Could not stop RX, we could be " + "confusing the DMA engine when we start RX up\n"); + ATH_DBG_WARN_ON_ONCE(!stopped); + } return stopped; } @@@ -594,8 -588,9 +594,8 @@@ static void ath_rx_ps_beacon(struct ath if (sc->ps_flags & PS_BEACON_SYNC) { sc->ps_flags &= ~PS_BEACON_SYNC; - ath_print(common, ATH_DBG_PS, - "Reconfigure Beacon timers based on " - "timestamp from the AP\n"); + ath_dbg(common, ATH_DBG_PS, + "Reconfigure Beacon timers based on timestamp from the AP\n"); ath_beacon_config(sc, NULL); } @@@ -607,8 -602,8 +607,8 @@@ * a backup trigger for returning into NETWORK SLEEP state, * so we are waiting for it as well. */ - ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " - "buffered broadcast/multicast frame(s)\n"); + ath_dbg(common, ATH_DBG_PS, + "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n"); sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; return; } @@@ -620,8 -615,8 +620,8 @@@ * been delivered. */ sc->ps_flags &= ~PS_WAIT_FOR_CAB; - ath_print(common, ATH_DBG_PS, - "PS wait for CAB frames timed out\n"); + ath_dbg(common, ATH_DBG_PS, + "PS wait for CAB frames timed out\n"); } } @@@ -646,14 -641,15 +646,14 @@@ static void ath_rx_ps(struct ath_softc * point. */ sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); - ath_print(common, ATH_DBG_PS, - "All PS CAB frames received, back to sleep\n"); + ath_dbg(common, ATH_DBG_PS, + "All PS CAB frames received, back to sleep\n"); } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && !is_multicast_ether_addr(hdr->addr1) && !ieee80211_has_morefrags(hdr->frame_control)) { sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; - ath_print(common, ATH_DBG_PS, - "Going back to sleep after having received " - "PS-Poll data (0x%lx)\n", + ath_dbg(common, ATH_DBG_PS, + "Going back to sleep after having received PS-Poll data (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | @@@ -662,7 -658,8 +662,7 @@@ } static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, - struct ath_softc *sc, struct sk_buff *skb, - struct ieee80211_rx_status *rxs) + struct ath_softc *sc, struct sk_buff *skb) { struct ieee80211_hdr *hdr; @@@ -841,6 -838,10 +841,10 @@@ static bool ath9k_rx_accept(struct ath_ struct ath_rx_status *rx_stats, bool *decrypt_error) { + #define is_mc_or_valid_tkip_keyix ((is_mc || \ + (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \ + test_bit(rx_stats->rs_keyix, common->tkip_keymap)))) + struct ath_hw *ah = common->ah; __le16 fc; u8 rx_status_len = ah->caps.rx_status_len; @@@ -882,15 -883,18 +886,18 @@@ if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { *decrypt_error = true; } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { + bool is_mc; /* * The MIC error bit is only valid if the frame * is not a control frame or fragment, and it was * decrypted using a valid TKIP key. */ + is_mc = !!is_multicast_ether_addr(hdr->addr1); + if (!ieee80211_is_ctl(fc) && !ieee80211_has_morefrags(fc) && !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && - test_bit(rx_stats->rs_keyix, common->tkip_keymap)) + is_mc_or_valid_tkip_keyix) rxs->flag |= RX_FLAG_MMIC_ERROR; else rx_stats->rs_status &= ~ATH9K_RXERR_MIC; @@@ -954,9 -958,8 +961,9 @@@ static int ath9k_process_rate(struct at * No valid hardware bitrate found -- we should not get here * because hardware has already validated this frame as OK. */ - ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " - "0x%02x using 1 Mbit\n", rx_stats->rs_rate); + ath_dbg(common, ATH_DBG_XMIT, + "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", + rx_stats->rs_rate); return -EINVAL; } @@@ -966,23 -969,36 +973,23 @@@ static void ath9k_process_rssi(struct a struct ieee80211_hdr *hdr, struct ath_rx_status *rx_stats) { + struct ath_wiphy *aphy = hw->priv; struct ath_hw *ah = common->ah; - struct ieee80211_sta *sta; - struct ath_node *an; - int last_rssi = ATH_RSSI_DUMMY_MARKER; + int last_rssi; __le16 fc; + if (ah->opmode != NL80211_IFTYPE_STATION) + return; + fc = hdr->frame_control; + if (!ieee80211_is_beacon(fc) || + compare_ether_addr(hdr->addr3, common->curbssid)) + return; - rcu_read_lock(); - /* - * XXX: use ieee80211_find_sta! This requires quite a bit of work - * under the current ath9k virtual wiphy implementation as we have - * no way of tying a vif to wiphy. Typically vifs are attached to - * at least one sdata of a wiphy on mac80211 but with ath9k virtual - * wiphy you'd have to iterate over every wiphy and each sdata. - */ - if (is_multicast_ether_addr(hdr->addr1)) - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); - else - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1); - - if (sta) { - an = (struct ath_node *) sta->drv_priv; - if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && - !rx_stats->rs_moreaggr) - ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); - last_rssi = an->last_rssi; - } - rcu_read_unlock(); + if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) + ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); + last_rssi = aphy->last_rssi; if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) rx_stats->rs_rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); @@@ -990,7 -1006,8 +997,7 @@@ rx_stats->rs_rssi = 0; /* Update Beacon RSSI, this is used by ANI. */ - if (ieee80211_is_beacon(fc)) - ah->stats.avgbrssi = rx_stats->rs_rssi; + ah->stats.avgbrssi = rx_stats->rs_rssi; } /* @@@ -1620,7 -1637,7 +1627,7 @@@ int ath_rx_tasklet(struct ath_softc *sc struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); /* - * The hw can techncically differ from common->hw when using ath9k + * The hw can technically differ from common->hw when using ath9k * virtual wiphy so to account for that we iterate over the active * wiphys and find the appropriate wiphy and therefore hw. */ @@@ -1727,8 -1744,9 +1734,8 @@@ dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(common, ATH_DBG_FATAL, - "dma_mapping_error() on RX\n"); - ath_rx_send_to_mac80211(hw, sc, skb, rxs); + ath_err(common, "dma_mapping_error() on RX\n"); + ath_rx_send_to_mac80211(hw, sc, skb); break; } @@@ -1744,18 -1762,17 +1751,18 @@@ } spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (unlikely(ath9k_check_auto_sleep(sc) || - (sc->ps_flags & (PS_WAIT_FOR_BEACON | + + if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA)))) + PS_WAIT_FOR_PSPOLL_DATA)) || + unlikely(ath9k_check_auto_sleep(sc))) ath_rx_ps(sc, skb); spin_unlock_irqrestore(&sc->sc_pm_lock, flags); if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) ath_ant_comb_scan(sc, &rs); - ath_rx_send_to_mac80211(hw, sc, skb, rxs); + ath_rx_send_to_mac80211(hw, sc, skb); requeue: if (edma) { diff --combined drivers/net/wireless/ath/ath9k/xmit.c index bce313e85cff,aff04789f794..43c0109f202c --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@@ -48,17 -48,19 +48,17 @@@ static u16 bits_per_symbol[][2] = #define IS_HT_RATE(_rate) ((_rate) & 0x80) -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head); static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq, struct list_head *bf_q, struct ath_tx_status *ts, int txok, int sendbar); static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, struct list_head *head); -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok); +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc); + int nframes, int nbad, int txok, bool update_rc); static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, int seqno); @@@ -122,7 -124,7 +122,7 @@@ static void ath_tx_queue_tid(struct ath static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; WARN_ON(!tid->paused); @@@ -138,21 -140,12 +138,21 @@@ unlock spin_unlock_bh(&txq->axq_lock); } +static struct ath_frame_info *get_frame_info(struct sk_buff *skb) +{ + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + BUILD_BUG_ON(sizeof(struct ath_frame_info) > + sizeof(tx_info->rate_driver_data)); + return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; +} + static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) { - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; + struct ath_txq *txq = tid->ac->txq; struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; INIT_LIST_HEAD(&bf_head); @@@ -163,15 -156,12 +163,15 @@@ bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) { - ath_tx_update_baw(sc, tid, bf->bf_seqno); + spin_unlock_bh(&txq->axq_lock); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) { + ath_tx_update_baw(sc, tid, fi->seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } else { - ath_tx_send_ht_normal(sc, txq, tid, &bf_head); + ath_tx_send_normal(sc, txq, tid, &bf_head); } + spin_lock_bh(&txq->axq_lock); } spin_unlock_bh(&txq->axq_lock); @@@ -194,11 -184,14 +194,11 @@@ static void ath_tx_update_baw(struct at } static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf) + u16 seqno) { int index, cindex; - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); + index = ATH_BA_INDEX(tid->seq_start, seqno); cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); __set_bit(cindex, tid->tx_buf); @@@ -222,7 -215,6 +222,7 @@@ static void ath_tid_drain(struct ath_so struct ath_buf *bf; struct list_head bf_head; struct ath_tx_status ts; + struct ath_frame_info *fi; memset(&ts, 0, sizeof(ts)); INIT_LIST_HEAD(&bf_head); @@@ -234,9 -226,8 +234,9 @@@ bf = list_first_entry(&tid->buf_q, struct ath_buf, list); list_move_tail(&bf->list, &bf_head); - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); + fi = get_frame_info(bf->bf_mpdu); + if (fi->retries) + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock(&txq->axq_lock); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@@ -248,15 -239,16 +248,15 @@@ } static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) + struct sk_buff *skb) { - struct sk_buff *skb; + struct ath_frame_info *fi = get_frame_info(skb); struct ieee80211_hdr *hdr; - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; TX_STAT_INC(txq->axq_qnum, a_retries); + if (fi->retries++ > 0) + return; - skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); } @@@ -306,41 -298,9 +306,41 @@@ static struct ath_buf* ath_clone_txbuf( return tbf; } +static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_status *ts, int txok, + int *nframes, int *nbad) +{ + struct ath_frame_info *fi; + u16 seq_st = 0; + u32 ba[WME_BA_BMP_SIZE >> 5]; + int ba_index; + int isaggr = 0; + + *nbad = 0; + *nframes = 0; + + isaggr = bf_isaggr(bf); + if (isaggr) { + seq_st = ts->ts_seqnum; + memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); + } + + while (bf) { + fi = get_frame_info(bf->bf_mpdu); + ba_index = ATH_BA_INDEX(seq_st, fi->seqno); + + (*nframes)++; + if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) + (*nbad)++; + + bf = bf->bf_next; + } +} + + static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct list_head *bf_q, - struct ath_tx_status *ts, int txok) + struct ath_tx_status *ts, int txok, bool retry) { struct ath_node *an = NULL; struct sk_buff *skb; @@@ -356,9 -316,7 +356,9 @@@ int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; + struct ath_frame_info *fi; int nframes; + u8 tidno; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@@ -367,6 -325,7 +367,6 @@@ hw = bf->aphy->hw; memcpy(rates, tx_info->control.rates, sizeof(rates)); - nframes = bf->bf_nframes; rcu_read_lock(); @@@ -383,7 -342,7 +383,7 @@@ !bf->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); - ath_tx_rc_status(bf, ts, 1, 0, false); + ath_tx_rc_status(bf, ts, 1, 1, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@@ -393,15 -352,14 +393,15 @@@ } an = (struct ath_node *)sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(an, tidno); /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted */ - if (bf->bf_tidno != ts->tid) + if (tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@@ -427,16 -385,15 +427,16 @@@ INIT_LIST_HEAD(&bf_pending); INIT_LIST_HEAD(&bf_head); - nbad = ath_tx_num_badfrms(sc, bf, ts, txok); + ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); while (bf) { txfail = txpending = 0; bf_next = bf->bf_next; skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); + fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { + if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; @@@ -444,9 -401,10 +444,9 @@@ /* transmit completion */ acked_cnt++; } else { - if (!(tid->state & AGGR_CLEANUP) && - !bf_last->bf_tx_aborted) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, txq, bf); + if (!(tid->state & AGGR_CLEANUP) && retry) { + if (fi->retries < ATH_MAX_SW_RETRIES) { + ath_tx_set_retry(sc, txq, bf->bf_mpdu); txpending = 1; } else { bf->bf_state.bf_type |= BUF_XRETRY; @@@ -484,15 -442,16 +484,15 @@@ * block-ack window */ spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { memcpy(tx_info->control.rates, rates, sizeof(rates)); - bf->bf_nframes = nframes; - ath_tx_rc_status(bf, ts, nbad, txok, true); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, true); rc_update = false; } else { - ath_tx_rc_status(bf, ts, nbad, txok, false); + ath_tx_rc_status(bf, ts, nframes, nbad, txok, false); } ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, @@@ -511,13 -470,14 +511,13 @@@ */ if (!tbf) { spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, - bf->bf_seqno); + ath_tx_update_baw(sc, tid, fi->seqno); spin_unlock_bh(&txq->axq_lock); bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ts, nbad, - 0, false); + ath_tx_rc_status(bf, ts, nframes, + nbad, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@@ -651,7 -611,6 +651,7 @@@ static int ath_compute_num_delims(struc u16 minlen; u8 flags, rix; int width, streams, half_gi, ndelim, mindelim; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); /* Select standard number of delimiters based on frame length alone */ ndelim = ATH_AGGR_GET_NDELIM(frmlen); @@@ -662,7 -621,7 +662,7 @@@ * TODO - this could be improved to be dependent on the rate. * The hardware can keep up at lower rates, but not higher rates */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) + if (fi->keyix != ATH9K_TXKEYIX_INVALID) ndelim += ATH_AGGR_ENCRYPTDELIM; /* @@@ -706,8 -665,7 +706,8 @@@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct list_head *bf_q) + struct list_head *bf_q, + int *aggr_len) { #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) struct ath_buf *bf, *bf_first, *bf_prev = NULL; @@@ -716,16 -674,14 +716,16 @@@ al_delta, h_baw = tid->baw_size / 2; enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; struct ieee80211_tx_info *tx_info; + struct ath_frame_info *fi; bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); do { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); + fi = get_frame_info(bf->bf_mpdu); /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { status = ATH_AGGR_BAW_CLOSED; break; } @@@ -736,7 -692,7 +736,7 @@@ } /* do not exceed aggregation limit */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; + al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; if (nframes && (aggr_limit < (al + bpad + al_delta + prev_al))) { @@@ -763,15 -719,14 +763,15 @@@ * Get the delimiters needed to meet the MPDU * density for this node. */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); + ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); bpad = PADBYTES(al_delta) + (ndelim << 2); bf->bf_next = NULL; ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); /* link buffers of this frame to the aggregate */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); list_move_tail(&bf->list, bf_q); if (bf_prev) { @@@ -783,7 -738,8 +783,7 @@@ } while (!list_empty(&tid->buf_q)); - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; + *aggr_len = al; return status; #undef PADBYTES @@@ -794,9 -750,7 +794,9 @@@ static void ath_tx_sched_aggr(struct at { struct ath_buf *bf; enum ATH_AGGR_STATUS status; + struct ath_frame_info *fi; struct list_head bf_q; + int aggr_len; do { if (list_empty(&tid->buf_q)) @@@ -804,7 -758,7 +804,7 @@@ INIT_LIST_HEAD(&bf_q); - status = ath_tx_form_aggr(sc, txq, tid, &bf_q); + status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); /* * no frames picked up to be aggregated; @@@ -817,20 -771,18 +817,20 @@@ bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); /* if only one frame, send as non-aggregate */ - if (bf->bf_nframes == 1) { + if (bf == bf->bf_lastbf) { + fi = get_frame_info(bf->bf_mpdu); + bf->bf_state.bf_type &= ~BUF_AGGR; ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); - ath_buf_set_rate(sc, bf); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_q); continue; } /* setup first desc of aggregate */ bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); + ath_buf_set_rate(sc, bf, aggr_len); + ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len); /* anchor last desc of aggregate */ ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); @@@ -865,7 -817,7 +865,7 @@@ void ath_tx_aggr_stop(struct ath_softc { struct ath_node *an = (struct ath_node *)sta->drv_priv; struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; + struct ath_txq *txq = txtid->ac->txq; if (txtid->state & AGGR_CLEANUP) return; @@@ -936,16 -888,10 +936,16 @@@ struct ath_txq *ath_txq_setup(struct at struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath9k_tx_queue_info qi; + static const int subtype_txq_to_hwq[] = { + [WME_AC_BE] = ATH_TXQ_AC_BE, + [WME_AC_BK] = ATH_TXQ_AC_BK, + [WME_AC_VI] = ATH_TXQ_AC_VI, + [WME_AC_VO] = ATH_TXQ_AC_VO, + }; int qnum, i; memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; + qi.tqi_subtype = subtype_txq_to_hwq[subtype]; qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; @@@ -985,14 -931,16 +985,14 @@@ return NULL; } if (qnum >= ARRAY_SIZE(sc->tx.txq)) { - ath_print(common, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); + ath_err(common, "qnum %u out of range, max %zu!\n", + qnum, ARRAY_SIZE(sc->tx.txq)); ath9k_hw_releasetxqueue(ah, qnum); return NULL; } if (!ATH_TXQ_SETUP(sc, qnum)) { struct ath_txq *txq = &sc->tx.txq[qnum]; - txq->axq_class = subtype; txq->axq_qnum = qnum; txq->axq_link = NULL; INIT_LIST_HEAD(&txq->axq_q); @@@ -1037,8 -985,8 +1037,8 @@@ int ath_txq_update(struct ath_softc *sc qi.tqi_readyTime = qinfo->tqi_readyTime; if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to update hardware queue %u!\n", qnum); error = -EIO; } else { ath9k_hw_resettxqueue(ah, qnum); @@@ -1114,6 -1062,8 +1114,6 @@@ void ath_draintxq(struct ath_softc *sc } lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_tx_aborted = true; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { list_cut_position(&bf_head, @@@ -1130,8 -1080,7 +1130,8 @@@ spin_unlock_bh(&txq->axq_lock); if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, + retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); } @@@ -1152,7 -1101,7 +1152,7 @@@ if (bf_isampdu(bf)) ath_tx_complete_aggr(sc, txq, bf, &bf_head, - &ts, 0); + &ts, 0, retry_tx); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); @@@ -1171,7 -1120,7 +1171,7 @@@ } } - void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) + bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@@ -1179,7 -1128,7 +1179,7 @@@ int i, npend = 0; if (sc->sc_flags & SC_OP_INVALID) - return; + return true; /* Stop beacon queue */ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); @@@ -1193,22 -1142,15 +1193,15 @@@ } } - if (npend) { - int r; - - ath_err(common, "Failed to stop TX DMA. Resetting hardware!\n"); - - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); - if (r) - ath_err(common, - "Unable to reset hardware; reset status %d\n", - r); - } + if (npend) - ath_print(common, ATH_DBG_FATAL, "Failed to stop TX DMA!\n"); ++ ath_err(common, "Failed to stop TX DMA!\n"); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) ath_draintxq(sc, &sc->tx.txq[i], retry_tx); } + + return !npend; } void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) @@@ -1260,6 -1202,24 +1253,6 @@@ void ath_txq_schedule(struct ath_softc } } -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; - - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; - } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - /***********/ /* TX, DMA */ /***********/ @@@ -1285,8 -1245,8 +1278,8 @@@ static void ath_tx_txqaddbuf(struct ath bf = list_first_entry(head, struct ath_buf, list); - ath_print(common, ATH_DBG_QUEUE, - "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); + ath_dbg(common, ATH_DBG_QUEUE, + "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { @@@ -1294,29 -1254,32 +1287,29 @@@ return; } if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) - ath_print(common, ATH_DBG_XMIT, - "Initializing tx fifo %d which " - "is non-empty\n", - txq->txq_headidx); + ath_dbg(common, ATH_DBG_XMIT, + "Initializing tx fifo %d which is non-empty\n", + txq->txq_headidx); INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - ath_print(common, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); } else { list_splice_tail_init(head, &txq->axq_q); if (txq->axq_link == NULL) { ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - ath_print(common, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), - bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", + txq->axq_qnum, ito64(bf->bf_daddr), + bf->bf_desc); } else { *txq->axq_link = bf->bf_daddr; - ath_print(common, ATH_DBG_XMIT, - "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); + ath_dbg(common, ATH_DBG_XMIT, + "link[%u] (%p)=%llx (%p)\n", + txq->axq_qnum, txq->axq_link, + ito64(bf->bf_daddr), bf->bf_desc); } ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, &txq->axq_link); @@@ -1326,11 -1289,12 +1319,11 @@@ } static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) + struct ath_buf *bf, struct ath_tx_control *txctl) { - struct ath_buf *bf; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); + struct list_head bf_head; - bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type |= BUF_AMPDU; TX_STAT_INC(txctl->txq->axq_qnum, a_queued); @@@ -1342,47 -1306,56 +1335,47 @@@ * - h/w queue depth exceeds low water mark */ if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || + !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { /* * Add this frame to software queue for scheduling later * for aggregation. */ - list_move_tail(&bf->list, &tid->buf_q); + list_add_tail(&bf->list, &tid->buf_q); ath_tx_queue_tid(txctl->txq, tid); return; } + INIT_LIST_HEAD(&bf_head); + list_add(&bf->list, &bf_head); + /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); + if (!fi->retries) + ath_tx_addto_baw(sc, tid, fi->seqno); /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); + ath_buf_set_rate(sc, bf, fi->framelen); + ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); } -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) +static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, + struct ath_atx_tid *tid, + struct list_head *bf_head) { + struct ath_frame_info *fi; struct ath_buf *bf; bf = list_first_entry(bf_head, struct ath_buf, list); bf->bf_state.bf_type &= ~BUF_AMPDU; /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); - TX_STAT_INC(txq->axq_qnum, queued); -} - -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); + if (tid) + INCR(tid->seq_start, IEEE80211_SEQ_MAX); bf->bf_lastbf = bf; - bf->bf_nframes = 1; - ath_buf_set_rate(sc, bf); + fi = get_frame_info(bf->bf_mpdu); + ath_buf_set_rate(sc, bf, fi->framelen); ath_tx_txqaddbuf(sc, txq, bf_head); TX_STAT_INC(txq->axq_qnum, queued); } @@@ -1410,52 -1383,40 +1403,52 @@@ static enum ath9k_pkt_type get_hw_packe return htype; } -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) +static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, + int framelen) { + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = tx_info->control.sta; + struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr; + struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an; struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; + enum ath9k_key_type keytype; + u16 seqno = 0; + u8 tidno; - if (!tx_info->control.sta) - return; + keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - an = (struct ath_node *)tx_info->control.sta->drv_priv; hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; + if (sta && ieee80211_is_data_qos(hdr->frame_control) && + conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; + an = (struct ath_node *) sta->drv_priv; + tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; + + /* + * Override seqno set by upper layer with the one + * in tx aggregation state. + */ + tid = ATH_AN_2_TID(an, tidno); + seqno = tid->seq_next; + hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); + INCR(tid->seq_next, IEEE80211_SEQ_MAX); } - /* - * For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); + memset(fi, 0, sizeof(*fi)); + if (hw_key) + fi->keyix = hw_key->hw_key_idx; + else + fi->keyix = ATH9K_TXKEYIX_INVALID; + fi->keytype = keytype; + fi->framelen = framelen; + fi->seqno = seqno; } -static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) +static int setup_tx_flags(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); int flags = 0; @@@ -1466,7 -1427,7 +1459,7 @@@ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= ATH9K_TXDESC_NOACK; - if (use_ldpc) + if (tx_info->flags & IEEE80211_TX_CTL_LDPC) flags |= ATH9K_TXDESC_LDPC; return flags; @@@ -1478,11 -1439,13 +1471,11 @@@ * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, +static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; + int streams; /* find number of symbols: PLCP + data */ streams = HT_RC_2_STREAMS(rix); @@@ -1501,19 -1464,7 +1494,19 @@@ return duration; } -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) +u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *curchan = ah->curchan; + if ((sc->sc_flags & SC_OP_ENABLE_APM) && + (curchan->channelFlags & CHANNEL_5GHZ) && + (chainmask == 0x7) && (rate < 0x90)) + return 0x3; + else + return chainmask; +} + +static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath9k_11n_rate_series series[4]; @@@ -1553,6 -1504,7 +1546,6 @@@ rix = rates[i].idx; series[i].Tries = rates[i].count; - series[i].ChSel = common->tx_chainmask; if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { @@@ -1575,16 -1527,14 +1568,16 @@@ if (rates[i].flags & IEEE80211_TX_RC_MCS) { /* MCS rates */ series[i].Rate = rix | 0x80; - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath_pkt_duration(sc, rix, len, is_40, is_sgi, is_sp); if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) series[i].RateFlags |= ATH9K_RATESERIES_STBC; continue; } - /* legcay rates */ + /* legacy rates */ if ((tx_info->band == IEEE80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; @@@ -1600,18 -1550,12 +1593,18 @@@ is_sp = false; } + if (bf->bf_state.bfs_paprd) + series[i].ChSel = common->tx_chainmask; + else + series[i].ChSel = ath_txchainmask_reduction(sc, + common->tx_chainmask, series[i].Rate); + series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, - phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); + phy, rate->bitrate * 100, len, rix, is_sp); } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) + if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) flags &= ~ATH9K_TXDESC_RTSENA; /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ @@@ -1628,29 -1572,67 +1621,29 @@@ ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); } -static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, - struct sk_buff *skb, - struct ath_tx_control *txctl) +static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, + struct ath_txq *txq, + struct sk_buff *skb) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int hdrlen; - __le16 fc; - int padpos, padsize; - bool use_ldpc = false; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_frame_info *fi = get_frame_info(skb); + struct ath_buf *bf; + struct ath_desc *ds; + int frm_type; - tx_info->pad[0] = 0; - switch (txctl->frame_type) { - case ATH9K_IFT_NOT_INTERNAL: - break; - case ATH9K_IFT_PAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; - /* fall through */ - case ATH9K_IFT_UNPAUSE: - tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; - break; + bf = ath_tx_get_buffer(sc); + if (!bf) { + ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); + return NULL; } - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; ATH_TXBUF_RESET(bf); bf->aphy = aphy; - bf->bf_frmlen = skb->len + FCS_LEN; - /* Remove the padding size from bf_frmlen, if any */ - padpos = ath9k_cmn_padpos(hdr->frame_control); - padsize = padpos & 3; - if (padsize && skb->len>padpos+padsize) { - bf->bf_frmlen -= padsize; - } - - if (!txctl->paprd && conf_is_ht(&hw->conf)) { - bf->bf_state.bf_type |= BUF_HT; - if (tx_info->flags & IEEE80211_TX_CTL_LDPC) - use_ldpc = true; - } - - bf->bf_state.bfs_paprd = txctl->paprd; - if (txctl->paprd) - bf->bf_state.bfs_paprd_timestamp = jiffies; - bf->bf_flags = setup_tx_flags(skb, use_ldpc); - - bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { - bf->bf_frmlen += tx_info->control.hw_key->icv_len; - bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; - } else { - bf->bf_keyix = ATH9K_TXKEYIX_INVALID; - } - - if (ieee80211_is_data_qos(fc) && bf_isht(bf) && - (sc->sc_flags & SC_OP_TXAGGR)) - assign_aggr_tid_seqno(skb, bf); - + bf->bf_flags = setup_tx_flags(skb); bf->bf_mpdu = skb; bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, @@@ -1658,19 -1640,42 +1651,19 @@@ if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { bf->bf_mpdu = NULL; bf->bf_buf_addr = 0; - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "dma_mapping_error() on TX\n"); - return -ENOMEM; + ath_err(ath9k_hw_common(sc->sc_ah), + "dma_mapping_error() on TX\n"); + ath_tx_return_buffer(sc, bf); + return NULL; } - bf->bf_tx_aborted = false; - - return 0; -} - -/* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_control *txctl) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_node *an = NULL; - struct list_head bf_head; - struct ath_desc *ds; - struct ath_atx_tid *tid; - struct ath_hw *ah = sc->sc_ah; - int frm_type; - __le16 fc; - frm_type = get_hw_packet_type(skb); - fc = hdr->frame_control; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); ds = bf->bf_desc; ath9k_hw_set_desc_link(ah, ds, 0); - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, - bf->bf_keyix, bf->bf_keytype, bf->bf_flags); + ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER, + fi->keyix, fi->keytype, bf->bf_flags); ath9k_hw_filltxdesc(ah, ds, skb->len, /* segment length */ @@@ -1678,50 -1683,42 +1671,50 @@@ true, /* last segment */ ds, /* first descriptor */ bf->bf_buf_addr, - txctl->txq->axq_qnum); + txq->axq_qnum); - if (bf->bf_state.bfs_paprd) - ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); - spin_lock_bh(&txctl->txq->axq_lock); + return bf; +} + +/* FIXME: tx power */ +static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, + struct ath_tx_control *txctl) +{ + struct sk_buff *skb = bf->bf_mpdu; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct list_head bf_head; + struct ath_atx_tid *tid; + u8 tidno; - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && - tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); + spin_lock_bh(&txctl->txq->axq_lock); - if (!ieee80211_is_data_qos(fc)) { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - goto tx_done; - } + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && txctl->an) { + tidno = ieee80211_get_qos_ctl(hdr)[0] & + IEEE80211_QOS_CTL_TID_MASK; + tid = ATH_AN_2_TID(txctl->an, tidno); - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - /* - * Try aggregation if it's a unicast data frame - * and the destination is HT capable. - */ - ath_tx_send_ampdu(sc, tid, &bf_head, txctl); - } else { - /* - * Send this frame as regular when ADDBA - * exchange is neither complete nor pending. - */ - ath_tx_send_ht_normal(sc, txctl->txq, - tid, &bf_head); - } + WARN_ON(tid->ac->txq != txctl->txq); + /* + * Try aggregation if it's a unicast data frame + * and the destination is HT capable. + */ + ath_tx_send_ampdu(sc, tid, bf, txctl); } else { - ath_tx_send_normal(sc, txctl->txq, &bf_head); + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); + + bf->bf_state.bfs_ftype = txctl->frame_type; + bf->bf_state.bfs_paprd = txctl->paprd; + + if (bf->bf_state.bfs_paprd) + ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc, + bf->bf_state.bfs_paprd); + + ath_tx_send_normal(sc, txctl->txq, NULL, &bf_head); } -tx_done: spin_unlock_bh(&txctl->txq->axq_lock); } @@@ -1729,23 -1726,66 +1722,23 @@@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, struct ath_tx_control *txctl) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = info->control.sta; struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_txq *txq = txctl->txq; struct ath_buf *bf; - int q, r; - - bf = ath_tx_get_buffer(sc); - if (!bf) { - ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); - return -1; - } - - r = ath_tx_setup_buffer(hw, bf, skb, txctl); - if (unlikely(r)) { - ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); - - /* upon ath_tx_processq() this TX queue will be resumed, we - * guarantee this will happen by knowing beforehand that - * we will at least have to run TX completionon one buffer - * on the queue */ - spin_lock_bh(&txq->axq_lock); - if (!txq->stopped && txq->axq_depth > 1) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_return_buffer(sc, bf); - - return r; - } - - q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - spin_lock_bh(&txq->axq_lock); - if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { - ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - ath_tx_start_dma(sc, bf, txctl); - - return 0; -} - -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; int padpos, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; + int frmlen = skb->len + FCS_LEN; + int q; + + /* NOTE: sta can be NULL according to net/mac80211.h */ + if (sta) + txctl->an = (struct ath_node *)sta->drv_priv; - memset(&txctl, 0, sizeof(struct ath_tx_control)); + if (info->control.hw_key) + frmlen += info->control.hw_key->icv_len; /* * As a temporary workaround, assign seq# here; this will likely need @@@ -1762,37 -1802,30 +1755,37 @@@ /* Add the padding after the header if this is not already done */ padpos = ath9k_cmn_padpos(hdr->frame_control); padsize = padpos & 3; - if (padsize && skb->len>padpos) { - if (skb_headroom(skb) < padsize) { - ath_print(common, ATH_DBG_XMIT, - "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } + if (padsize && skb->len > padpos) { + if (skb_headroom(skb) < padsize) + return -ENOMEM; + skb_push(skb, padsize); memmove(skb->data, skb->data + padsize, padpos); } - txctl.txq = sc->beacon.cabq; + setup_frame_info(hw, skb, frmlen); - ath_print(common, ATH_DBG_XMIT, - "transmitting CABQ packet, skb: %p\n", skb); + /* + * At this point, the vif, hw_key and sta pointers in the tx control + * info are no longer valid (overwritten by the ath_frame_info data. + */ + + bf = ath_tx_setup_buffer(hw, txctl->txq, skb); + if (unlikely(!bf)) + return -ENOMEM; - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; + q = skb_get_queue_mapping(skb); + spin_lock_bh(&txq->axq_lock); + if (txq == sc->tx.txq_map[q] && + ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { + ath_mac80211_stop_queue(sc, q); + txq->stopped = 1; } + spin_unlock_bh(&txq->axq_lock); - return; -exit: - dev_kfree_skb_any(skb); + ath_tx_start_dma(sc, bf, txctl); + + return 0; } /*****************/ @@@ -1800,8 -1833,7 +1793,8 @@@ /*****************/ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_wiphy *aphy, int tx_flags) + struct ath_wiphy *aphy, int tx_flags, int ftype, + struct ath_txq *txq) { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@@ -1809,7 -1841,7 +1802,7 @@@ struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; int q, padpos, padsize; - ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); + ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); if (aphy) hw = aphy->hw; @@@ -1835,24 -1867,24 +1828,24 @@@ if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; - ath_print(common, ATH_DBG_PS, - "Going back to sleep after having " - "received TX status (0x%lx)\n", + ath_dbg(common, ATH_DBG_PS, + "Going back to sleep after having received TX status (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK)); } - if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) - ath9k_tx_status(hw, skb); + if (unlikely(ftype)) + ath9k_tx_status(hw, skb, ftype); else { q = skb_get_queue_mapping(skb); - if (q >= 4) - q = 0; - - if (--sc->tx.pending_frames[q] < 0) - sc->tx.pending_frames[q] = 0; + if (txq == sc->tx.txq_map[q]) { + spin_lock_bh(&txq->axq_lock); + if (WARN_ON(--txq->pending_frames < 0)) + txq->pending_frames = 0; + spin_unlock_bh(&txq->axq_lock); + } ieee80211_tx_status(hw, skb); } @@@ -1880,14 -1912,15 +1873,14 @@@ static void ath_tx_complete_buf(struct bf->bf_buf_addr = 0; if (bf->bf_state.bfs_paprd) { - if (time_after(jiffies, - bf->bf_state.bfs_paprd_timestamp + - msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) + if (!sc->paprd_pending) dev_kfree_skb_any(skb); else complete(&sc->paprd_complete); } else { - ath_debug_stat_tx(sc, txq, bf, ts); - ath_tx_complete(sc, skb, bf->aphy, tx_flags); + ath_debug_stat_tx(sc, bf, ts); + ath_tx_complete(sc, skb, bf->aphy, tx_flags, + bf->bf_state.bfs_ftype, txq); } /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't * accidentally reference it later. @@@ -1902,15 -1935,42 +1895,15 @@@ spin_unlock_irqrestore(&sc->tx.txbuflock, flags); } -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_status *ts, int txok) -{ - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; - - if (bf->bf_lastbf->bf_tx_aborted) - return 0; - - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ts->ts_seqnum; - memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); - } - - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; - - bf = bf->bf_next; - } - - return nbad; -} - static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, - int nbad, int txok, bool update_rc) + int nframes, int nbad, int txok, bool update_rc) { struct sk_buff *skb = bf->bf_mpdu; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = bf->aphy->hw; + struct ath_softc *sc = bf->aphy->sc; + struct ath_hw *ah = sc->sc_ah; u8 i, tx_rateindex; if (txok) @@@ -1924,32 -1984,22 +1917,32 @@@ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; - BUG_ON(nbad > bf->bf_nframes); + BUG_ON(nbad > nframes); - tx_info->status.ampdu_len = bf->bf_nframes; - tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; + tx_info->status.ampdu_len = nframes; + tx_info->status.ampdu_ack_len = nframes - nbad; } if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { - if (ieee80211_is_data(hdr->frame_control)) { - if (ts->ts_flags & - (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) - tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; - if ((ts->ts_status & ATH9K_TXERR_XRETRY) || - (ts->ts_status & ATH9K_TXERR_FIFO)) - tx_info->pad[0] |= ATH_TX_INFO_XRETRY; - } + /* + * If an underrun error is seen assume it as an excessive + * retry only if max frame trigger level has been reached + * (2 KB for single stream, and 4 KB for dual stream). + * Adjust the long retry as if the frame was tried + * hw->max_rate_tries times to affect how rate control updates + * PER for the failed rate. + * In case of congestion on the bus penalizing this type of + * underruns should help hardware actually transmit new frames + * successfully by eventually preferring slower rates. + * This itself should also alleviate congestion on the bus. + */ + if (ieee80211_is_data(hdr->frame_control) && + (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | + ATH9K_TX_DELIM_UNDERRUN)) && + ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max) + tx_info->status.rates[tx_rateindex].count = + hw->max_rate_tries; } for (i = tx_rateindex + 1; i < hw->max_rates; i++) { @@@ -1960,13 -2010,16 +1953,13 @@@ tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; } -static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) +static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum) { - int qnum; - - qnum = ath_get_mac80211_qnum(txq->axq_class, sc); - if (qnum == -1) - return; + struct ath_txq *txq; + txq = sc->tx.txq_map[qnum]; spin_lock_bh(&txq->axq_lock); - if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { + if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { if (ath_mac80211_start_queue(sc, qnum)) txq->stopped = 0; } @@@ -1983,11 -2036,10 +1976,11 @@@ static void ath_tx_processq(struct ath_ struct ath_tx_status ts; int txok; int status; + int qnum; - ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), - txq->axq_link); + ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", + txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), + txq->axq_link); for (;;) { spin_lock_bh(&txq->axq_lock); @@@ -2056,19 -2108,15 +2049,19 @@@ */ if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, + true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (sc->sc_flags & SC_OP_TXAGGR) @@@ -2102,8 -2150,8 +2095,8 @@@ static void ath_tx_complete_poll_work(s } if (needreset) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, - "tx hung, resetting the chip\n"); + ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, + "tx hung, resetting the chip\n"); ath9k_ps_wakeup(sc); ath_reset(sc, true); ath9k_ps_restore(sc); @@@ -2138,15 -2186,14 +2131,15 @@@ void ath_tx_edma_tasklet(struct ath_sof struct list_head bf_head; int status; int txok; + int qnum; for (;;) { status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); if (status == -EINPROGRESS) break; if (status == -EIO) { - ath_print(common, ATH_DBG_XMIT, - "Error processing tx status\n"); + ath_dbg(common, ATH_DBG_XMIT, + "Error processing tx status\n"); break; } @@@ -2179,20 -2226,16 +2172,20 @@@ if (!bf_isampdu(bf)) { if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true); + ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true); } + qnum = skb_get_queue_mapping(bf->bf_mpdu); + if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); + ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, + txok, true); else ath_tx_complete_buf(sc, bf, txq, &bf_head, &txs, txok, 0); - ath_wake_mac80211_queue(sc, txq); + if (txq == sc->tx.txq_map[qnum]) + ath_wake_mac80211_queue(sc, qnum); spin_lock_bh(&txq->axq_lock); if (!list_empty(&txq->txq_fifo_pending)) { @@@ -2257,16 -2300,16 +2250,16 @@@ int ath_tx_init(struct ath_softc *sc, i error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, "tx", nbufs, 1, 1); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", error); + ath_err(common, + "Failed to allocate tx descriptors: %d\n", error); goto err; } error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, "beacon", ATH_BCBUF, 1, 1); if (error != 0) { - ath_print(common, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", error); + ath_err(common, + "Failed to allocate beacon descriptors: %d\n", error); goto err; } @@@ -2324,7 -2367,7 +2317,7 @@@ void ath_tx_node_init(struct ath_softc for (acno = 0, ac = &an->ac[acno]; acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; - ac->qnum = sc->tx.hwq_map[acno]; + ac->txq = sc->tx.txq_map[acno]; INIT_LIST_HEAD(&ac->tid_q); } } @@@ -2334,13 -2377,17 +2327,13 @@@ void ath_tx_node_cleanup(struct ath_sof struct ath_atx_ac *ac; struct ath_atx_tid *tid; struct ath_txq *txq; - int i, tidno; + int tidno; for (tidno = 0, tid = &an->tid[tidno]; tidno < WME_NUM_TID; tidno++, tid++) { - i = tid->ac->qnum; - - if (!ATH_TXQ_SETUP(sc, i)) - continue; - txq = &sc->tx.txq[i]; ac = tid->ac; + txq = ac->txq; spin_lock_bh(&txq->axq_lock); diff --combined drivers/net/wireless/orinoco/wext.c index 8e65ffc4cb0a,e5afabee60d1..e793679e2e19 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@@ -893,14 -893,6 +893,14 @@@ static int orinoco_ioctl_set_auth(struc */ break; + case IW_AUTH_MFP: + /* Management Frame Protection not supported. + * Only fail if set to required. + */ + if (param->value == IW_AUTH_MFP_REQUIRED) + ret = -EINVAL; + break; + case IW_AUTH_KEY_MGMT: /* wl_lkm implies value 2 == PSK for Hermes I * which ties in with WEXT @@@ -919,10 -911,10 +919,10 @@@ */ if (param->value) { priv->tkip_cm_active = 1; - ret = hermes_enable_port(hw, 0); + ret = hermes_disable_port(hw, 0); } else { priv->tkip_cm_active = 0; - ret = hermes_disable_port(hw, 0); + ret = hermes_enable_port(hw, 0); } break; diff --combined net/mac80211/tx.c index 5d6b0759d18c,7a637b80a62e..0ee56bb0ea7e --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@@ -622,8 -622,7 +622,8 @@@ ieee80211_tx_h_rate_ctrl(struct ieee802 txrc.max_rate_idx = -1; else txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; - txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; + txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || + tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); /* set up RTS protection if desired */ if (len > tx->local->hw.wiphy->rts_threshold) { @@@ -666,11 -665,10 +666,11 @@@ if (unlikely(info->control.rates[0].idx < 0)) return TX_DROP; - if (txrc.reported_rate.idx < 0) + if (txrc.reported_rate.idx < 0) { txrc.reported_rate = info->control.rates[0]; - - if (tx->sta) + if (tx->sta && ieee80211_is_data(hdr->frame_control)) + tx->sta->last_tx_rate = txrc.reported_rate; + } else if (tx->sta) tx->sta->last_tx_rate = txrc.reported_rate; if (unlikely(!info->control.rates[0].count)) @@@ -1035,7 -1033,6 +1035,7 @@@ static bool __ieee80211_parse_tx_radiot struct ieee80211_radiotap_header *rthdr = (struct ieee80211_radiotap_header *) skb->data; struct ieee80211_supported_band *sband; + bool hw_frag; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, NULL); @@@ -1045,9 -1042,6 +1045,9 @@@ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; tx->flags &= ~IEEE80211_TX_FRAGMENTED; + /* packet is fragmented in HW if we have a non-NULL driver callback */ + hw_frag = (tx->local->ops->set_frag_threshold != NULL); + /* * for every radiotap entry that is present * (ieee80211_radiotap_iterator_next returns -ENOENT when no more @@@ -1084,8 -1078,7 +1084,8 @@@ } if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP) info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT; - if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) + if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) && + !hw_frag) tx->flags |= IEEE80211_TX_FRAGMENTED; break; @@@ -1188,10 -1181,8 +1188,10 @@@ ieee80211_tx_prepare(struct ieee80211_s /* * Set this flag (used below to indicate "automatic fragmentation"), * it will be cleared/left by radiotap as desired. + * Only valid when fragmentation is done by the stack. */ - tx->flags |= IEEE80211_TX_FRAGMENTED; + if (!local->ops->set_frag_threshold) + tx->flags |= IEEE80211_TX_FRAGMENTED; /* process and remove the injection radiotap header */ if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { @@@ -1746,15 -1737,13 +1746,13 @@@ netdev_tx_t ieee80211_subif_start_xmit( int nh_pos, h_pos; struct sta_info *sta = NULL; u32 sta_flags = 0; + struct sk_buff *tmp_skb; if (unlikely(skb->len < ETH_HLEN)) { ret = NETDEV_TX_OK; goto fail; } - nh_pos = skb_network_header(skb) - skb->data; - h_pos = skb_transport_header(skb) - skb->data; - /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; @@@ -1927,6 -1916,20 +1925,20 @@@ goto fail; } + /* + * If the skb is shared we need to obtain our own copy. + */ + if (skb_shared(skb)) { + tmp_skb = skb; + skb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(tmp_skb); + + if (!skb) { + ret = NETDEV_TX_OK; + goto fail; + } + } + hdr.frame_control = fc; hdr.duration_id = 0; hdr.seq_ctrl = 0; @@@ -1945,6 -1948,9 +1957,9 @@@ encaps_len = 0; } + nh_pos = skb_network_header(skb) - skb->data; + h_pos = skb_transport_header(skb) - skb->data; + skb_pull(skb, skip_header_bytes); nh_pos -= skip_header_bytes; h_pos -= skip_header_bytes; @@@ -2315,7 -2321,7 +2330,7 @@@ struct sk_buff *ieee80211_beacon_get_ti txrc.max_rate_idx = -1; else txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; - txrc.ap = true; + txrc.bss = true; rate_control_get_rate(sdata, NULL, &txrc); info->control.vif = vif;