diff options
Diffstat (limited to 'drivers/net/wireless/ath9k')
-rw-r--r-- | drivers/net/wireless/ath9k/Kconfig | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/ath9k.h | 64 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/beacon.c | 383 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/core.c | 423 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/core.h | 295 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.c | 312 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/hw.h | 120 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 1275 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/phy.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/rc.c | 280 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/rc.h | 222 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/recv.c | 98 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/reg.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/xmit.c | 418 |
14 files changed, 2023 insertions, 1888 deletions
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig index 9e19dcceb3a..80a69243041 100644 --- a/drivers/net/wireless/ath9k/Kconfig +++ b/drivers/net/wireless/ath9k/Kconfig @@ -1,6 +1,9 @@ config ATH9K tristate "Atheros 802.11n wireless cards support" depends on PCI && MAC80211 && WLAN_80211 + select MAC80211_LEDS + select LEDS_CLASS + select NEW_LEDS ---help--- This module adds support for wireless adapters based on Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d1b0fbae5a3..accace5f7ef 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -144,6 +144,7 @@ struct ath_desc { #define ATH9K_TXDESC_EXT_AND_CTL 0x0080 #define ATH9K_TXDESC_VMF 0x0100 #define ATH9K_TXDESC_FRAG_IS_ON 0x0200 +#define ATH9K_TXDESC_CAB 0x0400 #define ATH9K_RXDESC_INTREQ 0x0020 @@ -564,8 +565,6 @@ enum ath9k_cipher { #define CTL_5GHT40 8 #define AR_EEPROM_MAC(i) (0x1d+(i)) -#define EEP_SCALE 100 -#define EEP_DELTA 10 #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 @@ -606,9 +605,6 @@ struct ath9k_country_entry { #define REG_CLR_BIT(_a, _r, _f) \ REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) -#define ATH9K_COMP_BUF_MAX_SIZE 9216 -#define ATH9K_COMP_BUF_ALIGN_SIZE 512 - #define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 #define INIT_AIFS 2 @@ -632,12 +628,6 @@ struct ath9k_country_entry { (IEEE80211_WEP_IVLEN + \ IEEE80211_WEP_KIDLEN + \ IEEE80211_WEP_CRCLEN)) -#define IEEE80211_MAX_LEN (2300 + FCS_LEN + \ - (IEEE80211_WEP_IVLEN + \ - IEEE80211_WEP_KIDLEN + \ - IEEE80211_WEP_CRCLEN)) - -#define MAX_REG_ADD_COUNT 129 #define MAX_RATE_POWER 63 enum ath9k_power_mode { @@ -707,13 +697,6 @@ enum phytype { }; #define PHY_CCK PHY_DS -enum start_adhoc_option { - START_ADHOC_NO_11A, - START_ADHOC_PER_11D, - START_ADHOC_IN_11A, - START_ADHOC_IN_11B, -}; - enum ath9k_tp_scale { ATH9K_TP_SCALE_MAX = 0, ATH9K_TP_SCALE_50, @@ -769,14 +752,11 @@ struct ath9k_node_stats { #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) -enum ath9k_gpio_output_mux_type { - ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT, - ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, - ATH9K_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, - ATH9K_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, - ATH9K_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, - ATH9K_GPIO_OUTPUT_MUX_NUM_ENTRIES -}; +#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 +#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 +#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 enum { ATH9K_RESET_POWER_ON, @@ -790,19 +770,20 @@ struct ath_hal { u32 ah_magic; u16 ah_devid; u16 ah_subvendorid; - struct ath_softc *ah_sc; - void __iomem *ah_sh; - u16 ah_countryCode; u32 ah_macVersion; u16 ah_macRev; u16 ah_phyRev; u16 ah_analog5GhzRev; u16 ah_analog2GhzRev; - u8 ah_decompMask[ATH9K_DECOMP_MASK_SIZE]; - u32 ah_flags; + + void __iomem *ah_sh; + struct ath_softc *ah_sc; enum ath9k_opmode ah_opmode; struct ath9k_ops_config ah_config; struct ath9k_hw_capabilities ah_caps; + + u16 ah_countryCode; + u32 ah_flags; int16_t ah_powerLimit; u16 ah_maxPowerLevel; u32 ah_tpScale; @@ -812,15 +793,17 @@ struct ath_hal { u16 ah_currentRD5G; u16 ah_currentRD2G; char ah_iso[4]; - enum start_adhoc_option ah_adHocMode; - bool ah_commonMode; + struct ath9k_channel ah_channels[150]; - u32 ah_nchan; struct ath9k_channel *ah_curchan; - u16 ah_rfsilent; - bool ah_rfkillEnabled; + u32 ah_nchan; + bool ah_isPciExpress; u16 ah_txTrigLevel; + u16 ah_rfsilent; + u32 ah_rfkill_gpio; + u32 ah_rfkill_polarity; + #ifndef ATH_NF_PER_CHAN struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; #endif @@ -853,7 +836,7 @@ bool ath9k_regd_init_channels(struct ath_hal *ah, u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints); -bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, +bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode, u8 txchainmask, u8 rxchainmask, @@ -871,7 +854,7 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, u8 rxchainmask, bool longcal, bool *isCalDone); -int16_t ath9k_hw_getchan_noise(struct ath_hal *ah, +s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan); void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId); @@ -1018,4 +1001,9 @@ void ath9k_hw_get_channel_centers(struct ath_hal *ah, bool ath9k_get_channel_edges(struct ath_hal *ah, u16 flags, u16 *low, u16 *high); +void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, + u32 ah_signal_type); +void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value); +u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio); +void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio); #endif diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 00a0eaa0886..9e15c30bbc0 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -16,7 +16,6 @@ /* Implementation of beacon processing. */ -#include <asm/unaligned.h> #include "core.h" /* @@ -26,14 +25,13 @@ * the operating mode of the station (AP or AdHoc). Parameters are AIFS * settings and channel width min/max */ - static int ath_beaconq_config(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; struct ath9k_tx_queue_info qi; ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi); - if (sc->sc_opmode == ATH9K_M_HOSTAP) { + if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { /* Always burst out beacon and CAB traffic. */ qi.tqi_aifs = 1; qi.tqi_cwmin = 0; @@ -63,19 +61,18 @@ static int ath_beaconq_config(struct ath_softc *sc) * up all required antenna switch parameters, rate codes, and channel flags. * Beacons are always sent out at the lowest rate, and are not retried. */ - static void ath_beacon_setup(struct ath_softc *sc, - struct ath_vap *avp, struct ath_buf *bf) + struct ath_vap *avp, struct ath_buf *bf) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ath_hal *ah = sc->sc_ah; struct ath_desc *ds; - int flags, antenna; + struct ath9k_11n_rate_series series[4]; const struct ath9k_rate_table *rt; + int flags, antenna; u8 rix, rate; int ctsrate = 0; int ctsduration = 0; - struct ath9k_11n_rate_series series[4]; DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", __func__, skb, skb->len); @@ -85,7 +82,7 @@ static void ath_beacon_setup(struct ath_softc *sc, flags = ATH9K_TXDESC_NOACK; - if (sc->sc_opmode == ATH9K_M_IBSS && + if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS && (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { ds->ds_link = bf->bf_daddr; /* self-linked */ flags |= ATH9K_TXDESC_VEOL; @@ -111,27 +108,28 @@ static void ath_beacon_setup(struct ath_softc *sc, rix = 0; rt = sc->sc_currates; rate = rt->info[rix].rateCode; - if (sc->sc_flags & ATH_PREAMBLE_SHORT) + if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) rate |= rt->info[rix].shortPreamble; - ath9k_hw_set11n_txdesc(ah, ds - , skb->len + FCS_LEN /* frame length */ - , ATH9K_PKT_TYPE_BEACON /* Atheros packet type */ - , avp->av_btxctl.txpower /* txpower XXX */ - , ATH9K_TXKEYIX_INVALID /* no encryption */ - , ATH9K_KEY_TYPE_CLEAR /* no encryption */ - , flags /* no ack, veol for beacons */ + ath9k_hw_set11n_txdesc(ah, ds, + skb->len + FCS_LEN, /* frame length */ + ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ + avp->av_btxctl.txpower, /* txpower XXX */ + ATH9K_TXKEYIX_INVALID, /* no encryption */ + ATH9K_KEY_TYPE_CLEAR, /* no encryption */ + flags /* no ack, + veol for beacons */ ); /* NB: beacon's BufLen must be a multiple of 4 bytes */ - ath9k_hw_filltxdesc(ah, ds - , roundup(skb->len, 4) /* buffer length */ - , true /* first segment */ - , true /* last segment */ - , ds /* first descriptor */ + ath9k_hw_filltxdesc(ah, ds, + roundup(skb->len, 4), /* buffer length */ + true, /* first segment */ + true, /* last segment */ + ds /* first descriptor */ ); - memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); + memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; series[0].ChSel = sc->sc_tx_chainmask; @@ -140,55 +138,6 @@ static void ath_beacon_setup(struct ath_softc *sc, ctsrate, ctsduration, series, 4, 0); } -/* Move everything from the vap's mcast queue to the hardware cab queue. - * Caller must hold mcasq lock and cabq lock - * XXX MORE_DATA bit? - */ -static void empty_mcastq_into_cabq(struct ath_hal *ah, - struct ath_txq *mcastq, struct ath_txq *cabq) -{ - struct ath_buf *bfmcast; - - BUG_ON(list_empty(&mcastq->axq_q)); - - bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list); - - /* link the descriptors */ - if (!cabq->axq_link) - ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr); - else - *cabq->axq_link = bfmcast->bf_daddr; - - /* append the private vap mcast list to the cabq */ - - cabq->axq_depth += mcastq->axq_depth; - cabq->axq_totalqueued += mcastq->axq_totalqueued; - cabq->axq_linkbuf = mcastq->axq_linkbuf; - cabq->axq_link = mcastq->axq_link; - list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q); - mcastq->axq_depth = 0; - mcastq->axq_totalqueued = 0; - mcastq->axq_linkbuf = NULL; - mcastq->axq_link = NULL; -} - -/* This is only run at DTIM. We move everything from the vap's mcast queue - * to the hardware cab queue. Caller must hold the mcastq lock. */ -static void trigger_mcastq(struct ath_hal *ah, - struct ath_txq *mcastq, struct ath_txq *cabq) -{ - spin_lock_bh(&cabq->axq_lock); - - if (!list_empty(&mcastq->axq_q)) - empty_mcastq_into_cabq(ah, mcastq, cabq); - - /* cabq is gated by beacon so it is safe to start here */ - if (!list_empty(&cabq->axq_q)) - ath9k_hw_txstart(ah, cabq->axq_qnum); - - spin_unlock_bh(&cabq->axq_lock); -} - /* * Generate beacon frame and queue cab data for a vap. * @@ -199,39 +148,36 @@ static void trigger_mcastq(struct ath_hal *ah, */ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) { - struct ath_hal *ah = sc->sc_ah; struct ath_buf *bf; struct ath_vap *avp; struct sk_buff *skb; - int cabq_depth; - int mcastq_depth; - int is_beacon_dtim = 0; - unsigned int curlen; struct ath_txq *cabq; - struct ath_txq *mcastq; struct ieee80211_tx_info *info; + int cabq_depth; + avp = sc->sc_vaps[if_id]; + ASSERT(avp); - mcastq = &avp->av_mcastq; cabq = sc->sc_cabq; - ASSERT(avp); - if (avp->av_bcbuf == NULL) { DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n", __func__, avp, avp->av_bcbuf); return NULL; } + bf = avp->av_bcbuf; - skb = (struct sk_buff *) bf->bf_mpdu; + skb = (struct sk_buff *)bf->bf_mpdu; + if (skb) { + pci_unmap_single(sc->pdev, bf->bf_dmacontext, + skb_end_pointer(skb) - skb->head, + PCI_DMA_TODEVICE); + } - /* - * Update dynamic beacon contents. If this returns - * non-zero then we need to remap the memory because - * the beacon frame changed size (probably because - * of the TIM bitmap). - */ - curlen = skb->len; + skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); + bf->bf_mpdu = skb; + if (skb == NULL) + return NULL; info = IEEE80211_SKB_CB(skb); if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -239,29 +185,18 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) * TODO: make sure the seq# gets assigned properly (vs. other * TX frames) */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; sc->seq_no += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); } - /* XXX: spin_lock_bh should not be used here, but sparse bitches - * otherwise. We should fix sparse :) */ - spin_lock_bh(&mcastq->axq_lock); - mcastq_depth = avp->av_mcastq.axq_depth; - - if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) == - 1) { - ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); - bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); - } else { - pci_dma_sync_single_for_cpu(sc->pdev, - bf->bf_buf_addr, - skb_tailroom(skb), - PCI_DMA_TODEVICE); - } + bf->bf_buf_addr = bf->bf_dmacontext = + pci_map_single(sc->pdev, skb->data, + skb_end_pointer(skb) - skb->head, + PCI_DMA_TODEVICE); + + skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); /* * if the CABQ traffic from previous DTIM is pending and the current @@ -275,9 +210,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) cabq_depth = cabq->axq_depth; spin_unlock_bh(&cabq->axq_lock); - is_beacon_dtim = avp->av_boff.bo_tim[4] & 1; - - if (mcastq_depth && is_beacon_dtim && cabq_depth) { + if (skb && cabq_depth) { /* * Unlock the cabq lock as ath_tx_draintxq acquires * the lock again which is a common function and that @@ -297,10 +230,11 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) * Enable the CAB queue before the beacon queue to * insure cab frames are triggered by this beacon. */ - if (is_beacon_dtim) - trigger_mcastq(ah, mcastq, cabq); + while (skb) { + ath_tx_cabq(sc, skb); + skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); + } - spin_unlock_bh(&mcastq->axq_lock); return bf; } @@ -308,7 +242,6 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) * Startup beacon transmission for adhoc mode when they are sent entirely * by the hardware using the self-linked descriptor + veol trick. */ - static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) { struct ath_hal *ah = sc->sc_ah; @@ -345,12 +278,11 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) * min/max, and enable aifs). The info structure does not need to be * persistant. */ - int ath_beaconq_setup(struct ath_hal *ah) { struct ath9k_tx_queue_info qi; - memzero(&qi, sizeof(qi)); + memset(&qi, 0, sizeof(qi)); qi.tqi_aifs = 1; qi.tqi_cwmin = 0; qi.tqi_cwmax = 0; @@ -366,29 +298,27 @@ int ath_beaconq_setup(struct ath_hal *ah) * the ATH interface. This routine also calculates the beacon "slot" for * staggared beacons in the mBSSID case. */ - int ath_beacon_alloc(struct ath_softc *sc, int if_id) { struct ath_vap *avp; - struct ieee80211_hdr *wh; + struct ieee80211_hdr *hdr; struct ath_buf *bf; struct sk_buff *skb; + __le64 tstamp; avp = sc->sc_vaps[if_id]; ASSERT(avp); /* Allocate a beacon descriptor if we haven't done so. */ if (!avp->av_bcbuf) { - /* - * Allocate beacon state for hostap/ibss. We know - * a buffer is available. - */ + /* Allocate beacon state for hostap/ibss. We know + * a buffer is available. */ avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, - struct ath_buf, list); + struct ath_buf, list); list_del(&avp->av_bcbuf->list); - if (sc->sc_opmode == ATH9K_M_HOSTAP || + if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || !(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { int slot; /* @@ -421,17 +351,16 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { skb = (struct sk_buff *)bf->bf_mpdu; - ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); + pci_unmap_single(sc->pdev, bf->bf_dmacontext, + skb_end_pointer(skb) - skb->head, + PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; } /* - * NB: the beacon data buffer must be 32-bit aligned; - * we assume the wbuf routines will return us something - * with this alignment (perhaps should assert). - * FIXME: Fill avp->av_boff.bo_tim,avp->av_btxctl.txpower and + * NB: the beacon data buffer must be 32-bit aligned. + * FIXME: Fill avp->av_btxctl.txpower and * avp->av_btxctl.shortPreamble */ skb = ieee80211_beacon_get(sc->hw, avp->av_if_data); @@ -441,6 +370,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) return -ENOMEM; } + tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + sc->bc_tstamp = le64_to_cpu(tstamp); + /* * Calculate a TSF adjustment factor required for * staggered beacons. Note that we assume the format @@ -452,9 +384,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) __le64 val; int intval; - /* FIXME: Use default value for now: Sujith */ - - intval = ATH_DEFAULT_BINTVAL; + intval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; /* * The beacon interval is in TU's; the TSF in usecs. @@ -475,12 +406,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) __func__, "stagger", avp->av_bslot, intval, (unsigned long long)tsfadjust); - wh = (struct ieee80211_hdr *)skb->data; - memcpy(&wh[1], &val, sizeof(val)); + hdr = (struct ieee80211_hdr *)skb->data; + memcpy(&hdr[1], &val, sizeof(val)); } - bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); + bf->bf_buf_addr = bf->bf_dmacontext = + pci_map_single(sc->pdev, skb->data, + skb_end_pointer(skb) - skb->head, + PCI_DMA_TODEVICE); bf->bf_mpdu = skb; return 0; @@ -490,9 +423,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) * Reclaim beacon resources and return buffer to the pool. * * Checks the VAP to put the beacon frame buffer back to the ATH object - * queue, and de-allocates any wbuf frames that were sent as CAB traffic. + * queue, and de-allocates any skbs that were sent as CAB traffic. */ - void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) { if (avp->av_bcbuf != NULL) { @@ -506,8 +438,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; - ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); + pci_unmap_single(sc->pdev, bf->bf_dmacontext, + skb_end_pointer(skb) - skb->head, + PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; } @@ -518,44 +451,14 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) } /* - * Reclaim beacon resources and return buffer to the pool. - * - * This function will free any wbuf frames that are still attached to the - * beacon buffers in the ATH object. Note that this does not de-allocate - * any wbuf objects that are in the transmit queue and have not yet returned - * to the ATH object. -*/ - -void ath_beacon_free(struct ath_softc *sc) -{ - struct ath_buf *bf; - - list_for_each_entry(bf, &sc->sc_bbuf, list) { - if (bf->bf_mpdu != NULL) { - struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu; - ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE, - get_dma_mem_context(bf, bf_dmacontext)); - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - } - } -} - -/* * Tasklet for Sending Beacons * * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame * contents are done as needed and the slot time is also adjusted based on * current state. - * - * This tasklet is not scheduled, it's called in ISR context. */ - void ath9k_beacon_tasklet(unsigned long data) { -#define TSF_TO_TU(_h,_l) \ - ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) - struct ath_softc *sc = (struct ath_softc *)data; struct ath_hal *ah = sc->sc_ah; struct ath_buf *bf = NULL; @@ -568,7 +471,7 @@ void ath9k_beacon_tasklet(unsigned long data) u32 tsftu; u16 intval; - if (sc->sc_noreset) { + if (sc->sc_flags & SC_OP_NO_RESET) { show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, &rx_clear, &rx_frame, @@ -581,6 +484,8 @@ void ath9k_beacon_tasklet(unsigned long data) * and wait for the next. Missed beacons indicate * a problem and should not occur. If we miss too * many consecutive beacons reset the device. + * + * FIXME: Clean up this mess !! */ if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) { sc->sc_bmisscount++; @@ -590,25 +495,22 @@ void ath9k_beacon_tasklet(unsigned long data) * (in that layer). */ if (sc->sc_bmisscount < BSTUCK_THRESH) { - if (sc->sc_noreset) { + if (sc->sc_flags & SC_OP_NO_RESET) { DPRINTF(sc, ATH_DBG_BEACON, "%s: missed %u consecutive beacons\n", __func__, sc->sc_bmisscount); if (show_cycles) { /* - * Display cycle counter stats - * from HW to aide in debug of - * stickiness. + * Display cycle counter stats from HW + * to aide in debug of stickiness. */ - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: busy times: rx_clear=%d, " "rx_frame=%d, tx_frame=%d\n", __func__, rx_clear, rx_frame, tx_frame); } else { - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: unable to obtain " "busy times\n", __func__); } @@ -618,10 +520,9 @@ void ath9k_beacon_tasklet(unsigned long data) __func__, sc->sc_bmisscount); } } else if (sc->sc_bmisscount >= BSTUCK_THRESH) { - if (sc->sc_noreset) { + if (sc->sc_flags & SC_OP_NO_RESET) { if (sc->sc_bmisscount == BSTUCK_THRESH) { - DPRINTF(sc, - ATH_DBG_BEACON, + DPRINTF(sc, ATH_DBG_BEACON, "%s: beacon is officially " "stuck\n", __func__); ath9k_hw_dmaRegDump(ah); @@ -633,13 +534,12 @@ void ath9k_beacon_tasklet(unsigned long data) ath_bstuck_process(sc); } } - return; } + if (sc->sc_bmisscount != 0) { - if (sc->sc_noreset) { - DPRINTF(sc, - ATH_DBG_BEACON, + if (sc->sc_flags & SC_OP_NO_RESET) { + DPRINTF(sc, ATH_DBG_BEACON, "%s: resume beacon xmit after %u misses\n", __func__, sc->sc_bmisscount); } else { @@ -656,17 +556,19 @@ void ath9k_beacon_tasklet(unsigned long data) * on the tsf to safeguard against missing an swba. */ - /* FIXME: Use default value for now - Sujith */ - intval = ATH_DEFAULT_BINTVAL; + intval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU(tsf>>32, tsf); slot = ((tsftu % intval) * ATH_BCBUF) / intval; if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF]; + DPRINTF(sc, ATH_DBG_BEACON, - "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", - __func__, slot, (unsigned long long) tsf, tsftu, - intval, if_id); + "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n", + __func__, slot, (unsigned long long)tsf, tsftu, + intval, if_id); + bfaddr = 0; if (if_id != ATH_IF_ID_ANY) { bf = ath_beacon_generate(sc, if_id); @@ -717,22 +619,20 @@ void ath9k_beacon_tasklet(unsigned long data) sc->ast_be_xmit += bc; /* XXX per-vap? */ } -#undef TSF_TO_TU } /* * Tasklet for Beacon Stuck processing * * Processing for Beacon Stuck. - * Basically calls the ath_internal_reset function to reset the chip. + * Basically resets the chip. */ - void ath_bstuck_process(struct ath_softc *sc) { DPRINTF(sc, ATH_DBG_BEACON, "%s: stuck beacon; resetting (bmiss count %u)\n", __func__, sc->sc_bmisscount); - ath_internal_reset(sc); + ath_reset(sc, false); } /* @@ -750,40 +650,32 @@ void ath_bstuck_process(struct ath_softc *sc) * interrupt when we stop seeing beacons from the AP * we've associated with. */ - void ath_beacon_config(struct ath_softc *sc, int if_id) { -#define TSF_TO_TU(_h,_l) \ - ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) struct ath_hal *ah = sc->sc_ah; - u32 nexttbtt, intval; struct ath_beacon_config conf; enum ath9k_opmode av_opmode; + u32 nexttbtt, intval; if (if_id != ATH_IF_ID_ANY) av_opmode = sc->sc_vaps[if_id]->av_opmode; else - av_opmode = sc->sc_opmode; + av_opmode = sc->sc_ah->ah_opmode; - memzero(&conf, sizeof(struct ath_beacon_config)); + memset(&conf, 0, sizeof(struct ath_beacon_config)); - /* FIXME: Use default values for now - Sujith */ - /* Query beacon configuration first */ - /* - * Protocol stack doesn't support dynamic beacon configuration, - * use default configurations. - */ - conf.beacon_interval = ATH_DEFAULT_BINTVAL; + conf.beacon_interval = sc->hw->conf.beacon_int ? + sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; conf.listen_interval = 1; conf.dtim_period = conf.beacon_interval; conf.dtim_count = 1; conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval; /* extract tstamp from last beacon and convert to TU */ - nexttbtt = TSF_TO_TU(get_unaligned_le32(conf.u.last_tstamp + 4), - get_unaligned_le32(conf.u.last_tstamp)); + nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp); + /* XXX conditionalize multi-bss support? */ - if (sc->sc_opmode == ATH9K_M_HOSTAP) { + if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { /* * For multi-bss ap support beacons are either staggered * evenly over N slots or burst together. For the former @@ -797,14 +689,16 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) intval = conf.beacon_interval & ATH9K_BEACON_PERIOD; } - if (nexttbtt == 0) /* e.g. for ap mode */ + if (nexttbtt == 0) /* e.g. for ap mode */ nexttbtt = intval; - else if (intval) /* NB: can be 0 for monitor mode */ + else if (intval) /* NB: can be 0 for monitor mode */ nexttbtt = roundup(nexttbtt, intval); + DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", __func__, nexttbtt, intval, conf.beacon_interval); + /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */ - if (sc->sc_opmode == ATH9K_M_STA) { + if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { struct ath9k_beacon_state bs; u64 tsf; u32 tsftu; @@ -816,19 +710,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * last beacon we received (which may be none). */ dtimperiod = conf.dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ + if (dtimperiod <= 0) /* NB: 0 if not known */ dtimperiod = 1; dtimcount = conf.dtim_count; - if (dtimcount >= dtimperiod) /* NB: sanity check */ - dtimcount = 0; /* XXX? */ - cfpperiod = 1; /* NB: no PCF support yet */ + if (dtimcount >= dtimperiod) /* NB: sanity check */ + dtimcount = 0; + cfpperiod = 1; /* NB: no PCF support yet */ cfpcount = 0; sleepduration = conf.listen_interval * intval; if (sleepduration <= 0) sleepduration = intval; -#define FUDGE 2 +#define FUDGE 2 /* * Pull nexttbtt forward to reflect the current * TSF and calculate dtim+cfp state for the result. @@ -844,7 +738,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) } } while (nexttbtt < tsftu); #undef FUDGE - memzero(&bs, sizeof(bs)); + memset(&bs, 0, sizeof(bs)); bs.bs_intval = intval; bs.bs_nexttbtt = nexttbtt; bs.bs_dtimperiod = dtimperiod*intval; @@ -852,6 +746,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; bs.bs_cfpmaxduration = 0; + /* * Calculate the number of consecutive beacons to miss * before taking a BMISS interrupt. The configuration @@ -860,9 +755,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * result to at most 15 beacons. */ if (sleepduration > intval) { - bs.bs_bmissthreshold = - conf.listen_interval * - ATH_DEFAULT_BMISS_LIMIT / 2; + bs.bs_bmissthreshold = conf.listen_interval * + ATH_DEFAULT_BMISS_LIMIT / 2; } else { bs.bs_bmissthreshold = DIV_ROUND_UP(conf.bmiss_timeout, intval); @@ -882,8 +776,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * XXX fixed at 100ms */ - bs.bs_sleepduration = - roundup(IEEE80211_MS_TO_TU(100), sleepduration); + bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), + sleepduration); if (bs.bs_sleepduration > bs.bs_dtimperiod) bs.bs_sleepduration = bs.bs_dtimperiod; @@ -899,19 +793,19 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) "cfp:period %u " "maxdur %u " "next %u " - "timoffset %u\n" - , __func__ - , (unsigned long long)tsf, tsftu - , bs.bs_intval - , bs.bs_nexttbtt - , bs.bs_dtimperiod - , bs.bs_nextdtim - , bs.bs_bmissthreshold - , bs.bs_sleepduration - , bs.bs_cfpperiod - , bs.bs_cfpmaxduration - , bs.bs_cfpnext - , bs.bs_timoffset + "timoffset %u\n", + __func__, + (unsigned long long)tsf, tsftu, + bs.bs_intval, + bs.bs_nexttbtt, + bs.bs_dtimperiod, + bs.bs_nextdtim, + bs.bs_bmissthreshold, + bs.bs_sleepduration, + bs.bs_cfpperiod, + bs.bs_cfpmaxduration, + bs.bs_cfpnext, + bs.bs_timoffset ); ath9k_hw_set_interrupts(ah, 0); @@ -924,12 +818,12 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) ath9k_hw_set_interrupts(ah, 0); if (nexttbtt == intval) intval |= ATH9K_BEACON_RESET_TSF; - if (sc->sc_opmode == ATH9K_M_IBSS) { + if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { /* * Pull nexttbtt forward to reflect the current - * TSF . + * TSF */ -#define FUDGE 2 +#define FUDGE 2 if (!(intval & ATH9K_BEACON_RESET_TSF)) { tsf = ath9k_hw_gettsf64(ah); tsftu = TSF_TO_TU((u32)(tsf>>32), @@ -956,7 +850,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) sc->sc_imask |= ATH9K_INT_SWBA; ath_beaconq_config(sc); - } else if (sc->sc_opmode == ATH9K_M_HOSTAP) { + } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) { /* * In AP mode we enable the beacon timers and * SWBA interrupts to prepare beacon frames. @@ -972,11 +866,10 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) * When using a self-linked beacon descriptor in * ibss mode load it once here. */ - if (sc->sc_opmode == ATH9K_M_IBSS && + if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS && (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) ath_beacon_start_adhoc(sc, 0); } -#undef TSF_TO_TU } /* Function to collect beacon rssi data and resync beacon if necessary */ @@ -988,5 +881,5 @@ void ath_beacon_sync(struct ath_softc *sc, int if_id) * beacon frame we just received. */ ath_beacon_config(sc, if_id); - sc->sc_beacons = 1; + sc->sc_flags |= SC_OP_BEACONS; } diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index f6c45288d0e..c5033f6f42a 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c @@ -21,9 +21,6 @@ static int ath_outdoor; /* enable outdoor use */ -static const u8 ath_bcast_mac[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - static u32 ath_chainmask_sel_up_rssi_thres = ATH_CHAINMASK_SEL_UP_RSSI_THRES; static u32 ath_chainmask_sel_down_rssi_thres = @@ -54,10 +51,8 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) * Set current operating mode * * This function initializes and fills the rate table in the ATH object based - * on the operating mode. The blink rates are also set up here, although - * they have been superceeded by the ath_led module. + * on the operating mode. */ - static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) { const struct ath9k_rate_table *rt; @@ -70,7 +65,7 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) for (i = 0; i < rt->rateCount; i++) sc->sc_rixmap[rt->info[i].rateCode] = (u8) i; - memzero(sc->sc_hwmap, sizeof(sc->sc_hwmap)); + memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap)); for (i = 0; i < 256; i++) { u8 ix = rt->rateCodeToIndex[i]; @@ -235,7 +230,7 @@ static int ath_setup_channels(struct ath_softc *sc) * Determine mode from channel flags * * This routine will provide the enumerated WIRELESSS_MODE value based - * on the settings of the channel flags. If ho valid set of flags + * on the settings of the channel flags. If no valid set of flags * exist, the lowest mode (11b) is selected. */ @@ -260,7 +255,8 @@ static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) else if (chan->chanmode == CHANNEL_G_HT40MINUS) return ATH9K_MODE_11NG_HT40MINUS; - /* NB: should not get here */ + WARN_ON(1); /* should not get here */ + return ATH9K_MODE_11B; } @@ -275,14 +271,12 @@ static int ath_stop(struct ath_softc *sc) { struct ath_hal *ah = sc->sc_ah; - DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %u\n", - __func__, sc->sc_invalid); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n", + __func__, sc->sc_flags & SC_OP_INVALID); /* * Shutdown the hardware and driver: * stop output from above - * reset 802.11 state machine - * (sends station deassoc/deauth frames) * turn off timers * disable interrupts * clear transmit machinery @@ -294,10 +288,8 @@ static int ath_stop(struct ath_softc *sc) * hardware is gone (invalid). */ - if (!sc->sc_invalid) - ath9k_hw_set_interrupts(ah, 0); ath_draintxq(sc, false); - if (!sc->sc_invalid) { + if (!(sc->sc_flags & SC_OP_INVALID)) { ath_stoprecv(sc); ath9k_hw_phy_disable(ah); } else @@ -307,56 +299,6 @@ static int ath_stop(struct ath_softc *sc) } /* - * Start Scan - * - * This function is called when starting a channel scan. It will perform - * power save wakeup processing, set the filter for the scan, and get the - * chip ready to send broadcast packets out during the scan. -*/ - -void ath_scan_start(struct ath_softc *sc) -{ - struct ath_hal *ah = sc->sc_ah; - u32 rfilt; - u32 now = (u32) jiffies_to_msecs(get_timestamp()); - - sc->sc_scanning = 1; - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(ah, rfilt); - ath9k_hw_write_associd(ah, ath_bcast_mac, 0); - - /* Restore previous power management state. */ - - DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0\n", - now / 1000, now % 1000, __func__, rfilt); -} - -/* - * Scan End - * - * This routine is called by the upper layer when the scan is completed. This - * will set the filters back to normal operating mode, set the BSSID to the - * correct value, and restore the power save state. -*/ - -void ath_scan_end(struct ath_softc *sc) -{ - struct ath_hal *ah = sc->sc_ah; - u32 rfilt; - u32 now = (u32) jiffies_to_msecs(get_timestamp()); - - sc->sc_scanning = 0; - /* Request for a full reset due to rx packet filter changes */ - sc->sc_full_reset = 1; - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(ah, rfilt); - ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); - - DPRINTF(sc, ATH_DBG_CONFIG, "%d.%03d | %s: RX filter 0x%x aid 0x%x\n", - now / 1000, now % 1000, __func__, rfilt, sc->sc_curaid); -} - -/* * Set the current channel * * Set/change channels. If the channel is really being changed, it's done @@ -367,25 +309,23 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) { struct ath_hal *ah = sc->sc_ah; bool fastcc = true, stopped; - enum ath9k_ht_macmode ht_macmode; - if (sc->sc_invalid) /* if the device is invalid or removed */ + if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */ return -EIO; DPRINTF(sc, ATH_DBG_CONFIG, "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", __func__, - ath9k_hw_mhz2ieee(ah, sc->sc_curchan.channel, - sc->sc_curchan.channelFlags), - sc->sc_curchan.channel, + ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel, + sc->sc_ah->ah_curchan->channelFlags), + sc->sc_ah->ah_curchan->channel, ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), hchan->channel, hchan->channelFlags); - ht_macmode = ath_cwm_macmode(sc); - - if (hchan->channel != sc->sc_curchan.channel || - hchan->channelFlags != sc->sc_curchan.channelFlags || - sc->sc_update_chainmask || sc->sc_full_reset) { + if (hchan->channel != sc->sc_ah->ah_curchan->channel || + hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || + (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || + (sc->sc_flags & SC_OP_FULL_RESET)) { int status; /* * This is only performed if the channel settings have @@ -404,15 +344,16 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) * to flush data frames already in queue because of * changing channel. */ - if (!stopped || sc->sc_full_reset) + if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) fastcc = false; spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, sc->sc_opmode, hchan, - ht_macmode, sc->sc_tx_chainmask, - sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, - fastcc, &status)) { + if (!ath9k_hw_reset(ah, hchan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, + sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, + fastcc, &status)) { DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to reset channel %u (%uMhz) " "flags 0x%x hal status %u\n", __func__, @@ -424,9 +365,8 @@ int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) } spin_unlock_bh(&sc->sc_resetlock); - sc->sc_curchan = *hchan; - sc->sc_update_chainmask = 0; - sc->sc_full_reset = 0; + sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; + sc->sc_flags &= ~SC_OP_FULL_RESET; /* Re-enable rx framework */ if (ath_startrecv(sc) != 0) { @@ -477,7 +417,7 @@ static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an) { struct ath_chainmask_sel *cm = &an->an_chainmask_sel; - memzero(cm, sizeof(struct ath_chainmask_sel)); + memset(cm, 0, sizeof(struct ath_chainmask_sel)); cm->cur_tx_mask = sc->sc_tx_chainmask; cm->cur_rx_mask = sc->sc_rx_chainmask; @@ -537,7 +477,7 @@ int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an) void ath_update_chainmask(struct ath_softc *sc, int is_ht) { - sc->sc_update_chainmask = 1; + sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; if (is_ht) { sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; @@ -550,66 +490,126 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); } -/******************/ -/* VAP management */ -/******************/ +/*******/ +/* ANI */ +/*******/ /* - * VAP in Listen mode - * - * This routine brings the VAP out of the down state into a "listen" state - * where it waits for association requests. This is used in AP and AdHoc - * modes. -*/ + * This routine performs the periodic noise floor calibration function + * that is used to adjust and optimize the chip performance. This + * takes environmental changes (location, temperature) into account. + * When the task is complete, it reschedules itself depending on the + * appropriate interval that was calculated. + */ -int ath_vap_listen(struct ath_softc *sc, int if_id) +static void ath_ani_calibrate(unsigned long data) { - struct ath_hal *ah = sc->sc_ah; - struct ath_vap *avp; - u32 rfilt = 0; - DECLARE_MAC_BUF(mac); + struct ath_softc *sc; + struct ath_hal *ah; + bool longcal = false; + bool shortcal = false; + bool aniflag = false; + unsigned int timestamp = jiffies_to_msecs(jiffies); + u32 cal_interval; - avp = sc->sc_vaps[if_id]; - if (avp == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n", - __func__, if_id); - return -EINVAL; - } + sc = (struct ath_softc *)data; + ah = sc->sc_ah; -#ifdef CONFIG_SLOW_ANT_DIV - ath_slow_ant_div_stop(&sc->sc_antdiv); -#endif + /* + * don't calibrate when we're scanning. + * we are most likely not on our home channel. + */ + if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC) + return; - /* update ratectrl about the new state */ - ath_rate_newstate(sc, avp); + /* Long calibration runs independently of short calibration. */ + if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) { + longcal = true; + DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n", + __func__, jiffies); + sc->sc_ani.sc_longcal_timer = timestamp; + } - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(ah, rfilt); + /* Short calibration applies only while sc_caldone is false */ + if (!sc->sc_ani.sc_caldone) { + if ((timestamp - sc->sc_ani.sc_shortcal_timer) >= + ATH_SHORT_CALINTERVAL) { + shortcal = true; + DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n", + __func__, jiffies); + sc->sc_ani.sc_shortcal_timer = timestamp; + sc->sc_ani.sc_resetcal_timer = timestamp; + } + } else { + if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= + ATH_RESTART_CALINTERVAL) { + ath9k_hw_reset_calvalid(ah, ah->ah_curchan, + &sc->sc_ani.sc_caldone); + if (sc->sc_ani.sc_caldone) + sc->sc_ani.sc_resetcal_timer = timestamp; + } + } - if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS) { - memcpy(sc->sc_curbssid, ath_bcast_mac, ETH_ALEN); - ath9k_hw_write_associd(ah, sc->sc_curbssid, sc->sc_curaid); - } else - sc->sc_curaid = 0; + /* Verify whether we must check ANI */ + if ((timestamp - sc->sc_ani.sc_checkani_timer) >= + ATH_ANI_POLLINTERVAL) { + aniflag = true; + sc->sc_ani.sc_checkani_timer = timestamp; + } - DPRINTF(sc, ATH_DBG_CONFIG, - "%s: RX filter 0x%x bssid %s aid 0x%x\n", - __func__, rfilt, print_mac(mac, - sc->sc_curbssid), sc->sc_curaid); + /* Skip all processing if there's nothing to do. */ + if (longcal || shortcal || aniflag) { + /* Call ANI routine if necessary */ + if (aniflag) + ath9k_hw_ani_monitor(ah, &sc->sc_halstats, + ah->ah_curchan); + + /* Perform calibration if necessary */ + if (longcal || shortcal) { + bool iscaldone = false; + + if (ath9k_hw_calibrate(ah, ah->ah_curchan, + sc->sc_rx_chainmask, longcal, + &iscaldone)) { + if (longcal) + sc->sc_ani.sc_noise_floor = + ath9k_hw_getchan_noise(ah, + ah->ah_curchan); + + DPRINTF(sc, ATH_DBG_ANI, + "%s: calibrate chan %u/%x nf: %d\n", + __func__, + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags, + sc->sc_ani.sc_noise_floor); + } else { + DPRINTF(sc, ATH_DBG_ANY, + "%s: calibrate chan %u/%x failed\n", + __func__, + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags); + } + sc->sc_ani.sc_caldone = iscaldone; + } + } /* - * XXXX - * Disable BMISS interrupt when we're not associated - */ - ath9k_hw_set_interrupts(ah, - sc->sc_imask & ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS)); - sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); - /* need to reconfigure the beacons when it moves to RUN */ - sc->sc_beacons = 0; + * Set timer interval based on previous results. + * The interval must be the shortest necessary to satisfy ANI, + * short calibration and long calibration. + */ - return 0; + cal_interval = ATH_ANI_POLLINTERVAL; + if (!sc->sc_ani.sc_caldone) + cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL); + + mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval)); } +/******************/ +/* VAP management */ +/******************/ + int ath_vap_attach(struct ath_softc *sc, int if_id, struct ieee80211_vif *if_data, @@ -642,21 +642,19 @@ int ath_vap_attach(struct ath_softc *sc, if (avp == NULL) return -ENOMEM; - memzero(avp, sizeof(struct ath_vap)); + memset(avp, 0, sizeof(struct ath_vap)); avp->av_if_data = if_data; /* Set the VAP opmode */ avp->av_opmode = opmode; avp->av_bslot = -1; - INIT_LIST_HEAD(&avp->av_mcastq.axq_q); - INIT_LIST_HEAD(&avp->av_mcastq.axq_acq); - spin_lock_init(&avp->av_mcastq.axq_lock); - ath9k_hw_set_tsfadjust(sc->sc_ah, 1); + if (opmode == ATH9K_M_HOSTAP) + ath9k_hw_set_tsfadjust(sc->sc_ah, 1); sc->sc_vaps[if_id] = avp; sc->sc_nvaps++; /* Set the device opmode */ - sc->sc_opmode = opmode; + sc->sc_ah->ah_opmode = opmode; /* default VAP configuration */ avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; @@ -689,9 +687,6 @@ int ath_vap_detach(struct ath_softc *sc, int if_id) ath_stoprecv(sc); /* stop recv side */ ath_flushrecv(sc); /* flush recv queue */ - /* Reclaim any pending mcast bufs on the vap. */ - ath_tx_draintxq(sc, &avp->av_mcastq, false); - kfree(avp); sc->sc_vaps[if_id] = NULL; sc->sc_nvaps--; @@ -728,9 +723,9 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) struct ath_hal *ah = sc->sc_ah; int status; int error = 0; - enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", __func__, sc->sc_opmode); + DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", + __func__, sc->sc_ah->ah_opmode); /* * Stop anything previously setup. This is safe @@ -752,16 +747,16 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - sc->sc_curchan = *initial_chan; spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, ht_macmode, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, false, &status)) { + if (!ath9k_hw_reset(ah, initial_chan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, false, &status)) { DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to reset hardware; hal status %u " "(freq %u flags 0x%x)\n", __func__, status, - sc->sc_curchan.channel, sc->sc_curchan.channelFlags); + initial_chan->channel, initial_chan->channelFlags); error = -EIO; spin_unlock_bh(&sc->sc_resetlock); goto done; @@ -802,7 +797,8 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) * Note we only do this (at the moment) for station mode. */ if (ath9k_hw_phycounters(ah) && - ((sc->sc_opmode == ATH9K_M_STA) || (sc->sc_opmode == ATH9K_M_IBSS))) + ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || + (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) sc->sc_imask |= ATH9K_INT_MIB; /* * Some hardware processes the TIM IE and fires an @@ -811,7 +807,7 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) * enable the TIM interrupt when operating as station. */ if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && - (sc->sc_opmode == ATH9K_M_STA) && + (sc->sc_ah->ah_opmode == ATH9K_M_STA) && !sc->sc_config.swBeaconProcess) sc->sc_imask |= ATH9K_INT_TIM; /* @@ -823,34 +819,34 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) /* XXX: we must make sure h/w is ready and clear invalid flag * before turning on interrupt. */ - sc->sc_invalid = 0; + sc->sc_flags &= ~SC_OP_INVALID; done: return error; } -/* - * Reset the hardware w/o losing operational state. This is - * basically a more efficient way of doing ath_stop, ath_init, - * followed by state transitions to the current 802.11 - * operational state. Used to recover from errors rx overrun - * and to reset the hardware when rf gain settings must be reset. - */ - -static int ath_reset_start(struct ath_softc *sc, u32 flag) +int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hal *ah = sc->sc_ah; + int status; + int error = 0; ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ - ath_draintxq(sc, flag & RESET_RETRY_TXQ); /* stop xmit side */ - ath_stoprecv(sc); /* stop recv side */ - ath_flushrecv(sc); /* flush recv queue */ + ath_draintxq(sc, retry_tx); /* stop xmit */ + ath_stoprecv(sc); /* stop recv */ + ath_flushrecv(sc); /* flush recv queue */ - return 0; -} - -static int ath_reset_end(struct ath_softc *sc, u32 flag) -{ - struct ath_hal *ah = sc->sc_ah; + /* Reset chip */ + spin_lock_bh(&sc->sc_resetlock); + if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, false, &status)) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: unable to reset hardware; hal status %u\n", + __func__, status); + error = -EIO; + } + spin_unlock_bh(&sc->sc_resetlock); if (ath_startrecv(sc) != 0) /* restart recv */ DPRINTF(sc, ATH_DBG_FATAL, @@ -861,16 +857,17 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag) * that changes the channel so update any state that * might change as a result. */ - ath_setcurmode(sc, ath_chan2mode(&sc->sc_curchan)); + ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan)); - ath_update_txpow(sc); /* update tx power state */ + ath_update_txpow(sc); - if (sc->sc_beacons) + if (sc->sc_flags & SC_OP_BEACONS) ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ + ath9k_hw_set_interrupts(ah, sc->sc_imask); /* Restart the txq */ - if (flag & RESET_RETRY_TXQ) { + if (retry_tx) { int i; for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { @@ -880,28 +877,6 @@ static int ath_reset_end(struct ath_softc *sc, u32 flag) } } } - return 0; -} - -int ath_reset(struct ath_softc *sc) -{ - struct ath_hal *ah = sc->sc_ah; - int status; - int error = 0; - enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); - - /* NB: indicate channel change so we do a full reset */ - spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, sc->sc_opmode, &sc->sc_curchan, - ht_macmode, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, false, &status)) { - DPRINTF(sc, ATH_DBG_FATAL, - "%s: unable to reset hardware; hal status %u\n", - __func__, status); - error = -EIO; - } - spin_unlock_bh(&sc->sc_resetlock); return error; } @@ -911,7 +886,7 @@ int ath_suspend(struct ath_softc *sc) struct ath_hal *ah = sc->sc_ah; /* No I/O if device has been surprise removed */ - if (sc->sc_invalid) + if (sc->sc_flags & SC_OP_INVALID) return -EIO; /* Shut off the interrupt before setting sc->sc_invalid to '1' */ @@ -919,7 +894,7 @@ int ath_suspend(struct ath_softc *sc) /* XXX: we must make sure h/w will not generate any interrupt * before setting the invalid flag. */ - sc->sc_invalid = 1; + sc->sc_flags |= SC_OP_INVALID; /* disable HAL and put h/w to sleep */ ath9k_hw_disable(sc->sc_ah); @@ -940,7 +915,7 @@ irqreturn_t ath_isr(int irq, void *dev) bool sched = false; do { - if (sc->sc_invalid) { + if (sc->sc_flags & SC_OP_INVALID) { /* * The hardware is not ready/present, don't * touch anything. Note this can happen early @@ -1050,7 +1025,7 @@ static void ath9k_tasklet(unsigned long data) if (status & ATH9K_INT_FATAL) { /* need a chip reset */ - ath_internal_reset(sc); + ath_reset(sc, false); return; } else { @@ -1093,10 +1068,9 @@ int ath_init(u16 devid, struct ath_softc *sc) int status; int error = 0, i; int csz = 0; - u32 rd; /* XXX: hardware will not be ready until ath_open() being called */ - sc->sc_invalid = 1; + sc->sc_flags |= SC_OP_INVALID; sc->sc_debug = DBG_DEFAULT; DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid); @@ -1126,8 +1100,9 @@ int ath_init(u16 devid, struct ath_softc *sc) } sc->sc_ah = ah; - /* Get the chipset-specific aggr limit. */ - sc->sc_rtsaggrlimit = ah->ah_caps.rts_aggr_limit; + /* Initializes the noise floor to a reasonable default value. + * Later on this will be updated during ANI processing. */ + sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; /* Get the hardware key cache size. */ sc->sc_keymax = ah->ah_caps.keycache_size; @@ -1162,14 +1137,12 @@ int ath_init(u16 devid, struct ath_softc *sc) * is resposible for filtering this list based on settings * like the phy mode. */ - rd = ah->ah_currentRD; - error = ath_setup_channels(sc); if (error) goto bad; /* default to STA mode */ - sc->sc_opmode = ATH9K_M_MONITOR; + sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; /* Setup rate tables */ @@ -1238,9 +1211,11 @@ int ath_init(u16 devid, struct ath_softc *sc) goto bad2; } + setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); + sc->sc_rc = ath_rate_attach(ah); if (sc->sc_rc == NULL) { - error = EIO; + error = -EIO; goto bad2; } @@ -1280,20 +1255,13 @@ int ath_init(u16 devid, struct ath_softc *sc) /* 11n Capabilities */ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { - sc->sc_txaggr = 1; - sc->sc_rxaggr = 1; + sc->sc_flags |= SC_OP_TXAGGR; + sc->sc_flags |= SC_OP_RXAGGR; } sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; - /* Configuration for rx chain detection */ - sc->sc_rxchaindetect_ref = 0; - sc->sc_rxchaindetect_thresh5GHz = 35; - sc->sc_rxchaindetect_thresh2GHz = 35; - sc->sc_rxchaindetect_delta5GHz = 30; - sc->sc_rxchaindetect_delta2GHz = 30; - ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); sc->sc_defant = ath9k_hw_getdefantenna(ah); @@ -1336,8 +1304,10 @@ void ath_deinit(struct ath_softc *sc) DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); ath_stop(sc); - if (!sc->sc_invalid) + if (!(sc->sc_flags & SC_OP_INVALID)) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); ath_rate_detach(sc->sc_rc); /* cleanup tx queues */ @@ -1364,7 +1334,7 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id) an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC); if (an == NULL) return NULL; - memzero(an, sizeof(*an)); + memset(an, 0, sizeof(*an)); an->an_sc = sc; memcpy(an->an_addr, addr, ETH_ALEN); @@ -1464,9 +1434,9 @@ void ath_newassoc(struct ath_softc *sc, /* if station reassociates, tear down the aggregation state. */ if (!isnew) { for (tidno = 0; tidno < WME_NUM_TID; tidno++) { - if (sc->sc_txaggr) + if (sc->sc_flags & SC_OP_TXAGGR) ath_tx_aggr_teardown(sc, an, tidno); - if (sc->sc_rxaggr) + if (sc->sc_flags & SC_OP_RXAGGR) ath_rx_aggr_teardown(sc, an, tidno); } } @@ -1751,7 +1721,7 @@ int ath_descdma_setup(struct ath_softc *sc, error = -ENOMEM; goto fail2; } - memzero(bf, bsize); + memset(bf, 0, bsize); dd->dd_bufptr = bf; INIT_LIST_HEAD(head); @@ -1783,7 +1753,7 @@ fail2: pci_free_consistent(sc->pdev, dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); fail: - memzero(dd, sizeof(*dd)); + memset(dd, 0, sizeof(*dd)); return error; #undef ATH_DESC_4KB_BOUND_CHECK #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED @@ -1808,20 +1778,13 @@ void ath_descdma_cleanup(struct ath_softc *sc, INIT_LIST_HEAD(head); kfree(dd->dd_bufptr); - memzero(dd, sizeof(*dd)); + memset(dd, 0, sizeof(*dd)); } /*************/ /* Utilities */ /*************/ -void ath_internal_reset(struct ath_softc *sc) -{ - ath_reset_start(sc, 0); - ath_reset(sc); - ath_reset_end(sc, 0); -} - int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) { int qnum; diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ee695b76b8..cb3e61e57c4 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -39,6 +39,8 @@ #include <linux/scatterlist.h> #include <asm/page.h> #include <net/mac80211.h> +#include <linux/leds.h> +#include <linux/rfkill.h> #include "ath9k.h" #include "rc.h" @@ -79,11 +81,8 @@ struct ath_node; } \ } while (0) -/* XXX: remove */ -#define memzero(_buf, _len) memset(_buf, 0, _len) - -#define get_dma_mem_context(var, field) (&((var)->field)) -#define copy_dma_mem_context(dst, src) (*dst = *src) +#define TSF_TO_TU(_h,_l) \ + ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) #define ATH9K_BH_STATUS_INTACT 0 #define ATH9K_BH_STATUS_CHANGE 1 @@ -95,6 +94,8 @@ static inline unsigned long get_timestamp(void) return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); } +static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + /*************/ /* Debugging */ /*************/ @@ -175,42 +176,38 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht); /* Descriptor Management */ /*************************/ -/* Number of descriptors per buffer. The only case where we see skbuff -chains is due to FF aggregation in the driver. */ -#define ATH_TXDESC 1 -/* if there's more fragment for this MSDU */ -#define ATH_BF_MORE_MPDU 1 #define ATH_TXBUF_RESET(_bf) do { \ (_bf)->bf_status = 0; \ (_bf)->bf_lastbf = NULL; \ (_bf)->bf_lastfrm = NULL; \ (_bf)->bf_next = NULL; \ - memzero(&((_bf)->bf_state), \ + memset(&((_bf)->bf_state), 0, \ sizeof(struct ath_buf_state)); \ } while (0) +enum buffer_type { + BUF_DATA = BIT(0), + BUF_AGGR = BIT(1), + BUF_AMPDU = BIT(2), + BUF_HT = BIT(3), + BUF_RETRY = BIT(4), + BUF_XRETRY = BIT(5), + BUF_SHORT_PREAMBLE = BIT(6), + BUF_BAR = BIT(7), + BUF_PSPOLL = BIT(8), + BUF_AGGR_BURST = BIT(9), + BUF_CALC_AIRTIME = BIT(10), +}; + struct ath_buf_state { - int bfs_nframes; /* # frames in aggregate */ - u16 bfs_al; /* length of aggregate */ - u16 bfs_frmlen; /* length of frame */ - int bfs_seqno; /* sequence number */ - int bfs_tidno; /* tid of this frame */ - int bfs_retries; /* current retries */ + int bfs_nframes; /* # frames in aggregate */ + u16 bfs_al; /* length of aggregate */ + u16 bfs_frmlen; /* length of frame */ + int bfs_seqno; /* sequence number */ + int bfs_tidno; /* tid of this frame */ + int bfs_retries; /* current retries */ struct ath_rc_series bfs_rcs[4]; /* rate series */ - u8 bfs_isdata:1; /* is a data frame/aggregate */ - u8 bfs_isaggr:1; /* is an aggregate */ - u8 bfs_isampdu:1; /* is an a-mpdu, aggregate or not */ - u8 bfs_ht:1; /* is an HT frame */ - u8 bfs_isretried:1; /* is retried */ - u8 bfs_isxretried:1; /* is excessive retried */ - u8 bfs_shpreamble:1; /* is short preamble */ - u8 bfs_isbar:1; /* is a BAR */ - u8 bfs_ispspoll:1; /* is a PS-Poll */ - u8 bfs_aggrburst:1; /* is a aggr burst */ - u8 bfs_calcairtime:1; /* requests airtime be calculated - when set for tx frame */ - int bfs_rifsburst_elem; /* RIFS burst/bar */ - int bfs_nrifsubframes; /* # of elements in burst */ + u32 bf_type; /* BUF_* (enum buffer_type) */ /* key type use to encrypt this frame */ enum ath9k_key_type bfs_keytype; }; @@ -222,26 +219,22 @@ struct ath_buf_state { #define bf_seqno bf_state.bfs_seqno #define bf_tidno bf_state.bfs_tidno #define bf_rcs bf_state.bfs_rcs -#define bf_isdata bf_state.bfs_isdata -#define bf_isaggr bf_state.bfs_isaggr -#define bf_isampdu bf_state.bfs_isampdu -#define bf_ht bf_state.bfs_ht -#define bf_isretried bf_state.bfs_isretried -#define bf_isxretried bf_state.bfs_isxretried -#define bf_shpreamble bf_state.bfs_shpreamble -#define bf_rifsburst_elem bf_state.bfs_rifsburst_elem -#define bf_nrifsubframes bf_state.bfs_nrifsubframes #define bf_keytype bf_state.bfs_keytype -#define bf_isbar bf_state.bfs_isbar -#define bf_ispspoll bf_state.bfs_ispspoll -#define bf_aggrburst bf_state.bfs_aggrburst -#define bf_calcairtime bf_state.bfs_calcairtime +#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA) +#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) +#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) +#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) +#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) +#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) +#define bf_isshpreamble(bf) (bf->bf_state.bf_type & BUF_SHORT_PREAMBLE) +#define bf_isbar(bf) (bf->bf_state.bf_type & BUF_BAR) +#define bf_ispspoll(bf) (bf->bf_state.bf_type & BUF_PSPOLL) +#define bf_isaggrburst(bf) (bf->bf_state.bf_type & BUF_AGGR_BURST) /* * Abstraction of a contiguous buffer to transmit/receive. There is only * a single hw descriptor encapsulated here. */ - struct ath_buf { struct list_head list; struct list_head *last; @@ -316,7 +309,7 @@ void ath_descdma_cleanup(struct ath_softc *sc, #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ #define WME_NUM_TID 16 #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ -#define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ +#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */ enum ATH_RX_TYPE { ATH_RX_NON_CONSUMED = 0, @@ -391,10 +384,10 @@ int ath_rx_input(struct ath_softc *sc, struct sk_buff *skb, struct ath_recv_status *rx_status, enum ATH_RX_TYPE *status); -int ath__rx_indicate(struct ath_softc *sc, - struct sk_buff *skb, - struct ath_recv_status *status, - u16 keyix); +int _ath_rx_indicate(struct ath_softc *sc, + struct sk_buff *skb, + struct ath_recv_status *status, + u16 keyix); int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, struct ath_recv_status *status); @@ -402,8 +395,7 @@ int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb, /* TX */ /******/ -#define ATH_FRAG_PER_MSDU 1 -#define ATH_TXBUF (512/ATH_FRAG_PER_MSDU) +#define ATH_TXBUF 512 /* max number of transmit attempts (tries) */ #define ATH_TXMAXTRY 13 /* max number of 11n transmit attempts (tries) */ @@ -522,7 +514,6 @@ struct ath_tx_control { u32 keyix; int min_rate; int mcast_rate; - u16 nextfraglen; struct ath_softc *dev; dma_addr_t dmacontext; }; @@ -557,10 +548,10 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_setup(struct ath_softc *sc, int haltype); void ath_draintxq(struct ath_softc *sc, bool retry_tx); void ath_tx_draintxq(struct ath_softc *sc, - struct ath_txq *txq, bool retry_tx); + struct ath_txq *txq, bool retry_tx); void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); void ath_tx_node_cleanup(struct ath_softc *sc, - struct ath_node *an, bool bh_flag); + struct ath_node *an, bool bh_flag); void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an); void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); int ath_tx_init(struct ath_softc *sc, int nbufs); @@ -575,6 +566,7 @@ u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ath_xmit_status *tx_status, struct ath_node *an); +void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); /**********************/ /* Node / Aggregation */ @@ -585,7 +577,6 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, /* indicates the node is 80211 power save */ #define ATH_NODE_PWRSAVE 0x2 -#define ADDBA_TIMEOUT 200 /* 200 milliseconds */ #define ADDBA_EXCHANGE_ATTEMPTS 10 #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ @@ -705,9 +696,6 @@ struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr); #define ATH_BCBUF 4 /* number of beacon buffers */ #define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */ #define ATH_DEFAULT_BMISS_LIMIT 10 -#define ATH_BEACON_AIFS_DEFAULT 0 /* Default aifs for ap beacon q */ -#define ATH_BEACON_CWMIN_DEFAULT 0 /* Default cwmin for ap beacon q */ -#define ATH_BEACON_CWMAX_DEFAULT 0 /* Default cwmax for ap beacon q */ #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) /* beacon configuration */ @@ -724,30 +712,16 @@ struct ath_beacon_config { } u; /* last received beacon/probe response timestamp of this BSS. */ }; -/* offsets in a beacon frame for - * quick acess of beacon content by low-level driver */ -struct ath_beacon_offset { - u8 *bo_tim; /* start of atim/dtim */ -}; - void ath9k_beacon_tasklet(unsigned long data); void ath_beacon_config(struct ath_softc *sc, int if_id); int ath_beaconq_setup(struct ath_hal *ah); int ath_beacon_alloc(struct ath_softc *sc, int if_id); void ath_bstuck_process(struct ath_softc *sc); -void ath_beacon_tasklet(struct ath_softc *sc, int *needmark); -void ath_beacon_free(struct ath_softc *sc); void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); void ath_beacon_sync(struct ath_softc *sc, int if_id); -void ath_update_beacon_info(struct ath_softc *sc, int avgbrssi); void ath_get_beaconconfig(struct ath_softc *sc, int if_id, struct ath_beacon_config *conf); -int ath_update_beacon(struct ath_softc *sc, - int if_id, - struct ath_beacon_offset *bo, - struct sk_buff *skb, - int mcast); /********/ /* VAPs */ /********/ @@ -774,10 +748,8 @@ struct ath_vap { struct ieee80211_vif *av_if_data; enum ath9k_opmode av_opmode; /* VAP operational mode */ struct ath_buf *av_bcbuf; /* beacon buffer */ - struct ath_beacon_offset av_boff; /* dynamic update state */ struct ath_tx_control av_btxctl; /* txctl information for beacon */ int av_bslot; /* beacon slot index */ - struct ath_txq av_mcastq; /* multicast transmit queue */ struct ath_vap_config av_config;/* vap configuration parameters*/ struct ath_rate_node *rc_node; }; @@ -788,8 +760,7 @@ int ath_vap_attach(struct ath_softc *sc, enum ath9k_opmode opmode); int ath_vap_detach(struct ath_softc *sc, int if_id); int ath_vap_config(struct ath_softc *sc, - int if_id, struct ath_vap_config *if_config); -int ath_vap_listen(struct ath_softc *sc, int if_id); + int if_id, struct ath_vap_config *if_config); /*********************/ /* Antenna diversity */ @@ -829,6 +800,58 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv, struct ath_rx_status *rx_stats); void ath_setdefantenna(void *sc, u32 antenna); +/*******/ +/* ANI */ +/*******/ + +/* ANI values for STA only. + FIXME: Add appropriate values for AP later */ + +#define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */ +#define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */ +#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */ +#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */ + +struct ath_ani { + bool sc_caldone; + int16_t sc_noise_floor; + unsigned int sc_longcal_timer; + unsigned int sc_shortcal_timer; + unsigned int sc_resetcal_timer; + unsigned int sc_checkani_timer; + struct timer_list timer; +}; + +/********************/ +/* LED Control */ +/********************/ + +#define ATH_LED_PIN 1 + +enum ath_led_type { + ATH_LED_RADIO, + ATH_LED_ASSOC, + ATH_LED_TX, + ATH_LED_RX +}; + +struct ath_led { + struct ath_softc *sc; + struct led_classdev led_cdev; + enum ath_led_type led_type; + char name[32]; + bool registered; +}; + +/* Rfkill */ +#define ATH_RFKILL_POLL_INTERVAL 2000 /* msecs */ + +struct ath_rfkill { + struct rfkill *rfkill; + struct delayed_work rfkill_poll; + char rfkill_name[32]; +}; + /********************/ /* Main driver core */ /********************/ @@ -841,11 +864,7 @@ void ath_setdefantenna(void *sc, u32 antenna); #define ATH_DEFAULT_NOISE_FLOOR -95 #define ATH_REGCLASSIDS_MAX 10 #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ -#define ATH_PREAMBLE_SHORT (1<<0) -#define ATH_PROTECT_ENABLE (1<<1) #define ATH_MAX_SW_RETRIES 10 -/* Num farmes difference in tx to flip default recv */ -#define ATH_ANTENNA_DIFF 2 #define ATH_CHAN_MAX 255 #define IEEE80211_WEP_NKID 4 /* number of key ids */ #define IEEE80211_RATE_VAL 0x7f @@ -859,9 +878,7 @@ void ath_setdefantenna(void *sc, u32 antenna); */ #define ATH_KEYMAX 128 /* max key cache size we handle */ -#define RESET_RETRY_TXQ 0x00000001 #define ATH_IF_ID_ANY 0xff - #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ #define RSSI_LPF_THRESHOLD -20 @@ -907,60 +924,64 @@ struct ath_ht_info { u8 ext_chan_offset; }; +#define SC_OP_INVALID BIT(0) +#define SC_OP_BEACONS BIT(1) +#define SC_OP_RXAGGR BIT(2) +#define SC_OP_TXAGGR BIT(3) +#define SC_OP_CHAINMASK_UPDATE BIT(4) +#define SC_OP_FULL_RESET BIT(5) +#define SC_OP_NO_RESET BIT(6) +#define SC_OP_PREAMBLE_SHORT BIT(7) +#define SC_OP_PROTECT_ENABLE BIT(8) +#define SC_OP_RXFLUSH BIT(9) +#define SC_OP_LED_ASSOCIATED BIT(10) +#define SC_OP_RFKILL_REGISTERED BIT(11) +#define SC_OP_RFKILL_SW_BLOCKED BIT(12) +#define SC_OP_RFKILL_HW_BLOCKED BIT(13) + struct ath_softc { struct ieee80211_hw *hw; struct pci_dev *pdev; - void __iomem *mem; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; - struct ath_config sc_config; /* load-time parameters */ - int sc_debug; + struct ath_config sc_config; struct ath_hal *sc_ah; - struct ath_rate_softc *sc_rc; /* tx rate control support */ + struct ath_rate_softc *sc_rc; + void __iomem *mem; + + u8 sc_curbssid[ETH_ALEN]; + u8 sc_myaddr[ETH_ALEN]; + u8 sc_bssidmask[ETH_ALEN]; + + int sc_debug; u32 sc_intrstatus; - enum ath9k_opmode sc_opmode; /* current operating mode */ - - u8 sc_invalid; /* being detached */ - u8 sc_beacons; /* beacons running */ - u8 sc_scanning; /* scanning active */ - u8 sc_txaggr; /* enable 11n tx aggregation */ - u8 sc_rxaggr; /* enable 11n rx aggregation */ - u8 sc_update_chainmask; /* change chain mask */ - u8 sc_full_reset; /* force full reset */ - enum wireless_mode sc_curmode; /* current phy mode */ + u32 sc_flags; /* SC_OP_* */ + unsigned int rx_filter; u16 sc_curtxpow; u16 sc_curaid; - u8 sc_curbssid[ETH_ALEN]; - u8 sc_myaddr[ETH_ALEN]; + u16 sc_cachelsz; + int sc_slotupdate; /* slot to next advance fsm */ + int sc_slottime; + int sc_bslot[ATH_BCBUF]; + u8 sc_tx_chainmask; + u8 sc_rx_chainmask; + enum ath9k_int sc_imask; + enum wireless_mode sc_curmode; /* current phy mode */ enum PROT_MODE sc_protmode; - u8 sc_mcastantenna; - u8 sc_txantenna; /* data tx antenna (fixed or auto) */ + u8 sc_nbcnvaps; /* # of vaps sending beacons */ u16 sc_nvaps; /* # of active virtual ap's */ struct ath_vap *sc_vaps[ATH_BCBUF]; - enum ath9k_int sc_imask; - u8 sc_bssidmask[ETH_ALEN]; + + u8 sc_mcastantenna; u8 sc_defant; /* current default antenna */ u8 sc_rxotherant; /* rx's on non-default antenna */ - u16 sc_cachelsz; - int sc_slotupdate; /* slot to next advance fsm */ - int sc_slottime; - u8 sc_noreset; - int sc_bslot[ATH_BCBUF]; + struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ struct list_head node_list; struct ath_ht_info sc_ht_info; - int16_t sc_noise_floor; /* signal noise floor in dBm */ enum ath9k_ht_extprotspacing sc_ht_extprotspacing; - u8 sc_tx_chainmask; - u8 sc_rx_chainmask; - u8 sc_rxchaindetect_ref; - u8 sc_rxchaindetect_thresh5GHz; - u8 sc_rxchaindetect_thresh2GHz; - u8 sc_rxchaindetect_delta5GHz; - u8 sc_rxchaindetect_delta2GHz; - u32 sc_rtsaggrlimit; /* Chipset specific aggr limit */ - u32 sc_flags; + #ifdef CONFIG_SLOW_ANT_DIV struct ath_antdiv sc_antdiv; #endif @@ -974,15 +995,12 @@ struct ath_softc { u32 sc_keymax; /* size of key cache */ DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */ u8 sc_splitmic; /* split TKIP MIC keys */ - int sc_keytype; /* RX */ struct list_head sc_rxbuf; struct ath_descdma sc_rxdma; int sc_rxbufsize; /* rx size based on mtu */ u32 *sc_rxlink; /* link ptr in last RX desc */ - u32 sc_rxflush; /* rx flush in progress */ - u64 sc_lastrx; /* tsf of last rx'd frame */ /* TX */ struct list_head sc_txbuf; @@ -991,7 +1009,6 @@ struct ath_softc { u32 sc_txqsetup; u32 sc_txintrperiod; /* tx interrupt batching */ int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */ - u32 sc_ant_tx[8]; /* recent tx frames/antenna */ u16 seq_no; /* TX sequence number */ /* Beacon */ @@ -1002,6 +1019,7 @@ struct ath_softc { u32 sc_bhalq; u32 sc_bmisscount; u32 ast_be_xmit; /* beacons transmitted */ + u64 bc_tstamp; /* Rate */ struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; @@ -1016,7 +1034,6 @@ struct ath_softc { /* Channel, Band */ struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ath9k_channel sc_curchan; /* Locks */ spinlock_t sc_rxflushlock; @@ -1024,6 +1041,18 @@ struct ath_softc { spinlock_t sc_txbuflock; spinlock_t sc_resetlock; spinlock_t node_lock; + + /* LEDs */ + struct ath_led radio_led; + struct ath_led assoc_led; + struct ath_led tx_led; + struct ath_led rx_led; + + /* Rfkill */ + struct ath_rfkill rf_kill; + + /* ANI */ + struct ath_ani sc_ani; }; int ath_init(u16 devid, struct ath_softc *sc); @@ -1031,14 +1060,8 @@ void ath_deinit(struct ath_softc *sc); int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); int ath_suspend(struct ath_softc *sc); irqreturn_t ath_isr(int irq, void *dev); -int ath_reset(struct ath_softc *sc); -void ath_scan_start(struct ath_softc *sc); -void ath_scan_end(struct ath_softc *sc); +int ath_reset(struct ath_softc *sc, bool retry_tx); int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); -void ath_setup_rate(struct ath_softc *sc, - enum wireless_mode wMode, - enum RATE_TYPE type, - const struct ath9k_rate_table *rt); /*********************/ /* Utility Functions */ @@ -1057,17 +1080,5 @@ int ath_cabq_update(struct ath_softc *); void ath_get_currentCountry(struct ath_softc *sc, struct ath9k_country_entry *ctry); u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); -void ath_internal_reset(struct ath_softc *sc); -u32 ath_chan2flags(struct ieee80211_channel *chan, struct ath_softc *sc); -dma_addr_t ath_skb_map_single(struct ath_softc *sc, - struct sk_buff *skb, - int direction, - dma_addr_t *pa); -void ath_skb_unmap_single(struct ath_softc *sc, - struct sk_buff *skb, - int direction, - dma_addr_t *pa); -void ath_mcast_merge(struct ath_softc *sc, u32 mfilt[2]); -enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc); #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 6dbfed0b414..98bc25c9b3c 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -85,29 +85,6 @@ static const struct hal_percal_data adc_init_dc_cal = { ath9k_hw_adc_dccal_calibrate }; -static const struct ath_hal ar5416hal = { - AR5416_MAGIC, - 0, - 0, - NULL, - NULL, - CTRY_DEFAULT, - 0, - 0, - 0, - 0, - 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }, -}; - static struct ath9k_rate_table ar5416_11a_table = { 8, {0}, @@ -352,7 +329,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) ah->ah_config.ofdm_trig_high = 500; ah->ah_config.cck_trig_high = 200; ah->ah_config.cck_trig_low = 100; - ah->ah_config.enable_ani = 0; + ah->ah_config.enable_ani = 1; ah->ah_config.noise_immunity_level = 4; ah->ah_config.ofdm_weaksignal_det = 1; ah->ah_config.cck_weaksignal_thr = 0; @@ -371,7 +348,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) ah->ah_config.intr_mitigation = 0; } -static inline void ath9k_hw_override_ini(struct ath_hal *ah, +static void ath9k_hw_override_ini(struct ath_hal *ah, struct ath9k_channel *chan) { if (!AR_SREV_5416_V20_OR_LATER(ah) @@ -381,8 +358,8 @@ static inline void ath9k_hw_override_ini(struct ath_hal *ah, REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); } -static inline void ath9k_hw_init_bb(struct ath_hal *ah, - struct ath9k_channel *chan) +static void ath9k_hw_init_bb(struct ath_hal *ah, + struct ath9k_channel *chan) { u32 synthDelay; @@ -397,8 +374,8 @@ static inline void ath9k_hw_init_bb(struct ath_hal *ah, udelay(synthDelay + BASE_ACTIVATE_DELAY); } -static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, - enum ath9k_opmode opmode) +static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, + enum ath9k_opmode opmode) { struct ath_hal_5416 *ahp = AH5416(ah); @@ -428,7 +405,7 @@ static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah, } } -static inline void ath9k_hw_init_qos(struct ath_hal *ah) +static void ath9k_hw_init_qos(struct ath_hal *ah) { REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); @@ -523,7 +500,7 @@ static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, return ath9k_hw_eeprom_read(ah, off, data); } -static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah) +static bool ath9k_hw_fill_eeprom(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); struct ar5416_eeprom *eep = &ahp->ah_eeprom; @@ -790,7 +767,7 @@ ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, return true; } -static inline int ath9k_hw_check_eeprom(struct ath_hal *ah) +static int ath9k_hw_check_eeprom(struct ath_hal *ah) { u32 sum = 0, el; u16 *eepdata; @@ -1196,11 +1173,12 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, ah = &ahp->ah; - memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal)); - ah->ah_sc = sc; ah->ah_sh = mem; + ah->ah_magic = AR5416_MAGIC; + ah->ah_countryCode = CTRY_DEFAULT; + ah->ah_devid = devid; ah->ah_subvendorid = 0; @@ -1294,7 +1272,7 @@ u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, } } -static inline int ath9k_hw_get_radiorev(struct ath_hal *ah) +static int ath9k_hw_get_radiorev(struct ath_hal *ah) { u32 val; int i; @@ -1307,7 +1285,7 @@ static inline int ath9k_hw_get_radiorev(struct ath_hal *ah) return ath9k_hw_reverse_bits(val, 8); } -static inline int ath9k_hw_init_macaddr(struct ath_hal *ah) +static int ath9k_hw_init_macaddr(struct ath_hal *ah) { u32 sum; int i; @@ -1389,7 +1367,7 @@ static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, return spur_val; } -static inline int ath9k_hw_rfattach(struct ath_hal *ah) +static int ath9k_hw_rfattach(struct ath_hal *ah) { bool rfStatus = false; int ecode = 0; @@ -1434,8 +1412,8 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah) return 0; } -static inline void ath9k_hw_init_pll(struct ath_hal *ah, - struct ath9k_channel *chan) +static void ath9k_hw_init_pll(struct ath_hal *ah, + struct ath9k_channel *chan) { u32 pll; @@ -1553,7 +1531,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode) } } -static inline void +static void ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan) { u32 rfMode = 0; @@ -1623,7 +1601,7 @@ static bool ath9k_hw_set_reset(struct ath_hal *ah, int type) return true; } -static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) +static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah) { REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); @@ -1664,7 +1642,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, } } -static inline +static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, struct ath9k_channel *chan) { @@ -2098,7 +2076,7 @@ static void ath9k_hw_ani_attach(struct ath_hal *ah) ahp->ah_procPhyErr |= HAL_PROCESS_ANI; } -static inline void ath9k_hw_ani_setup(struct ath_hal *ah) +static void ath9k_hw_ani_setup(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); int i; @@ -2548,6 +2526,11 @@ static void ath9k_ani_reset(struct ath_hal *ah) } } +/* + * Process a MIB interrupt. We may potentially be invoked because + * any of the MIB counters overflow/trigger so don't assume we're + * here because a PHY error counter triggered. + */ void ath9k_hw_procmibevent(struct ath_hal *ah, const struct ath9k_node_stats *stats) { @@ -2555,18 +2538,20 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, u32 phyCnt1, phyCnt2; DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n"); - + /* Reset these counters regardless */ REG_WRITE(ah, AR_FILT_OFDM, 0); REG_WRITE(ah, AR_FILT_CCK, 0); if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); + /* Clear the mib counters and save them in the stats */ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats); ahp->ah_stats.ast_nodestats = *stats; if (!DO_ANI(ah)) return; + /* NB: these are not reset-on-read */ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || @@ -2574,6 +2559,7 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, struct ar5416AniState *aniState = ahp->ah_curani; u32 ofdmPhyErrCnt, cckPhyErrCnt; + /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; ahp->ah_stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount; @@ -2584,11 +2570,17 @@ void ath9k_hw_procmibevent(struct ath_hal *ah, cckPhyErrCnt - aniState->cckPhyErrCount; aniState->cckPhyErrCount = cckPhyErrCnt; + /* + * NB: figure out which counter triggered. If both + * trigger we'll only deal with one as the processing + * clobbers the error counter so the trigger threshold + * check will never be true. + */ if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) ath9k_hw_ani_ofdm_err_trigger(ah); if (aniState->cckPhyErrCount > aniState->cckTrigHigh) ath9k_hw_ani_cck_err_trigger(ah); - + /* NB: always restart to insure the h/w counters are reset */ ath9k_ani_restart(ah); } } @@ -2822,32 +2814,11 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah, } } -static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, - enum ath9k_gpio_output_mux_type - halSignalType) +void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, + u32 ah_signal_type) { - u32 ah_signal_type; u32 gpio_shift; - static u32 MuxSignalConversionTable[] = { - - AR_GPIO_OUTPUT_MUX_AS_OUTPUT, - - AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, - - AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, - - AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, - - AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, - }; - - if ((halSignalType >= 0) - && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable))) - ah_signal_type = MuxSignalConversionTable[halSignalType]; - else - return false; - ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); gpio_shift = 2 * gpio; @@ -2856,19 +2827,46 @@ static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); - - return true; } -static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, - u32 val) +void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val) { REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), AR_GPIO_BIT(gpio)); - return true; } -static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) +/* + * Configure GPIO Input lines + */ +void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio) +{ + u32 gpio_shift; + + ASSERT(gpio < ah->ah_caps.num_gpio_pins); + + gpio_shift = gpio << 1; + + REG_RMW(ah, + AR_GPIO_OE_OUT, + (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), + (AR_GPIO_OE_OUT_DRV << gpio_shift)); +} + +#ifdef CONFIG_RFKILL +static void ath9k_enable_rfkill(struct ath_hal *ah) +{ + REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, + AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); + + REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, + AR_GPIO_INPUT_MUX2_RFSILENT); + + ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio); + REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +} +#endif + +u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) { if (gpio >= ah->ah_caps.num_gpio_pins) return 0xffffffff; @@ -2883,7 +2881,7 @@ static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio) } } -static inline int ath9k_hw_post_attach(struct ath_hal *ah) +static int ath9k_hw_post_attach(struct ath_hal *ah) { int ecode; @@ -3081,17 +3079,17 @@ static bool ath9k_hw_fill_cap_info(struct ath_hal *ah) pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; +#ifdef CONFIG_RFKILL ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT); if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { - ahp->ah_gpioSelect = + ah->ah_rfkill_gpio = MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); - ahp->ah_polarity = + ah->ah_rfkill_polarity = MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY); - ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true, - NULL); pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; } +#endif if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) || (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) || @@ -3595,7 +3593,7 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, return true; } -static inline void +static void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, struct ath9k_channel *chan, struct cal_data_per_freq *pRawDataSet, @@ -3777,7 +3775,7 @@ ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah, return; } -static inline bool +static bool ath9k_hw_set_power_cal_table(struct ath_hal *ah, struct ar5416_eeprom *pEepData, struct ath9k_channel *chan, @@ -3980,7 +3978,7 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore) } } -static inline void +static void ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, struct ath9k_channel *chan, struct cal_target_power_leg *powInfo, @@ -4046,7 +4044,7 @@ ath9k_hw_get_legacy_target_powers(struct ath_hal *ah, } } -static inline void +static void ath9k_hw_get_target_powers(struct ath_hal *ah, struct ath9k_channel *chan, struct cal_target_power_ht *powInfo, @@ -4113,7 +4111,7 @@ ath9k_hw_get_target_powers(struct ath_hal *ah, } } -static inline u16 +static u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, bool is2GHz) @@ -4143,7 +4141,7 @@ ath9k_hw_get_max_edge_power(u16 freq, return twiceMaxEdgePower; } -static inline bool +static bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah, struct ar5416_eeprom *pEepData, struct ath9k_channel *chan, @@ -5122,7 +5120,7 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); } -static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah) +static void ath9k_hw_init_chain_masks(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); int rx_chainmask, tx_chainmask; @@ -5326,7 +5324,7 @@ bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us) } } -static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) +static void ath9k_hw_init_user_settings(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); @@ -5345,7 +5343,7 @@ static inline void ath9k_hw_init_user_settings(struct ath_hal *ah) ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout); } -static inline int +static int ath9k_hw_process_ini(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) @@ -5476,7 +5474,7 @@ ath9k_hw_process_ini(struct ath_hal *ah, return 0; } -static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, +static void ath9k_hw_setup_calibration(struct ath_hal *ah, struct hal_cal_list *currCal) { REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), @@ -5512,8 +5510,8 @@ static inline void ath9k_hw_setup_calibration(struct ath_hal *ah, AR_PHY_TIMING_CTRL4_DO_CAL); } -static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, - struct hal_cal_list *currCal) +static void ath9k_hw_reset_calibration(struct ath_hal *ah, + struct hal_cal_list *currCal) { struct ath_hal_5416 *ahp = AH5416(ah); int i; @@ -5532,7 +5530,7 @@ static inline void ath9k_hw_reset_calibration(struct ath_hal *ah, ahp->ah_CalSamples = 0; } -static inline void +static void ath9k_hw_per_calibration(struct ath_hal *ah, struct ath9k_channel *ichan, u8 rxchainmask, @@ -5622,7 +5620,7 @@ static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah, return true; } -static inline bool +static bool ath9k_hw_channel_change(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode) @@ -5799,8 +5797,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hal *ah, return retval; } -static inline bool ath9k_hw_init_cal(struct ath_hal *ah, - struct ath9k_channel *chan) +static bool ath9k_hw_init_cal(struct ath_hal *ah, + struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); struct ath9k_channel *ichan = @@ -5861,7 +5859,7 @@ static inline bool ath9k_hw_init_cal(struct ath_hal *ah, } -bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, +bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, enum ath9k_ht_macmode macmode, u8 txchainmask, u8 rxchainmask, @@ -5869,7 +5867,6 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, bool bChannelChange, int *status) { -#define FAIL(_code) do { ecode = _code; goto bad; } while (0) u32 saveLedState; struct ath_hal_5416 *ahp = AH5416(ah); struct ath9k_channel *curchan = ah->ah_curchan; @@ -5891,11 +5888,14 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->channel, chan->channelFlags); - FAIL(-EINVAL); + ecode = -EINVAL; + goto bad; } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; + if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { + ecode = -EIO; + goto bad; + } if (curchan) ath9k_hw_getnf(ah, curchan); @@ -5932,7 +5932,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, if (!ath9k_hw_chip_reset(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n", __func__); - FAIL(-EIO); + ecode = -EINVAL; + goto bad; } if (AR_SREV_9280(ah)) { @@ -5945,12 +5946,14 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, else ath9k_hw_set_gpio(ah, 9, 1); } - ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_cfg_output(ah, 9, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); } ecode = ath9k_hw_process_ini(ah, chan, macmode); - if (ecode != 0) + if (ecode != 0) { + ecode = -EINVAL; goto bad; + } if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) ath9k_hw_set_delta_slope(ah, chan); @@ -5963,7 +5966,8 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, if (!ath9k_hw_eeprom_set_board_values(ah, chan)) { DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: error setting board options\n", __func__); - FAIL(-EIO); + ecode = -EIO; + goto bad; } ath9k_hw_decrease_chain_power(ah, chan); @@ -5975,7 +5979,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, | (ah->ah_config. ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) | ahp->ah_staId1Defaults); - ath9k_hw_set_operating_mode(ah, opmode); + ath9k_hw_set_operating_mode(ah, ah->ah_opmode); REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask)); REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4)); @@ -5991,11 +5995,15 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!(ath9k_hw_ar9280_set_channel(ah, chan))) - FAIL(-EIO); + if (!(ath9k_hw_ar9280_set_channel(ah, chan))) { + ecode = -EIO; + goto bad; + } } else { - if (!(ath9k_hw_set_channel(ah, chan))) - FAIL(-EIO); + if (!(ath9k_hw_set_channel(ah, chan))) { + ecode = -EIO; + goto bad; + } } for (i = 0; i < AR_NUM_DCU; i++) @@ -6005,13 +6013,15 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, for (i = 0; i < ah->ah_caps.total_queues; i++) ath9k_hw_resettxqueue(ah, i); - ath9k_hw_init_interrupt_masks(ah, opmode); + ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode); ath9k_hw_init_qos(ah); +#ifdef CONFIG_RFKILL + if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + ath9k_enable_rfkill(ah); +#endif ath9k_hw_init_user_settings(ah); - ah->ah_opmode = opmode; - REG_WRITE(ah, AR_STA_ID1, REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); @@ -6027,8 +6037,10 @@ bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode, ath9k_hw_init_bb(ah, chan); - if (!ath9k_hw_init_cal(ah, chan)) - FAIL(-ENODEV); + if (!ath9k_hw_init_cal(ah, chan)){ + ecode = -EIO;; + goto bad; + } rx_chainmask = ahp->ah_rxchainmask; if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { @@ -6064,7 +6076,6 @@ bad: if (status) *status = ecode; return false; -#undef FAIL } bool ath9k_hw_phy_disable(struct ath_hal *ah) @@ -6539,31 +6550,6 @@ ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask) return true; } -#ifdef CONFIG_ATH9K_RFKILL -static void ath9k_enable_rfkill(struct ath_hal *ah) -{ - struct ath_hal_5416 *ahp = AH5416(ah); - - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); - - if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) { - - ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, - !ahp->ah_gpioBit); - } else { - ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect, - ahp->ah_gpioBit); - } -} -#endif - void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId) @@ -7678,8 +7664,7 @@ bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q) REG_WRITE(ah, AR_DRETRY_LIMIT(q), SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) - | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH) - ); + | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); REG_WRITE(ah, AR_DMISC(q), @@ -8324,15 +8309,7 @@ struct ath_hal *ath9k_hw_attach(u16 devid, *error = -ENXIO; break; } - if (ah != NULL) { - ah->ah_devid = ah->ah_devid; - ah->ah_subvendorid = ah->ah_subvendorid; - ah->ah_macVersion = ah->ah_macVersion; - ah->ah_macRev = ah->ah_macRev; - ah->ah_phyRev = ah->ah_phyRev; - ah->ah_analog5GhzRev = ah->ah_analog5GhzRev; - ah->ah_analog2GhzRev = ah->ah_analog2GhzRev; - } + return ah; } @@ -8439,23 +8416,48 @@ u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags) } } -int16_t +/* We can tune this as we go by monitoring really low values */ +#define ATH9K_NF_TOO_LOW -60 + +/* AR5416 may return very high value (like -31 dBm), in those cases the nf + * is incorrect and we should use the static NF value. Later we can try to + * find out why they are reporting these values */ +static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf) +{ + if (nf > ATH9K_NF_TOO_LOW) { + DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, + "%s: noise floor value detected (%d) is " + "lower than what we think is a " + "reasonable value (%d)\n", + __func__, nf, ATH9K_NF_TOO_LOW); + return false; + } + return true; +} + +s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) { struct ath9k_channel *ichan; + s16 nf; ichan = ath9k_regd_check_channel(ah, chan); if (ichan == NULL) { DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, "%s: invalid channel %u/0x%x; no mapping\n", __func__, chan->channel, chan->channelFlags); - return 0; + return ATH_DEFAULT_NOISE_FLOOR; } if (ichan->rawNoiseFloor == 0) { enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); - return NOISE_FLOOR[mode]; + nf = NOISE_FLOOR[mode]; } else - return ichan->rawNoiseFloor; + nf = ichan->rawNoiseFloor; + + if (!ath9k_hw_nf_in_range(ah, nf)) + nf = ATH_DEFAULT_NOISE_FLOOR; + + return nf; } bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting) diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index ae680f21ba7..2113818ee93 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h @@ -314,14 +314,11 @@ struct ar5416_desc { #define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ MS(ads->ds_rxstatus0, AR_RxRate) : \ (ads->ds_rxstatus3 >> 2) & 0xFF) -#define RXSTATUS_DUPLICATE(ah, ads) (AR_SREV_5416_V20_OR_LATER(ah) ? \ - MS(ads->ds_rxstatus3, AR_Parallel40) : \ - (ads->ds_rxstatus3 >> 10) & 0x1) -#define set11nTries(_series, _index) \ +#define set11nTries(_series, _index) \ (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) -#define set11nRate(_series, _index) \ +#define set11nRate(_series, _index) \ (SM((_series)[_index].Rate, AR_XmitRate##_index)) #define set11nPktDurRTSCTS(_series, _index) \ @@ -330,11 +327,11 @@ struct ar5416_desc { AR_RTSCTSQual##_index : 0)) #define set11nRateFlags(_series, _index) \ - (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ - AR_2040_##_index : 0) \ - |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ - AR_GI##_index : 0) \ - |SM((_series)[_index].ChSel, AR_ChainSel##_index)) + (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ + AR_2040_##_index : 0) \ + |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ + AR_GI##_index : 0) \ + |SM((_series)[_index].ChSel, AR_ChainSel##_index)) #define AR_SREV_9100(ah) ((ah->ah_macVersion) == AR_SREV_VERSION_9100) @@ -346,9 +343,6 @@ struct ar5416_desc { #define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) #define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD -#define NUM_CORNER_FIX_BITS_2133 7 -#define CCK_OFDM_GAIN_DELTA 15 - struct ar5416AniState { struct ath9k_channel c; u8 noiseImmunityLevel; @@ -377,11 +371,8 @@ struct ar5416AniState { }; #define HAL_PROCESS_ANI 0x00000001 -#define HAL_RADAR_EN 0x80000000 -#define HAL_AR_EN 0x40000000 - #define DO_ANI(ah) \ - ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI)) + ((AH5416(ah)->ah_procPhyErr & HAL_PROCESS_ANI)) struct ar5416Stats { u32 ast_ani_niup; @@ -425,7 +416,6 @@ struct ar5416Stats { #define AR5416_EEP_MINOR_VER_7 0x7 #define AR5416_EEP_MINOR_VER_9 0x9 -#define AR5416_EEP_START_LOC 256 #define AR5416_NUM_5G_CAL_PIERS 8 #define AR5416_NUM_2G_CAL_PIERS 4 #define AR5416_NUM_5G_20_TARGET_POWERS 8 @@ -441,25 +431,10 @@ struct ar5416Stats { #define AR5416_EEPROM_MODAL_SPURS 5 #define AR5416_MAX_RATE_POWER 63 #define AR5416_NUM_PDADC_VALUES 128 -#define AR5416_NUM_RATES 16 #define AR5416_BCHAN_UNUSED 0xFF #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR5416_EEPMISC_BIG_ENDIAN 0x01 #define AR5416_MAX_CHAINS 3 -#define AR5416_ANT_16S 25 - -#define AR5416_NUM_ANT_CHAIN_FIELDS 7 -#define AR5416_NUM_ANT_COMMON_FIELDS 4 -#define AR5416_SIZE_ANT_CHAIN_FIELD 3 -#define AR5416_SIZE_ANT_COMMON_FIELD 4 -#define AR5416_ANT_CHAIN_MASK 0x7 -#define AR5416_ANT_COMMON_MASK 0xf -#define AR5416_CHAIN_0_IDX 0 -#define AR5416_CHAIN_1_IDX 1 -#define AR5416_CHAIN_2_IDX 2 - #define AR5416_PWR_TABLE_OFFSET -5 -#define AR5416_LEGACY_CHAINMASK 1 enum eeprom_param { EEP_NFTHRESH_5, @@ -633,7 +608,7 @@ struct ar5416IniArray { }; #define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ - (iniarray)->ia_array = (u32 *)(array); \ + (iniarray)->ia_array = (u32 *)(array); \ (iniarray)->ia_rows = (rows); \ (iniarray)->ia_columns = (columns); \ } while (0) @@ -641,16 +616,16 @@ struct ar5416IniArray { #define INI_RA(iniarray, row, column) \ (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) -#define INIT_CAL(_perCal) do { \ - (_perCal)->calState = CAL_WAITING; \ - (_perCal)->calNext = NULL; \ +#define INIT_CAL(_perCal) do { \ + (_perCal)->calState = CAL_WAITING; \ + (_perCal)->calNext = NULL; \ } while (0) #define INSERT_CAL(_ahp, _perCal) \ do { \ if ((_ahp)->ah_cal_list_last == NULL) { \ - (_ahp)->ah_cal_list = \ - (_ahp)->ah_cal_list_last = (_perCal); \ + (_ahp)->ah_cal_list = \ + (_ahp)->ah_cal_list_last = (_perCal); \ ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ } else { \ ((_ahp)->ah_cal_list_last)->calNext = (_perCal); \ @@ -696,25 +671,29 @@ struct hal_cal_list { struct ath_hal_5416 { struct ath_hal ah; struct ar5416_eeprom ah_eeprom; + struct ar5416Stats ah_stats; + struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES]; + void __iomem *ah_cal_mem; + u8 ah_macaddr[ETH_ALEN]; u8 ah_bssid[ETH_ALEN]; u8 ah_bssidmask[ETH_ALEN]; u16 ah_assocId; + int16_t ah_curchanRadIndex; u32 ah_maskReg; - struct ar5416Stats ah_stats; - u32 ah_txDescMask; u32 ah_txOkInterruptMask; u32 ah_txErrInterruptMask; u32 ah_txDescInterruptMask; u32 ah_txEolInterruptMask; u32 ah_txUrnInterruptMask; - struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES]; - enum ath9k_power_mode ah_powerMode; bool ah_chipFullSleep; u32 ah_atimWindow; - enum ath9k_ant_setting ah_diversityControl; u16 ah_antennaSwitchSwap; + enum ath9k_power_mode ah_powerMode; + enum ath9k_ant_setting ah_diversityControl; + + /* Calibration */ enum hal_cal_types ah_suppCals; struct hal_cal_list ah_iqCalData; struct hal_cal_list ah_adcGainCalData; @@ -751,16 +730,16 @@ struct ath_hal_5416 { int32_t sign[AR5416_MAX_CHAINS]; } ah_Meas3; u16 ah_CalSamples; - u32 ah_tx6PowerInHalfDbm; + u32 ah_staId1Defaults; u32 ah_miscMode; - bool ah_tpcEnabled; - u32 ah_beaconInterval; enum { AUTO_32KHZ, USE_32KHZ, DONT_USE_32KHZ, } ah_enable32kHzClock; + + /* RF */ u32 *ah_analogBank0Data; u32 *ah_analogBank1Data; u32 *ah_analogBank2Data; @@ -770,8 +749,9 @@ struct ath_hal_5416 { u32 *ah_analogBank7Data; u32 *ah_addac5416_21; u32 *ah_bank6Temp; - u32 ah_ofdmTxPower; + int16_t ah_txPowerIndexOffset; + u32 ah_beaconInterval; u32 ah_slottime; u32 ah_acktimeout; u32 ah_ctstimeout; @@ -780,7 +760,8 @@ struct ath_hal_5416 { u32 ah_gpioSelect; u32 ah_polarity; u32 ah_gpioBit; - bool ah_eepEnabled; + + /* ANI */ u32 ah_procPhyErr; bool ah_hasHwPhyCounters; u32 ah_aniPeriod; @@ -790,18 +771,14 @@ struct ath_hal_5416 { int ah_coarseHigh[5]; int ah_coarseLow[5]; int ah_firpwr[5]; - u16 ah_ratesArray[16]; + enum ath9k_ani_cmd ah_ani_function; + u32 ah_intrTxqs; bool ah_intrMitigation; - u32 ah_cycleCount; - u32 ah_ctlBusy; - u32 ah_extBusy; enum ath9k_ht_extprotspacing ah_extprotspacing; u8 ah_txchainmask; u8 ah_rxchainmask; - int ah_hwp; - void __iomem *ah_cal_mem; - enum ath9k_ani_cmd ah_ani_function; + struct ar5416IniArray ah_iniModes; struct ar5416IniArray ah_iniCommon; struct ar5416IniArray ah_iniBank0; @@ -820,10 +797,6 @@ struct ath_hal_5416 { #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) -#define IS_5416_EMU(ah) \ - ((ah->ah_devid == AR5416_DEVID_EMU) || \ - (ah->ah_devid == AR5416_DEVID_EMU_PCIE)) - #define ar5416RfDetach(ah) do { \ if (AH5416(ah)->ah_rfHal.rfDetach != NULL) \ AH5416(ah)->ah_rfHal.rfDetach(ah); \ @@ -841,8 +814,8 @@ struct ath_hal_5416 { #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ int r; \ for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ - INI_RA((iniarray), r, (column))); \ + REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ + INI_RA((iniarray), r, (column))); \ DO_DELAY(regWr); \ } \ } while (0) @@ -852,30 +825,21 @@ struct ath_hal_5416 { #define COEF_SCALE_S 24 #define HT40_CHANNEL_CENTER_SHIFT 10 -#define ar5416CheckOpMode(_opmode) \ - ((_opmode == ATH9K_M_STA) || (_opmode == ATH9K_M_IBSS) || \ - (_opmode == ATH9K_M_HOSTAP) || (_opmode == ATH9K_M_MONITOR)) - #define AR5416_EEPROM_MAGIC_OFFSET 0x0 #define AR5416_EEPROM_S 2 #define AR5416_EEPROM_OFFSET 0x2000 -#define AR5416_EEPROM_START_ADDR \ +#define AR5416_EEPROM_START_ADDR \ (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 #define AR5416_EEPROM_MAX 0xae0 -#define ar5416_get_eep_ver(_ahp) \ +#define ar5416_get_eep_ver(_ahp) \ (((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF) -#define ar5416_get_eep_rev(_ahp) \ +#define ar5416_get_eep_rev(_ahp) \ (((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF) -#define ar5416_get_ntxchains(_txchainmask) \ +#define ar5416_get_ntxchains(_txchainmask) \ (((_txchainmask >> 2) & 1) + \ ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) -#define IS_EEP_MINOR_V3(_ahp) \ - (ath9k_hw_get_eeprom((_ahp), EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_3) - -#define FIXED_CCA_THRESHOLD 15 - #ifdef __BIG_ENDIAN #define AR5416_EEPROM_MAGIC 0x5aa5 #else @@ -910,8 +874,6 @@ struct ath_hal_5416 { #define AR_GPIOD_MASK 0x00001FFF #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) -#define MAX_ANALOG_START 319 - #define HAL_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) #define BEACON_RSSI(ahp) \ @@ -923,8 +885,6 @@ struct ath_hal_5416 { #define AH_TIMEOUT 100000 #define AH_TIME_QUANTUM 10 -#define IS(_c, _f) (((_c)->channelFlags & _f) || 0) - #define AR_KEYTABLE_SIZE 128 #define POWER_UP_TIME 200000 @@ -964,6 +924,6 @@ struct ath_hal_5416 { #define OFDM_SYMBOL_TIME_QUARTER 16 u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp, - enum eeprom_param param); + enum eeprom_param param); #endif diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 99badf1404c..74726990d59 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -22,8 +22,6 @@ #define ATH_PCI_VERSION "0.1" #define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13 -#define IEEE80211_ACTION_CAT_HT 7 -#define IEEE80211_ACTION_HT_TXCHWIDTH 0 static char *dev_info = "ath9k"; @@ -142,7 +140,7 @@ static int ath_key_config(struct ath_softc *sc, struct ath9k_keyval hk; const u8 *mac = NULL; int ret = 0; - enum ieee80211_if_types opmode; + enum nl80211_iftype opmode; memset(&hk, 0, sizeof(hk)); @@ -181,14 +179,14 @@ static int ath_key_config(struct ath_softc *sc, */ if (is_broadcast_ether_addr(addr)) { switch (opmode) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: /* default key: could be group WPA key * or could be static WEP key */ mac = NULL; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: break; - case IEEE80211_IF_TYPE_AP: + case NL80211_IFTYPE_AP: break; default: ASSERT(0); @@ -206,37 +204,30 @@ static int ath_key_config(struct ath_softc *sc, if (!ret) return -EIO; - if (mac) - sc->sc_keytype = hk.kv_type; return 0; } static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) { -#define ATH_MAX_NUM_KEYS 4 int freeslot; - freeslot = (key->keyidx >= ATH_MAX_NUM_KEYS) ? 1 : 0; + freeslot = (key->keyidx >= 4) ? 1 : 0; ath_key_reset(sc, key->keyidx, freeslot); -#undef ATH_MAX_NUM_KEYS } static void setup_ht_cap(struct ieee80211_ht_info *ht_info) { -/* Until mac80211 includes these fields */ - -#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -#define IEEE80211_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ -#define IEEE80211_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ +#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ +#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ ht_info->ht_supported = 1; ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH - |(u16)IEEE80211_HT_CAP_MIMO_PS + |(u16)IEEE80211_HT_CAP_SM_PS |(u16)IEEE80211_HT_CAP_SGI_40 |(u16)IEEE80211_HT_CAP_DSSSCCK40; - ht_info->ampdu_factor = IEEE80211_HT_CAP_MAXRXAMPDU_65536; - ht_info->ampdu_density = IEEE80211_HT_CAP_MPDUDENSITY_8; + ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; + ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; /* setup supported mcs set */ memset(ht_info->supp_mcs_set, 0, 16); ht_info->supp_mcs_set[0] = 0xff; @@ -283,10 +274,12 @@ static void ath9k_rx_prepare(struct ath_softc *sc, rx_status->mactime = status->tsf; rx_status->band = curchan->band; rx_status->freq = curchan->center_freq; - rx_status->noise = ATH_DEFAULT_NOISE_FLOOR; + rx_status->noise = sc->sc_ani.sc_noise_floor; rx_status->signal = rx_status->noise + status->rssi; rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); rx_status->antenna = status->antenna; + + /* XXX Fix me, 64 cannot be the max rssi value, rigure it out */ rx_status->qual = status->rssi * 100 / 64; if (status->flags & ATH_RX_MIC_ERROR) @@ -332,6 +325,698 @@ static u8 parse_mpdudensity(u8 mpdudensity) } } +static void ath9k_ht_conf(struct ath_softc *sc, + struct ieee80211_bss_conf *bss_conf) +{ +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14) + struct ath_ht_info *ht_info = &sc->sc_ht_info; + + if (bss_conf->assoc_ht) { + ht_info->ext_chan_offset = + bss_conf->ht_bss_conf->bss_cap & + IEEE80211_HT_IE_CHA_SEC_OFFSET; + + if (!(bss_conf->ht_conf->cap & + IEEE80211_HT_CAP_40MHZ_INTOLERANT) && + (bss_conf->ht_bss_conf->bss_cap & + IEEE80211_HT_IE_CHA_WIDTH)) + ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; + else + ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; + + ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); + ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + + bss_conf->ht_conf->ampdu_factor); + ht_info->mpdudensity = + parse_mpdudensity(bss_conf->ht_conf->ampdu_density); + + } + +#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT +} + +static void ath9k_bss_assoc_info(struct ath_softc *sc, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_channel *curchan = hw->conf.channel; + struct ath_vap *avp; + int pos; + DECLARE_MAC_BUF(mac); + + if (bss_conf->assoc) { + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n", + __func__, + bss_conf->aid); + + avp = sc->sc_vaps[0]; + if (avp == NULL) { + DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", + __func__); + return; + } + + /* New association, store aid */ + if (avp->av_opmode == ATH9K_M_STA) { + sc->sc_curaid = bss_conf->aid; + ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, + sc->sc_curaid); + } + + /* Configure the beacon */ + ath_beacon_config(sc, 0); + sc->sc_flags |= SC_OP_BEACONS; + + /* Reset rssi stats */ + sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; + sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; + + /* Update chainmask */ + ath_update_chainmask(sc, bss_conf->assoc_ht); + + DPRINTF(sc, ATH_DBG_CONFIG, + "%s: bssid %s aid 0x%x\n", + __func__, + print_mac(mac, sc->sc_curbssid), sc->sc_curaid); + + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", + __func__, + curchan->center_freq); + + pos = ath_get_channel(sc, curchan); + if (pos == -1) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Invalid channel\n", __func__); + return; + } + + if (hw->conf.ht_conf.ht_supported) + sc->sc_ah->ah_channels[pos].chanmode = + ath_get_extchanmode(sc, curchan); + else + sc->sc_ah->ah_channels[pos].chanmode = + (curchan->band == IEEE80211_BAND_2GHZ) ? + CHANNEL_G : CHANNEL_A; + + /* set h/w channel */ + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Unable to set channel\n", + __func__); + + ath_rate_newstate(sc, avp); + /* Update ratectrl about the new state */ + ath_rc_node_update(hw, avp->rc_node); + + /* Start ANI */ + mod_timer(&sc->sc_ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + + } else { + DPRINTF(sc, ATH_DBG_CONFIG, + "%s: Bss Info DISSOC\n", __func__); + sc->sc_curaid = 0; + } +} + +void ath_get_beaconconfig(struct ath_softc *sc, + int if_id, + struct ath_beacon_config *conf) +{ + struct ieee80211_hw *hw = sc->hw; + + /* fill in beacon config data */ + + conf->beacon_interval = hw->conf.beacon_int; + conf->listen_interval = 100; + conf->dtim_count = 1; + conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; +} + +void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, + struct ath_xmit_status *tx_status, struct ath_node *an) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + + DPRINTF(sc, ATH_DBG_XMIT, + "%s: TX complete: skb: %p\n", __func__, skb); + + if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || + tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { + /* free driver's private data area of tx_info */ + if (tx_info->driver_data[0] != NULL) + kfree(tx_info->driver_data[0]); + tx_info->driver_data[0] = NULL; + } + + if (tx_status->flags & ATH_TX_BAR) { + tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + tx_status->flags &= ~ATH_TX_BAR; + } + + if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) { + if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { + /* Frame was not ACKed, but an ACK was expected */ + tx_info->status.excessive_retries = 1; + } + } else { + /* Frame was ACKed */ + tx_info->flags |= IEEE80211_TX_STAT_ACK; + } + + tx_info->status.retry_count = tx_status->retries; + + ieee80211_tx_status(hw, skb); + if (an) + ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); +} + +int _ath_rx_indicate(struct ath_softc *sc, + struct sk_buff *skb, + struct ath_recv_status *status, + u16 keyix) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_node *an = NULL; + struct ieee80211_rx_status rx_status; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + int hdrlen = ieee80211_get_hdrlen_from_skb(skb); + int padsize; + enum ATH_RX_TYPE st; + + /* see if any padding is done by the hw and remove it */ + if (hdrlen & 3) { + padsize = hdrlen % 4; + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } + + /* Prepare rx status */ + ath9k_rx_prepare(sc, skb, status, &rx_status); + + if (!(keyix == ATH9K_RXKEYIX_INVALID) && + !(status->flags & ATH_RX_DECRYPT_ERROR)) { + rx_status.flag |= RX_FLAG_DECRYPTED; + } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) + && !(status->flags & ATH_RX_DECRYPT_ERROR) + && skb->len >= hdrlen + 4) { + keyix = skb->data[hdrlen + 3] >> 6; + + if (test_bit(keyix, sc->sc_keymap)) + rx_status.flag |= RX_FLAG_DECRYPTED; + } + + spin_lock_bh(&sc->node_lock); + an = ath_node_find(sc, hdr->addr2); + spin_unlock_bh(&sc->node_lock); + + if (an) { + ath_rx_input(sc, an, + hw->conf.ht_conf.ht_supported, + skb, status, &st); + } + if (!an || (st != ATH_RX_CONSUMED)) + __ieee80211_rx(hw, skb, &rx_status); + + return 0; +} + +int ath_rx_subframe(struct ath_node *an, + struct sk_buff *skb, + struct ath_recv_status *status) +{ + struct ath_softc *sc = an->an_sc; + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_rx_status rx_status; + + /* Prepare rx status */ + ath9k_rx_prepare(sc, skb, status, &rx_status); + if (!(status->flags & ATH_RX_DECRYPT_ERROR)) + rx_status.flag |= RX_FLAG_DECRYPTED; + + __ieee80211_rx(hw, skb, &rx_status); + + return 0; +} + +/********************************/ +/* LED functions */ +/********************************/ + +static void ath_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); + struct ath_softc *sc = led->sc; + + switch (brightness) { + case LED_OFF: + if (led->led_type == ATH_LED_ASSOC || + led->led_type == ATH_LED_RADIO) + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, + (led->led_type == ATH_LED_RADIO) ? 1 : + !!(sc->sc_flags & SC_OP_LED_ASSOCIATED)); + break; + case LED_FULL: + if (led->led_type == ATH_LED_ASSOC) + sc->sc_flags |= SC_OP_LED_ASSOCIATED; + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); + break; + default: + break; + } +} + +static int ath_register_led(struct ath_softc *sc, struct ath_led *led, + char *trigger) +{ + int ret; + + led->sc = sc; + led->led_cdev.name = led->name; + led->led_cdev.default_trigger = trigger; + led->led_cdev.brightness_set = ath_led_brightness; + + ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); + if (ret) + DPRINTF(sc, ATH_DBG_FATAL, + "Failed to register led:%s", led->name); + else + led->registered = 1; + return ret; +} + +static void ath_unregister_led(struct ath_led *led) +{ + if (led->registered) { + led_classdev_unregister(&led->led_cdev); + led->registered = 0; + } +} + +static void ath_deinit_leds(struct ath_softc *sc) +{ + ath_unregister_led(&sc->assoc_led); + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + ath_unregister_led(&sc->tx_led); + ath_unregister_led(&sc->rx_led); + ath_unregister_led(&sc->radio_led); + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); +} + +static void ath_init_leds(struct ath_softc *sc) +{ + char *trigger; + int ret; + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + + trigger = ieee80211_get_radio_led_name(sc->hw); + snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), + "ath9k-%s:radio", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->radio_led, trigger); + sc->radio_led.led_type = ATH_LED_RADIO; + if (ret) + goto fail; + + trigger = ieee80211_get_assoc_led_name(sc->hw); + snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), + "ath9k-%s:assoc", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->assoc_led, trigger); + sc->assoc_led.led_type = ATH_LED_ASSOC; + if (ret) + goto fail; + + trigger = ieee80211_get_tx_led_name(sc->hw); + snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), + "ath9k-%s:tx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->tx_led, trigger); + sc->tx_led.led_type = ATH_LED_TX; + if (ret) + goto fail; + + trigger = ieee80211_get_rx_led_name(sc->hw); + snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), + "ath9k-%s:rx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->rx_led, trigger); + sc->rx_led.led_type = ATH_LED_RX; + if (ret) + goto fail; + + return; + +fail: + ath_deinit_leds(sc); +} + +#ifdef CONFIG_RFKILL +/*******************/ +/* Rfkill */ +/*******************/ + +static void ath_radio_enable(struct ath_softc *sc) +{ + struct ath_hal *ah = sc->sc_ah; + int status; + + spin_lock_bh(&sc->sc_resetlock); + if (!ath9k_hw_reset(ah, ah->ah_curchan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, + sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, + false, &status)) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: unable to reset channel %u (%uMhz) " + "flags 0x%x hal status %u\n", __func__, + ath9k_hw_mhz2ieee(ah, + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags), + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags, status); + } + spin_unlock_bh(&sc->sc_resetlock); + + ath_update_txpow(sc); + if (ath_startrecv(sc) != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: unable to restart recv logic\n", __func__); + return; + } + + if (sc->sc_flags & SC_OP_BEACONS) + ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ + + /* Re-Enable interrupts */ + ath9k_hw_set_interrupts(ah, sc->sc_imask); + + /* Enable LED */ + ath9k_hw_cfg_output(ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); + + ieee80211_wake_queues(sc->hw); +} + +static void ath_radio_disable(struct ath_softc *sc) +{ + struct ath_hal *ah = sc->sc_ah; + int status; + + + ieee80211_stop_queues(sc->hw); + + /* Disable LED */ + ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); + ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); + + /* Disable interrupts */ + ath9k_hw_set_interrupts(ah, 0); + + ath_draintxq(sc, false); /* clear pending tx frames */ + ath_stoprecv(sc); /* turn off frame recv */ + ath_flushrecv(sc); /* flush recv queue */ + + spin_lock_bh(&sc->sc_resetlock); + if (!ath9k_hw_reset(ah, ah->ah_curchan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, + sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, + false, &status)) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: unable to reset channel %u (%uMhz) " + "flags 0x%x hal status %u\n", __func__, + ath9k_hw_mhz2ieee(ah, + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags), + ah->ah_curchan->channel, + ah->ah_curchan->channelFlags, status); + } + spin_unlock_bh(&sc->sc_resetlock); + + ath9k_hw_phy_disable(ah); + ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); +} + +static bool ath_is_rfkill_set(struct ath_softc *sc) +{ + struct ath_hal *ah = sc->sc_ah; + + return ath9k_hw_gpio_get(ah, ah->ah_rfkill_gpio) == + ah->ah_rfkill_polarity; +} + +/* h/w rfkill poll function */ +static void ath_rfkill_poll(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + rf_kill.rfkill_poll.work); + bool radio_on; + + if (sc->sc_flags & SC_OP_INVALID) + return; + + radio_on = !ath_is_rfkill_set(sc); + + /* + * enable/disable radio only when there is a + * state change in RF switch + */ + if (radio_on == !!(sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED)) { + enum rfkill_state state; + + if (sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED) { + state = radio_on ? RFKILL_STATE_SOFT_BLOCKED + : RFKILL_STATE_HARD_BLOCKED; + } else if (radio_on) { + ath_radio_enable(sc); + state = RFKILL_STATE_UNBLOCKED; + } else { + ath_radio_disable(sc); + state = RFKILL_STATE_HARD_BLOCKED; + } + + if (state == RFKILL_STATE_HARD_BLOCKED) + sc->sc_flags |= SC_OP_RFKILL_HW_BLOCKED; + else + sc->sc_flags &= ~SC_OP_RFKILL_HW_BLOCKED; + + rfkill_force_state(sc->rf_kill.rfkill, state); + } + + queue_delayed_work(sc->hw->workqueue, &sc->rf_kill.rfkill_poll, + msecs_to_jiffies(ATH_RFKILL_POLL_INTERVAL)); +} + +/* s/w rfkill handler */ +static int ath_sw_toggle_radio(void *data, enum rfkill_state state) +{ + struct ath_softc *sc = data; + + switch (state) { + case RFKILL_STATE_SOFT_BLOCKED: + if (!(sc->sc_flags & (SC_OP_RFKILL_HW_BLOCKED | + SC_OP_RFKILL_SW_BLOCKED))) + ath_radio_disable(sc); + sc->sc_flags |= SC_OP_RFKILL_SW_BLOCKED; + return 0; + case RFKILL_STATE_UNBLOCKED: + if ((sc->sc_flags & SC_OP_RFKILL_SW_BLOCKED)) { + sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED; + if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) { + DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the" + "radio as it is disabled by h/w \n"); + return -EPERM; + } + ath_radio_enable(sc); + } + return 0; + default: + return -EINVAL; + } +} + +/* Init s/w rfkill */ +static int ath_init_sw_rfkill(struct ath_softc *sc) +{ + sc->rf_kill.rfkill = rfkill_allocate(wiphy_dev(sc->hw->wiphy), + RFKILL_TYPE_WLAN); + if (!sc->rf_kill.rfkill) { + DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); + return -ENOMEM; + } + + snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), + "ath9k-%s:rfkill", wiphy_name(sc->hw->wiphy)); + sc->rf_kill.rfkill->name = sc->rf_kill.rfkill_name; + sc->rf_kill.rfkill->data = sc; + sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio; + sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED; + sc->rf_kill.rfkill->user_claim_unsupported = 1; + + return 0; +} + +/* Deinitialize rfkill */ +static void ath_deinit_rfkill(struct ath_softc *sc) +{ + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); + + if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { + rfkill_unregister(sc->rf_kill.rfkill); + sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; + sc->rf_kill.rfkill = NULL; + } +} +#endif /* CONFIG_RFKILL */ + +static int ath_detach(struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); + + /* Deinit LED control */ + ath_deinit_leds(sc); + +#ifdef CONFIG_RFKILL + /* deinit rfkill */ + ath_deinit_rfkill(sc); +#endif + + /* Unregister hw */ + + ieee80211_unregister_hw(hw); + + /* unregister Rate control */ + ath_rate_control_unregister(); + + /* tx/rx cleanup */ + + ath_rx_cleanup(sc); + ath_tx_cleanup(sc); + + /* Deinit */ + + ath_deinit(sc); + + return 0; +} + +static int ath_attach(u16 devid, + struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + int error = 0; + + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); + + error = ath_init(devid, sc); + if (error != 0) + return error; + + /* Init nodes */ + + INIT_LIST_HEAD(&sc->node_list); + spin_lock_init(&sc->node_lock); + + /* get mac address from hardware and set in mac80211 */ + + SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); + + /* setup channels and rates */ + + sc->sbands[IEEE80211_BAND_2GHZ].channels = + sc->channels[IEEE80211_BAND_2GHZ]; + sc->sbands[IEEE80211_BAND_2GHZ].bitrates = + sc->rates[IEEE80211_BAND_2GHZ]; + sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) + /* Setup HT capabilities for 2.4Ghz*/ + setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &sc->sbands[IEEE80211_BAND_2GHZ]; + + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_5GHZ].channels = + sc->channels[IEEE80211_BAND_5GHZ]; + sc->sbands[IEEE80211_BAND_5GHZ].bitrates = + sc->rates[IEEE80211_BAND_5GHZ]; + sc->sbands[IEEE80211_BAND_5GHZ].band = + IEEE80211_BAND_5GHZ; + + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) + /* Setup HT capabilities for 5Ghz*/ + setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); + + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &sc->sbands[IEEE80211_BAND_5GHZ]; + } + + /* FIXME: Have to figure out proper hw init values later */ + + hw->queues = 4; + hw->ampdu_queues = 1; + + /* Register rate control */ + hw->rate_control_algorithm = "ath9k_rate_control"; + error = ath_rate_control_register(); + if (error != 0) { + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Unable to register rate control " + "algorithm:%d\n", __func__, error); + ath_rate_control_unregister(); + goto bad; + } + + error = ieee80211_register_hw(hw); + if (error != 0) { + ath_rate_control_unregister(); + goto bad; + } + + /* Initialize LED control */ + ath_init_leds(sc); + +#ifdef CONFIG_RFKILL + /* Initialze h/w Rfkill */ + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); + + /* Initialize s/w rfkill */ + if (ath_init_sw_rfkill(sc)) + goto detach; +#endif + + /* initialize tx/rx engine */ + + error = ath_tx_init(sc, ATH_TXBUF); + if (error != 0) + goto detach; + + error = ath_rx_init(sc, ATH_RXBUF); + if (error != 0) + goto detach; + + return 0; +detach: + ath_detach(sc); +bad: + return error; +} + static int ath9k_start(struct ieee80211_hw *hw) { struct ath_softc *sc = hw->priv; @@ -360,6 +1045,33 @@ static int ath9k_start(struct ieee80211_hw *hw) return error; } +#ifdef CONFIG_RFKILL + /* Start rfkill polling */ + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + queue_delayed_work(sc->hw->workqueue, + &sc->rf_kill.rfkill_poll, 0); + + if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { + if (rfkill_register(sc->rf_kill.rfkill)) { + DPRINTF(sc, ATH_DBG_FATAL, + "Unable to register rfkill\n"); + rfkill_free(sc->rf_kill.rfkill); + + /* Deinitialize the device */ + if (sc->pdev->irq) + free_irq(sc->pdev->irq, sc); + ath_detach(sc); + pci_iounmap(sc->pdev, sc->mem); + pci_release_region(sc->pdev, 0); + pci_disable_device(sc->pdev); + ieee80211_free_hw(hw); + return -EIO; + } else { + sc->sc_flags |= SC_OP_RFKILL_REGISTERED; + } + } +#endif + ieee80211_wake_queues(hw); return 0; } @@ -421,6 +1133,11 @@ static void ath9k_stop(struct ieee80211_hw *hw) "%s: Device is no longer present\n", __func__); ieee80211_stop_queues(hw); + +#ifdef CONFIG_RFKILL + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); +#endif } static int ath9k_add_interface(struct ieee80211_hw *hw, @@ -435,16 +1152,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, return -ENOBUFS; switch (conf->type) { - case IEEE80211_IF_TYPE_STA: + case NL80211_IFTYPE_STATION: ic_opmode = ATH9K_M_STA; break; - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_ADHOC: ic_opmode = ATH9K_M_IBSS; break; + case NL80211_IFTYPE_AP: + ic_opmode = ATH9K_M_HOSTAP; + break; default: DPRINTF(sc, ATH_DBG_FATAL, - "%s: Only STA and IBSS are supported currently\n", - __func__); + "%s: Interface type %d not yet supported\n", + __func__, conf->type); return -EOPNOTSUPP; } @@ -460,6 +1180,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, return error; } + if (conf->type == NL80211_IFTYPE_AP) { + /* TODO: is this a suitable place to start ANI for AP mode? */ + /* Start ANI */ + mod_timer(&sc->sc_ani.timer, + jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); + } + return 0; } @@ -482,12 +1209,15 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, #ifdef CONFIG_SLOW_ANT_DIV ath_slow_ant_div_stop(&sc->sc_antdiv); #endif + /* Stop ANI */ + del_timer_sync(&sc->sc_ani.timer); /* Update ratectrl */ ath_rate_newstate(sc, avp); /* Reclaim beacon resources */ - if (sc->sc_opmode == ATH9K_M_HOSTAP || sc->sc_opmode == ATH9K_M_IBSS) { + if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP || + sc->sc_ah->ah_opmode == ATH9K_M_IBSS) { ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); ath_beacon_return(sc, avp); } @@ -495,7 +1225,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, /* Set interrupt mask */ sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL); - sc->sc_beacons = 0; + sc->sc_flags &= ~SC_OP_BEACONS; error = ath_vap_detach(sc, 0); if (error) @@ -544,6 +1274,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct ath_softc *sc = hw->priv; + struct ath_hal *ah = sc->sc_ah; struct ath_vap *avp; u32 rfilt = 0; int error, i; @@ -556,18 +1287,25 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, return -EINVAL; } + /* TODO: Need to decide which hw opmode to use for multi-interface + * cases */ + if (vif->type == NL80211_IFTYPE_AP && + ah->ah_opmode != ATH9K_M_HOSTAP) { + ah->ah_opmode = ATH9K_M_HOSTAP; + ath9k_hw_setopmode(ah); + ath9k_hw_write_associd(ah, sc->sc_myaddr, 0); + /* Request full reset to get hw opmode changed properly */ + sc->sc_flags |= SC_OP_FULL_RESET; + } + if ((conf->changed & IEEE80211_IFCC_BSSID) && !is_zero_ether_addr(conf->bssid)) { switch (vif->type) { - case IEEE80211_IF_TYPE_STA: - case IEEE80211_IF_TYPE_IBSS: + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: /* Update ratectrl about the new state */ ath_rate_newstate(sc, avp); - /* Set rx filter */ - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(sc->sc_ah, rfilt); - /* Set BSSID */ memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); sc->sc_curaid = 0; @@ -600,7 +1338,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, print_mac(mac, sc->sc_curbssid), sc->sc_curaid); /* need to reconfigure the beacon */ - sc->sc_beacons = 0; + sc->sc_flags &= ~SC_OP_BEACONS ; break; default: @@ -609,7 +1347,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } if ((conf->changed & IEEE80211_IFCC_BEACON) && - (vif->type == IEEE80211_IF_TYPE_IBSS)) { + ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP))) { /* * Allocate and setup the beacon frame. * @@ -628,7 +1367,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != IEEE80211_IF_TYPE_STA)) { + if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { for (i = 0; i < IEEE80211_WEP_NKID; i++) if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) ath9k_hw_keysetmac(sc->sc_ah, @@ -637,7 +1376,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, } /* Only legacy IBSS for now */ - if (vif->type == IEEE80211_IF_TYPE_IBSS) + if (vif->type == NL80211_IFTYPE_ADHOC) ath_update_chainmask(sc, 0); return 0; @@ -651,8 +1390,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, FIF_BCN_PRBRESP_PROMISC | \ FIF_FCSFAIL) -/* Accept unicast, bcast and mcast frames */ - +/* FIXME: sc->sc_full_reset ? */ static void ath9k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -660,22 +1398,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, struct dev_mc_list *mclist) { struct ath_softc *sc = hw->priv; + u32 rfilt; changed_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS; + sc->rx_filter = *total_flags; + rfilt = ath_calcrxfilter(sc); + ath9k_hw_setrxfilter(sc->sc_ah, rfilt); + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - ath_scan_start(sc); - else - ath_scan_end(sc); + ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0); } + + DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n", + __func__, sc->rx_filter); } static void ath9k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, - const u8 *addr) + struct ieee80211_sta *sta) { struct ath_softc *sc = hw->priv; struct ath_node *an; @@ -683,19 +1427,18 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, DECLARE_MAC_BUF(mac); spin_lock_irqsave(&sc->node_lock, flags); - an = ath_node_find(sc, (u8 *) addr); + an = ath_node_find(sc, sta->addr); spin_unlock_irqrestore(&sc->node_lock, flags); switch (cmd) { case STA_NOTIFY_ADD: spin_lock_irqsave(&sc->node_lock, flags); if (!an) { - ath_node_attach(sc, (u8 *)addr, 0); + ath_node_attach(sc, sta->addr, 0); DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n", - __func__, - print_mac(mac, addr)); + __func__, print_mac(mac, sta->addr)); } else { - ath_node_get(sc, (u8 *)addr); + ath_node_get(sc, sta->addr); } spin_unlock_irqrestore(&sc->node_lock, flags); break; @@ -708,7 +1451,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT); DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n", __func__, - print_mac(mac, addr)); + print_mac(mac, sta->addr)); } break; default: @@ -778,7 +1521,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw, case DISABLE_KEY: ath_key_delete(sc, key); clear_bit(key->keyidx, sc->sc_keymap); - sc->sc_keytype = ATH9K_CIPHER_CLR; break; default: ret = -EINVAL; @@ -787,117 +1529,6 @@ static int ath9k_set_key(struct ieee80211_hw *hw, return ret; } -static void ath9k_ht_conf(struct ath_softc *sc, - struct ieee80211_bss_conf *bss_conf) -{ -#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14) - struct ath_ht_info *ht_info = &sc->sc_ht_info; - - if (bss_conf->assoc_ht) { - ht_info->ext_chan_offset = - bss_conf->ht_bss_conf->bss_cap & - IEEE80211_HT_IE_CHA_SEC_OFFSET; - - if (!(bss_conf->ht_conf->cap & - IEEE80211_HT_CAP_40MHZ_INTOLERANT) && - (bss_conf->ht_bss_conf->bss_cap & - IEEE80211_HT_IE_CHA_WIDTH)) - ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; - else - ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; - - ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); - ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + - bss_conf->ht_conf->ampdu_factor); - ht_info->mpdudensity = - parse_mpdudensity(bss_conf->ht_conf->ampdu_density); - - } - -#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT -} - -static void ath9k_bss_assoc_info(struct ath_softc *sc, - struct ieee80211_bss_conf *bss_conf) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath_vap *avp; - int pos; - DECLARE_MAC_BUF(mac); - - if (bss_conf->assoc) { - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n", - __func__, - bss_conf->aid); - - avp = sc->sc_vaps[0]; - if (avp == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n", - __func__); - return; - } - - /* New association, store aid */ - if (avp->av_opmode == ATH9K_M_STA) { - sc->sc_curaid = bss_conf->aid; - ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid, - sc->sc_curaid); - } - - /* Configure the beacon */ - ath_beacon_config(sc, 0); - sc->sc_beacons = 1; - - /* Reset rssi stats */ - sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; - - /* Update chainmask */ - ath_update_chainmask(sc, bss_conf->assoc_ht); - - DPRINTF(sc, ATH_DBG_CONFIG, - "%s: bssid %s aid 0x%x\n", - __func__, - print_mac(mac, sc->sc_curbssid), sc->sc_curaid); - - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", - __func__, - curchan->center_freq); - - pos = ath_get_channel(sc, curchan); - if (pos == -1) { - DPRINTF(sc, ATH_DBG_FATAL, - "%s: Invalid channel\n", __func__); - return; - } - - if (hw->conf.ht_conf.ht_supported) - sc->sc_ah->ah_channels[pos].chanmode = - ath_get_extchanmode(sc, curchan); - else - sc->sc_ah->ah_channels[pos].chanmode = - (curchan->band == IEEE80211_BAND_2GHZ) ? - CHANNEL_G : CHANNEL_A; - - /* set h/w channel */ - if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) - DPRINTF(sc, ATH_DBG_FATAL, - "%s: Unable to set channel\n", - __func__); - - ath_rate_newstate(sc, avp); - /* Update ratectrl about the new state */ - ath_rc_node_update(hw, avp->rc_node); - } else { - DPRINTF(sc, ATH_DBG_CONFIG, - "%s: Bss Info DISSOC\n", __func__); - sc->sc_curaid = 0; - } -} - static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -910,9 +1541,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, __func__, bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) - sc->sc_flags |= ATH_PREAMBLE_SHORT; + sc->sc_flags |= SC_OP_PREAMBLE_SHORT; else - sc->sc_flags &= ~ATH_PREAMBLE_SHORT; + sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; } if (changed & BSS_CHANGED_ERP_CTS_PROT) { @@ -921,9 +1552,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && hw->conf.channel->band != IEEE80211_BAND_5GHZ) - sc->sc_flags |= ATH_PROTECT_ENABLE; + sc->sc_flags |= SC_OP_PROTECT_ENABLE; else - sc->sc_flags &= ~ATH_PROTECT_ENABLE; + sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; } if (changed & BSS_CHANGED_HT) { @@ -962,45 +1593,44 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) static int ath9k_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, - u16 tid, - u16 *ssn) + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) { struct ath_softc *sc = hw->priv; int ret = 0; switch (action) { case IEEE80211_AMPDU_RX_START: - ret = ath_rx_aggr_start(sc, addr, tid, ssn); + ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start RX aggregation\n", __func__); break; case IEEE80211_AMPDU_RX_STOP: - ret = ath_rx_aggr_stop(sc, addr, tid); + ret = ath_rx_aggr_stop(sc, sta->addr, tid); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop RX aggregation\n", __func__); break; case IEEE80211_AMPDU_TX_START: - ret = ath_tx_aggr_start(sc, addr, tid, ssn); + ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to start TX aggregation\n", __func__); else - ieee80211_start_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); break; case IEEE80211_AMPDU_TX_STOP: - ret = ath_tx_aggr_stop(sc, addr, tid); + ret = ath_tx_aggr_stop(sc, sta->addr, tid); if (ret < 0) DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to stop TX aggregation\n", __func__); - ieee80211_stop_tx_ba_cb_irqsafe(hw, (u8 *)addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); break; default: DPRINTF(sc, ATH_DBG_FATAL, @@ -1037,260 +1667,6 @@ static struct ieee80211_ops ath9k_ops = { .ampdu_action = ath9k_ampdu_action }; -void ath_get_beaconconfig(struct ath_softc *sc, - int if_id, - struct ath_beacon_config *conf) -{ - struct ieee80211_hw *hw = sc->hw; - - /* fill in beacon config data */ - - conf->beacon_interval = hw->conf.beacon_int; - conf->listen_interval = 100; - conf->dtim_count = 1; - conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; -} - -int ath_update_beacon(struct ath_softc *sc, - int if_id, - struct ath_beacon_offset *bo, - struct sk_buff *skb, - int mcast) -{ - return 0; -} - -void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - struct ath_xmit_status *tx_status, struct ath_node *an) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - DPRINTF(sc, ATH_DBG_XMIT, - "%s: TX complete: skb: %p\n", __func__, skb); - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || - tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - /* free driver's private data area of tx_info */ - if (tx_info->driver_data[0] != NULL) - kfree(tx_info->driver_data[0]); - tx_info->driver_data[0] = NULL; - } - - if (tx_status->flags & ATH_TX_BAR) { - tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - tx_status->flags &= ~ATH_TX_BAR; - } - - if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) { - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { - /* Frame was not ACKed, but an ACK was expected */ - tx_info->status.excessive_retries = 1; - } - } else { - /* Frame was ACKed */ - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } - - tx_info->status.retry_count = tx_status->retries; - - ieee80211_tx_status(hw, skb); - if (an) - ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE); -} - -int ath__rx_indicate(struct ath_softc *sc, - struct sk_buff *skb, - struct ath_recv_status *status, - u16 keyix) -{ - struct ieee80211_hw *hw = sc->hw; - struct ath_node *an = NULL; - struct ieee80211_rx_status rx_status; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - int padsize; - enum ATH_RX_TYPE st; - - /* see if any padding is done by the hw and remove it */ - if (hdrlen & 3) { - padsize = hdrlen % 4; - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - /* remove FCS before passing up to protocol stack */ - skb_trim(skb, (skb->len - FCS_LEN)); - - /* Prepare rx status */ - ath9k_rx_prepare(sc, skb, status, &rx_status); - - if (!(keyix == ATH9K_RXKEYIX_INVALID) && - !(status->flags & ATH_RX_DECRYPT_ERROR)) { - rx_status.flag |= RX_FLAG_DECRYPTED; - } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) - && !(status->flags & ATH_RX_DECRYPT_ERROR) - && skb->len >= hdrlen + 4) { - keyix = skb->data[hdrlen + 3] >> 6; - - if (test_bit(keyix, sc->sc_keymap)) - rx_status.flag |= RX_FLAG_DECRYPTED; - } - - spin_lock_bh(&sc->node_lock); - an = ath_node_find(sc, hdr->addr2); - spin_unlock_bh(&sc->node_lock); - - if (an) { - ath_rx_input(sc, an, - hw->conf.ht_conf.ht_supported, - skb, status, &st); - } - if (!an || (st != ATH_RX_CONSUMED)) - __ieee80211_rx(hw, skb, &rx_status); - - return 0; -} - -int ath_rx_subframe(struct ath_node *an, - struct sk_buff *skb, - struct ath_recv_status *status) -{ - struct ath_softc *sc = an->an_sc; - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_rx_status rx_status; - - /* Prepare rx status */ - ath9k_rx_prepare(sc, skb, status, &rx_status); - if (!(status->flags & ATH_RX_DECRYPT_ERROR)) - rx_status.flag |= RX_FLAG_DECRYPTED; - - __ieee80211_rx(hw, skb, &rx_status); - - return 0; -} - -enum ath9k_ht_macmode ath_cwm_macmode(struct ath_softc *sc) -{ - return sc->sc_ht_info.tx_chan_width; -} - -static int ath_detach(struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); - - /* Unregister hw */ - - ieee80211_unregister_hw(hw); - - /* unregister Rate control */ - ath_rate_control_unregister(); - - /* tx/rx cleanup */ - - ath_rx_cleanup(sc); - ath_tx_cleanup(sc); - - /* Deinit */ - - ath_deinit(sc); - - return 0; -} - -static int ath_attach(u16 devid, - struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - int error = 0; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__); - - error = ath_init(devid, sc); - if (error != 0) - return error; - - /* Init nodes */ - - INIT_LIST_HEAD(&sc->node_list); - spin_lock_init(&sc->node_lock); - - /* get mac address from hardware and set in mac80211 */ - - SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr); - - /* setup channels and rates */ - - sc->sbands[IEEE80211_BAND_2GHZ].channels = - sc->channels[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = - sc->rates[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 2.4Ghz*/ - setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = - sc->channels[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - sc->rates[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].band = - IEEE80211_BAND_5GHZ; - - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 5Ghz*/ - setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); - - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; - } - - /* FIXME: Have to figure out proper hw init values later */ - - hw->queues = 4; - hw->ampdu_queues = 1; - - /* Register rate control */ - hw->rate_control_algorithm = "ath9k_rate_control"; - error = ath_rate_control_register(); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "%s: Unable to register rate control " - "algorithm:%d\n", __func__, error); - ath_rate_control_unregister(); - goto bad; - } - - error = ieee80211_register_hw(hw); - if (error != 0) { - ath_rate_control_unregister(); - goto bad; - } - - /* initialize tx/rx engine */ - - error = ath_tx_init(sc, ATH_TXBUF); - if (error != 0) - goto bad1; - - error = ath_rx_init(sc, ATH_RXBUF); - if (error != 0) - goto bad1; - - return 0; -bad1: - ath_detach(sc); -bad: - return error; -} - static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { void __iomem *mem; @@ -1364,9 +1740,16 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto bad2; } - hw->flags = IEEE80211_HW_SIGNAL_DBM | + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + SET_IEEE80211_DEV(hw, &pdev->dev); pci_set_drvdata(pdev, hw); @@ -1414,10 +1797,17 @@ static void ath_pci_remove(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; + enum ath9k_int status; - if (pdev->irq) + if (pdev->irq) { + ath9k_hw_set_interrupts(sc->sc_ah, 0); + /* clear the ISR */ + ath9k_hw_getisr(sc->sc_ah, &status); + sc->sc_flags |= SC_OP_INVALID; free_irq(pdev->irq, sc); + } ath_detach(sc); + pci_iounmap(pdev, sc->mem); pci_release_region(pdev, 0); pci_disable_device(pdev); @@ -1428,6 +1818,16 @@ static void ath_pci_remove(struct pci_dev *pdev) static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) { + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; + + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#ifdef CONFIG_RFKILL + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); +#endif + pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, 3); @@ -1437,6 +1837,8 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int ath_pci_resume(struct pci_dev *pdev) { + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; u32 val; int err; @@ -1453,6 +1855,21 @@ static int ath_pci_resume(struct pci_dev *pdev) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + /* Enable LED */ + ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); + +#ifdef CONFIG_RFKILL + /* + * check the h/w rfkill state on resume + * and start the rfkill poll timer + */ + if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + queue_delayed_work(sc->hw->workqueue, + &sc->rf_kill.rfkill_poll, 0); +#endif + return 0; } diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 0cd399a5344..14702344448 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h @@ -18,19 +18,19 @@ #define PHY_H bool ath9k_hw_ar9280_set_channel(struct ath_hal *ah, - struct ath9k_channel - *chan); + struct ath9k_channel + *chan); bool ath9k_hw_set_channel(struct ath_hal *ah, - struct ath9k_channel *chan); + struct ath9k_channel *chan); void ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, u32 freqIndex, int regWrites); bool ath9k_hw_set_rf_regs(struct ath_hal *ah, - struct ath9k_channel *chan, - u16 modesIndex); + struct ath9k_channel *chan, + u16 modesIndex); void ath9k_hw_decrease_chain_power(struct ath_hal *ah, struct ath9k_channel *chan); bool ath9k_hw_init_rf(struct ath_hal *ah, - int *status); + int *status); #define AR_PHY_BASE 0x9800 #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 73c460ad355..cca2fc5b076 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -20,6 +20,7 @@ */ #include "core.h" +/* FIXME: remove this include! */ #include "../net/mac80211/rate.h" static u32 tx_triglevel_max; @@ -653,8 +654,8 @@ ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); for (i = 0; i < rate_table->rate_cnt; i++) { valid = (ath_rc_priv->single_stream ? - rate_table->info[i].valid_single_stream : - rate_table->info[i].valid); + rate_table->info[i].valid_single_stream : + rate_table->info[i].valid); if (valid == TRUE) { u32 phy = rate_table->info[i].phy; u8 valid_rate_count = 0; @@ -740,14 +741,14 @@ ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, for (j = 0; j < rate_table->rate_cnt; j++) { u32 phy = rate_table->info[j].phy; u32 valid = (ath_rc_priv->single_stream ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); + rate_table->info[j].valid_single_stream : + rate_table->info[j].valid); if (((((struct ath_rateset *) - mcs_set)->rs_rates[i] & 0x7F) != - (rate_table->info[j].dot11rate & 0x7F)) || - !WLAN_RC_PHY_HT(phy) || - !WLAN_RC_PHY_HT_VALID(valid, capflag)) + mcs_set)->rs_rates[i] & 0x7F) != + (rate_table->info[j].dot11rate & 0x7F)) || + !WLAN_RC_PHY_HT(phy) || + !WLAN_RC_PHY_HT_VALID(valid, capflag)) continue; if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) @@ -847,9 +848,9 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) /* For half and quarter rate channles use different * rate tables */ - if (sc->sc_curchan.channelFlags & CHANNEL_HALF) + if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF) ar5416_sethalf_ratetable(asc); - else if (sc->sc_curchan.channelFlags & CHANNEL_QUARTER) + else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER) ar5416_setquarter_ratetable(asc); else /* full rate */ ar5416_setfull_ratetable(asc); @@ -866,10 +867,10 @@ void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) } static u8 ath_rc_ratefind_ht(struct ath_softc *sc, - struct ath_rate_node *ath_rc_priv, - const struct ath_rate_table *rate_table, - int probe_allowed, int *is_probing, - int is_retry) + struct ath_rate_node *ath_rc_priv, + const struct ath_rate_table *rate_table, + int probe_allowed, int *is_probing, + int is_retry) { u32 dt, best_thruput, this_thruput, now_msec; u8 rate, next_rate, best_rate, maxindex, minindex; @@ -997,8 +998,8 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, rate = rate_ctrl->rate_table_size - 1; ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || - (rate_table->info[rate].valid_single_stream && - ath_rc_priv->single_stream)); + (rate_table->info[rate].valid_single_stream && + ath_rc_priv->single_stream)); return rate; } @@ -1023,10 +1024,10 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , } static u8 ath_rc_rate_getidx(struct ath_softc *sc, - struct ath_rate_node *ath_rc_priv, - const struct ath_rate_table *rate_table, - u8 rix, u16 stepdown, - u16 min_rate) + struct ath_rate_node *ath_rc_priv, + const struct ath_rate_table *rate_table, + u8 rix, u16 stepdown, + u16 min_rate) { u32 j; u8 nextindex; @@ -1066,8 +1067,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, rate_table = (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, - (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, - is_probe, is_retry); + (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, + is_probe, is_retry); nrix = rix; if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { @@ -1099,13 +1100,13 @@ static void ath_rc_ratefind(struct ath_softc *sc, try_num = ((i + 1) == num_rates) ? num_tries - (try_per_rate * i) : try_per_rate ; min_rate = (((i + 1) == num_rates) && - (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; + (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; nrix = ath_rc_rate_getidx(sc, ath_rc_priv, - rate_table, nrix, 1, min_rate); + rate_table, nrix, 1, min_rate); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, - &series[i], try_num, nrix, TRUE); + &series[i], try_num, nrix, TRUE); } /* @@ -1124,13 +1125,13 @@ static void ath_rc_ratefind(struct ath_softc *sc, * above conditions. */ if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) || - (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || - (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { + (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) || + (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) { u8 dot11rate = rate_table->info[rix].dot11rate; u8 phy = rate_table->info[rix].phy; if (i == 4 && ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || - (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { + (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { series[3].rix = series[2].rix; series[3].flags = series[2].flags; series[3].max_4ms_framelen = series[2].max_4ms_framelen; @@ -1141,18 +1142,19 @@ static void ath_rc_ratefind(struct ath_softc *sc, /* * Return the Tx rate series. */ -void ath_rate_findrate(struct ath_softc *sc, - struct ath_rate_node *ath_rc_priv, - int num_tries, - int num_rates, - unsigned int rcflag, - struct ath_rc_series series[], - int *is_probe, - int is_retry) +static void ath_rate_findrate(struct ath_softc *sc, + struct ath_rate_node *ath_rc_priv, + int num_tries, + int num_rates, + unsigned int rcflag, + struct ath_rc_series series[], + int *is_probe, + int is_retry) { struct ath_vap *avp = ath_rc_priv->avp; - DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); + DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); + if (!num_rates || !num_tries) return; @@ -1174,9 +1176,8 @@ void ath_rate_findrate(struct ath_softc *sc, unsigned int mcs; u8 series_rix = 0; - series[idx].tries = - IEEE80211_RATE_IDX_ENTRY( - avp->av_config.av_fixed_retryset, idx); + series[idx].tries = IEEE80211_RATE_IDX_ENTRY( + avp->av_config.av_fixed_retryset, idx); mcs = IEEE80211_RATE_IDX_ENTRY( avp->av_config.av_fixed_rateset, idx); @@ -1228,7 +1229,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, u32 now_msec = jiffies_to_msecs(jiffies); int state_change = FALSE, rate, count; u8 last_per; - struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; + struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; struct ath_rate_table *rate_table = (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; @@ -1272,14 +1273,14 @@ static void ath_rc_update_ht(struct ath_softc *sc, } else { /* xretries == 2 */ count = sizeof(nretry_to_per_lookup) / - sizeof(nretry_to_per_lookup[0]); + sizeof(nretry_to_per_lookup[0]); if (retries >= count) retries = count - 1; /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ rate_ctrl->state[tx_rate].per = (u8)(rate_ctrl->state[tx_rate].per - - (rate_ctrl->state[tx_rate].per >> 3) + - ((100) >> 3)); + (rate_ctrl->state[tx_rate].per >> 3) + + ((100) >> 3)); } /* xretries == 1 or 2 */ @@ -1295,8 +1296,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, if (retries >= count) retries = count - 1; if (info_priv->n_bad_frames) { - /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ - /* + /* new_PER = 7/8*old_PER + 1/8*(currentPER) * Assuming that n_frames is not 0. The current PER * from the retries is 100 * retries / (retries+1), * since the first retries attempts failed, and the @@ -1386,7 +1386,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, * rssi_ack values. */ if (tx_rate == rate_ctrl->rate_max_phy && - rate_ctrl->hw_maxretry_pktcnt < 255) { + rate_ctrl->hw_maxretry_pktcnt < 255) { rate_ctrl->hw_maxretry_pktcnt++; } @@ -1418,7 +1418,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, /* Now reduce the current * rssi threshold. */ if ((rssi_ackAvg < rssi_thres + 2) && - (rssi_thres > rssi_ack_vmin)) { + (rssi_thres > rssi_ack_vmin)) { rate_ctrl->state[tx_rate]. rssi_thres--; } @@ -1436,10 +1436,10 @@ static void ath_rc_update_ht(struct ath_softc *sc, * a while (except if we are probing). */ if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && - rate_table->info[tx_rate].ratekbps <= - rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { + rate_table->info[tx_rate].ratekbps <= + rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, - (u8) tx_rate, &rate_ctrl->rate_max_phy); + (u8) tx_rate, &rate_ctrl->rate_max_phy); /* Don't probe for a little while. */ rate_ctrl->probe_time = now_msec; @@ -1460,43 +1460,43 @@ static void ath_rc_update_ht(struct ath_softc *sc, break; if (rate_ctrl->state[rate].rssi_thres + - rate_table->info[rate].rssi_ack_deltamin > - rate_ctrl->state[rate+1].rssi_thres) { + rate_table->info[rate].rssi_ack_deltamin > + rate_ctrl->state[rate+1].rssi_thres) { rate_ctrl->state[rate+1].rssi_thres = rate_ctrl->state[rate]. - rssi_thres + + rssi_thres + rate_table->info[rate]. - rssi_ack_deltamin; + rssi_ack_deltamin; } } /* Make sure the rates below this have lower rssi thresholds. */ for (rate = tx_rate - 1; rate >= 0; rate--) { if (rate_table->info[rate].phy != - rate_table->info[tx_rate].phy) + rate_table->info[tx_rate].phy) break; if (rate_ctrl->state[rate].rssi_thres + - rate_table->info[rate].rssi_ack_deltamin > - rate_ctrl->state[rate+1].rssi_thres) { + rate_table->info[rate].rssi_ack_deltamin > + rate_ctrl->state[rate+1].rssi_thres) { if (rate_ctrl->state[rate+1].rssi_thres < - rate_table->info[rate]. - rssi_ack_deltamin) + rate_table->info[rate]. + rssi_ack_deltamin) rate_ctrl->state[rate].rssi_thres = 0; else { rate_ctrl->state[rate].rssi_thres = rate_ctrl->state[rate+1]. - rssi_thres - - rate_table->info[rate]. - rssi_ack_deltamin; + rssi_thres - + rate_table->info[rate]. + rssi_ack_deltamin; } if (rate_ctrl->state[rate].rssi_thres < - rate_table->info[rate]. - rssi_ack_validmin) { + rate_table->info[rate]. + rssi_ack_validmin) { rate_ctrl->state[rate].rssi_thres = rate_table->info[rate]. - rssi_ack_validmin; + rssi_ack_validmin; } } } @@ -1507,11 +1507,11 @@ static void ath_rc_update_ht(struct ath_softc *sc, if (rate_ctrl->state[tx_rate].per < last_per) { for (rate = tx_rate - 1; rate >= 0; rate--) { if (rate_table->info[rate].phy != - rate_table->info[tx_rate].phy) + rate_table->info[tx_rate].phy) break; if (rate_ctrl->state[rate].per > - rate_ctrl->state[rate+1].per) { + rate_ctrl->state[rate+1].per) { rate_ctrl->state[rate].per = rate_ctrl->state[rate+1].per; } @@ -1528,11 +1528,11 @@ static void ath_rc_update_ht(struct ath_softc *sc, /* Every so often, we reduce the thresholds and * PER (different for CCK and OFDM). */ if (now_msec - rate_ctrl->rssi_down_time >= - rate_table->rssi_reduce_interval) { + rate_table->rssi_reduce_interval) { for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { if (rate_ctrl->state[rate].rssi_thres > - rate_table->info[rate].rssi_ack_validmin) + rate_table->info[rate].rssi_ack_validmin) rate_ctrl->state[rate].rssi_thres -= 1; } rate_ctrl->rssi_down_time = now_msec; @@ -1541,7 +1541,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, /* Every so often, we reduce the thresholds * and PER (different for CCK and OFDM). */ if (now_msec - rate_ctrl->per_down_time >= - rate_table->rssi_reduce_interval) { + rate_table->rssi_reduce_interval) { for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { rate_ctrl->state[rate].per = 7 * rate_ctrl->state[rate].per / 8; @@ -1560,7 +1560,7 @@ static void ath_rc_update(struct ath_softc *sc, struct ath_tx_info_priv *info_priv, int final_ts_idx, int xretries, int long_retry) { - struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; + struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; struct ath_rate_table *rate_table; struct ath_tx_ratectrl *rate_ctrl; struct ath_rc_series rcs[4]; @@ -1637,7 +1637,6 @@ static void ath_rc_update(struct ath_softc *sc, xretries, long_retry); } - /* * Process a tx descriptor for a completed transmit (success or failure). */ @@ -1651,13 +1650,13 @@ static void ath_rate_tx_complete(struct ath_softc *sc, struct ath_vap *avp; avp = rc_priv->avp; - if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) - || info_priv->tx.ts_status & ATH9K_TXERR_FILT) + if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) || + (info_priv->tx.ts_status & ATH9K_TXERR_FILT)) return; if (info_priv->tx.ts_rssi > 0) { ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, - info_priv->tx.ts_rssi); + info_priv->tx.ts_rssi); } /* @@ -1682,7 +1681,6 @@ static void ath_rate_tx_complete(struct ath_softc *sc, info_priv->tx.ts_longretry); } - /* * Update the SIB's rate control information * @@ -1701,8 +1699,8 @@ static void ath_rc_sib_update(struct ath_softc *sc, struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; struct ath_rateset *rateset = negotiated_rates; u8 *ht_mcs = (u8 *)negotiated_htrates; - struct ath_tx_ratectrl *rate_ctrl = (struct ath_tx_ratectrl *) - (ath_rc_priv); + struct ath_tx_ratectrl *rate_ctrl = + (struct ath_tx_ratectrl *)ath_rc_priv; u8 i, j, k, hi = 0, hthi = 0; rate_table = (struct ath_rate_table *) @@ -1815,19 +1813,18 @@ static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) } -static void ath_setup_rates(struct ieee80211_local *local, struct sta_info *sta) +static void ath_setup_rates(struct ath_softc *sc, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, + struct ath_rate_node *rc_priv) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ath_softc *sc = hw->priv; - struct ath_rate_node *rc_priv = sta->rate_ctrl_priv; int i, j = 0; - DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); + for (i = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[local->hw.conf.channel->band] & BIT(i)) { + if (sta->supp_rates[sband->band] & BIT(i)) { rc_priv->neg_rates.rs_rates[j] = (sband->bitrates[i].bitrate * 2) / 10; j++; @@ -1854,19 +1851,17 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) } /* Rate Control callbacks */ -static void ath_tx_status(void *priv, struct net_device *dev, +static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { struct ath_softc *sc = priv; struct ath_tx_info_priv *tx_info_priv; struct ath_node *an; - struct sta_info *sta; - struct ieee80211_local *local; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr; __le16 fc; - local = hw_to_local(sc->hw); hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; @@ -1875,8 +1870,7 @@ static void ath_tx_status(void *priv, struct net_device *dev, an = ath_node_find(sc, hdr->addr1); spin_unlock_bh(&sc->node_lock); - sta = sta_info_get(local, hdr->addr1); - if (!an || !sta || !ieee80211_is_data(fc)) { + if (!an || !priv_sta || !ieee80211_is_data(fc)) { if (tx_info->driver_data[0] != NULL) { kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; @@ -1884,37 +1878,40 @@ static void ath_tx_status(void *priv, struct net_device *dev, return; } if (tx_info->driver_data[0] != NULL) { - ath_rate_tx_complete(sc, an, sta->rate_ctrl_priv, tx_info_priv); + ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); kfree(tx_info->driver_data[0]); tx_info->driver_data[0] = NULL; } } static void ath_tx_aggr_resp(struct ath_softc *sc, - struct sta_info *sta, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, struct ath_node *an, u8 tidno) { - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_local *local; struct ath_atx_tid *txtid; - struct ieee80211_supported_band *sband; u16 buffersize = 0; int state; - DECLARE_MAC_BUF(mac); + struct sta_info *si; - if (!sc->sc_txaggr) + if (!(sc->sc_flags & SC_OP_TXAGGR)) return; txtid = ATH_AN_2_TID(an, tidno); if (!txtid->paused) return; - local = hw_to_local(sc->hw); - sband = hw->wiphy->bands[hw->conf.channel->band]; + /* + * XXX: This is entirely busted, we aren't supposed to + * access the sta from here because it's internal + * to mac80211, and looking at the state without + * locking is wrong too. + */ + si = container_of(sta, struct sta_info, sta); buffersize = IEEE80211_MIN_AMPDU_BUF << sband->ht_info.ampdu_factor; /* FIXME */ - state = sta->ampdu_mlme.tid_state_tx[tidno]; + state = si->ampdu_mlme.tid_state_tx[tidno]; if (state & HT_ADDBA_RECEIVED_MSK) { txtid->addba_exchangecomplete = 1; @@ -1930,21 +1927,18 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, } } -static void ath_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) +static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb, struct rate_selection *sel) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sta_info *sta; - struct ath_softc *sc = (struct ath_softc *)priv; + struct ath_softc *sc = priv; struct ieee80211_hw *hw = sc->hw; struct ath_tx_info_priv *tx_info_priv; - struct ath_rate_node *ath_rc_priv; + struct ath_rate_node *ath_rc_priv = priv_sta; struct ath_node *an; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - int is_probe, chk, ret; + int is_probe = FALSE, chk, ret; s8 lowest_idx; __le16 fc = hdr->frame_control; u8 *qc, tid; @@ -1957,18 +1951,15 @@ static void ath_get_rate(void *priv, struct net_device *dev, ASSERT(tx_info->driver_data[0] != NULL); tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; - sta = sta_info_get(local, hdr->addr1); - lowest_idx = rate_lowest_index(local, sband, sta); + lowest_idx = rate_lowest_index(sband, sta); tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; /* lowest rate for management and multicast/broadcast frames */ if (!ieee80211_is_data(fc) || - is_multicast_ether_addr(hdr->addr1) || !sta) { + is_multicast_ether_addr(hdr->addr1) || !sta) { sel->rate_idx = lowest_idx; return; } - ath_rc_priv = sta->rate_ctrl_priv; - /* Find tx rate for unicast frames */ ath_rate_findrate(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, @@ -1977,8 +1968,7 @@ static void ath_get_rate(void *priv, struct net_device *dev, &is_probe, false); if (is_probe) - sel->probe_idx = ((struct ath_tx_ratectrl *) - sta->rate_ctrl_priv)->probe_rate; + sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; /* Ratecontrol sometimes returns invalid rate index */ if (tx_info_priv->rcs[0].rix != 0xff) @@ -2022,38 +2012,31 @@ static void ath_get_rate(void *priv, struct net_device *dev, __func__, print_mac(mac, hdr->addr1)); } else if (chk == AGGR_EXCHANGE_PROGRESS) - ath_tx_aggr_resp(sc, sta, an, tid); + ath_tx_aggr_resp(sc, sband, sta, an, tid); } } } -static void ath_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) +static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta) { - struct ieee80211_supported_band *sband; - struct ieee80211_hw *hw = local_to_hw(local); - struct ieee80211_conf *conf = &local->hw.conf; - struct ath_softc *sc = hw->priv; + struct ath_softc *sc = priv; + struct ath_rate_node *ath_rc_priv = priv_sta; int i, j = 0; DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sta->txrate_idx = rate_lowest_index(local, sband, sta); - - ath_setup_rates(local, sta); - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + ath_setup_rates(sc, sband, sta, ath_rc_priv); + if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { for (i = 0; i < MCS_SET_SIZE; i++) { - if (conf->ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) - ((struct ath_rate_node *) - priv_sta)->neg_ht_rates.rs_rates[j++] = i; + if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) + ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; if (j == ATH_RATE_MAX) break; } - ((struct ath_rate_node *)priv_sta)->neg_ht_rates.rs_nrates = j; + ath_rc_priv->neg_ht_rates.rs_nrates = j; } - ath_rc_node_update(hw, priv_sta); + ath_rc_node_update(sc->hw, priv_sta); } static void ath_rate_clear(void *priv) @@ -2061,13 +2044,12 @@ static void ath_rate_clear(void *priv) return; } -static void *ath_rate_alloc(struct ieee80211_local *local) +static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { - struct ieee80211_hw *hw = local_to_hw(local); struct ath_softc *sc = hw->priv; - DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); - return local->hw.priv; + DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); + return hw->priv; } static void ath_rate_free(void *priv) @@ -2075,24 +2057,28 @@ static void ath_rate_free(void *priv) return; } -static void *ath_rate_alloc_sta(void *priv, gfp_t gfp) +static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) { struct ath_softc *sc = priv; struct ath_vap *avp = sc->sc_vaps[0]; struct ath_rate_node *rate_priv; - DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); + DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); + rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); if (!rate_priv) { - DPRINTF(sc, ATH_DBG_FATAL, "%s:Unable to allocate" - "private rate control structure", __func__); + DPRINTF(sc, ATH_DBG_FATAL, + "%s: Unable to allocate private rc structure\n", + __func__); return NULL; } ath_rc_sib_init(rate_priv); + return rate_priv; } -static void ath_rate_free_sta(void *priv, void *priv_sta) +static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, + void *priv_sta) { struct ath_rate_node *rate_priv = priv_sta; struct ath_softc *sc = priv; @@ -2111,7 +2097,7 @@ static struct rate_control_ops ath_rate_ops = { .alloc = ath_rate_alloc, .free = ath_rate_free, .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta + .free_sta = ath_rate_free_sta, }; int ath_rate_control_register(void) diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index 71aef9c7523..b95b41508b9 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h @@ -71,9 +71,6 @@ enum ieee80211_fixed_rate_mode { */ #define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) -#define SHORT_PRE 1 -#define LONG_PRE 0 - #define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS #define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS #define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI @@ -102,18 +99,18 @@ enum { WLAN_RC_PHY_MAX }; -#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ + || (_phy == WLAN_RC_PHY_HT_40_DS) \ + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ + || (_phy == WLAN_RC_PHY_HT_40_DS) \ + || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) #define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) @@ -135,56 +132,59 @@ enum { #define WLAN_RC_SGI_FLAG (0x04) #define WLAN_RC_HT_FLAG (0x08) -/* Index into the rate table */ -#define INIT_RATE_MAX_20 23 -#define INIT_RATE_MAX_40 40 - #define RATE_TABLE_SIZE 64 -/* XXX: Convert to kdoc */ +/** + * struct ath_rate_table - Rate Control table + * @valid: valid for use in rate control + * @valid_single_stream: valid for use in rate control for + * single stream operation + * @phy: CCK/OFDM + * @ratekbps: rate in Kbits per second + * @user_ratekbps: user rate in Kbits per second + * @ratecode: rate that goes into HW descriptors + * @short_preamble: Mask for enabling short preamble in ratecode for CCK + * @dot11rate: value that goes into supported + * rates info element of MLME + * @ctrl_rate: Index of next lower basic rate, used for duration computation + * @max_4ms_framelen: maximum frame length(bytes) for tx duration + * @probe_interval: interval for rate control to probe for other rates + * @rssi_reduce_interval: interval for rate control to reduce rssi + * @initial_ratemax: initial ratemax value used in ath_rc_sib_update() + */ struct ath_rate_table { int rate_cnt; struct { - int valid; /* Valid for use in rate control */ - int valid_single_stream;/* Valid for use in rate control - for single stream operation */ - u8 phy; /* CCK/OFDM/TURBO/XR */ - u32 ratekbps; /* Rate in Kbits per second */ - u32 user_ratekbps; /* User rate in KBits per second */ - u8 ratecode; /* rate that goes into - hw descriptors */ - u8 short_preamble; /* Mask for enabling short preamble - in rate code for CCK */ - u8 dot11rate; /* Value that goes into supported - rates info element of MLME */ - u8 ctrl_rate; /* Index of next lower basic rate, - used for duration computation */ - int8_t rssi_ack_validmin; /* Rate control related */ - int8_t rssi_ack_deltamin; /* Rate control related */ - u8 base_index; /* base rate index */ - u8 cw40index; /* 40cap rate index */ - u8 sgi_index; /* shortgi rate index */ - u8 ht_index; /* shortgi rate index */ - u32 max_4ms_framelen; /* Maximum frame length(bytes) - for 4ms tx duration */ + int valid; + int valid_single_stream; + u8 phy; + u32 ratekbps; + u32 user_ratekbps; + u8 ratecode; + u8 short_preamble; + u8 dot11rate; + u8 ctrl_rate; + int8_t rssi_ack_validmin; + int8_t rssi_ack_deltamin; + u8 base_index; + u8 cw40index; + u8 sgi_index; + u8 ht_index; + u32 max_4ms_framelen; } info[RATE_TABLE_SIZE]; - u32 probe_interval; /* interval for ratectrl to - probe for other rates */ - u32 rssi_reduce_interval; /* interval for ratectrl - to reduce RSSI */ - u8 initial_ratemax; /* the initial ratemax value used - in ath_rc_sib_update() */ + u32 probe_interval; + u32 rssi_reduce_interval; + u8 initial_ratemax; }; #define ATH_RC_PROBE_ALLOWED 0x00000001 #define ATH_RC_MINRATE_LASTRATE 0x00000002 -#define ATH_RC_SHORT_PREAMBLE 0x00000004 struct ath_rc_series { - u8 rix; - u8 tries; - u8 flags; - u32 max_4ms_framelen; + u8 rix; + u8 tries; + u8 flags; + u32 max_4ms_framelen; }; /* rcs_flags definition */ @@ -201,42 +201,56 @@ struct ath_rc_series { #define MAX_TX_RATE_PHY 48 struct ath_tx_ratectrl_state { - int8_t rssi_thres; /* required rssi for this rate (dB) */ - u8 per; /* recent estimate of packet error rate (%) */ + int8_t rssi_thres; /* required rssi for this rate (dB) */ + u8 per; /* recent estimate of packet error rate (%) */ }; +/** + * struct ath_tx_ratectrl - TX Rate control Information + * @state: RC state + * @rssi_last: last ACK rssi + * @rssi_last_lookup: last ACK rssi used for lookup + * @rssi_last_prev: previous last ACK rssi + * @rssi_last_prev2: 2nd previous last ACK rssi + * @rssi_sum_cnt: count of rssi_sum for averaging + * @rssi_sum_rate: rate that we are averaging + * @rssi_sum: running sum of rssi for averaging + * @probe_rate: rate we are probing at + * @rssi_time: msec timestamp for last ack rssi + * @rssi_down_time: msec timestamp for last down step + * @probe_time: msec timestamp for last probe + * @hw_maxretry_pktcnt: num of packets since we got HW max retry error + * @max_valid_rate: maximum number of valid rate + * @per_down_time: msec timestamp for last PER down step + * @valid_phy_ratecnt: valid rate count + * @rate_max_phy: phy index for the max rate + * @probe_interval: interval for ratectrl to probe for other rates + */ struct ath_tx_ratectrl { - struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; /* state */ - int8_t rssi_last; /* last ack rssi */ - int8_t rssi_last_lookup; /* last ack rssi used for lookup */ - int8_t rssi_last_prev; /* previous last ack rssi */ - int8_t rssi_last_prev2; /* 2nd previous last ack rssi */ - int32_t rssi_sum_cnt; /* count of rssi_sum for averaging */ - int32_t rssi_sum_rate; /* rate that we are averaging */ - int32_t rssi_sum; /* running sum of rssi for averaging */ - u32 valid_txrate_mask; /* mask of valid rates */ - u8 rate_table_size; /* rate table size */ - u8 rate_max; /* max rate that has recently worked */ - u8 probe_rate; /* rate we are probing at */ - u32 rssi_time; /* msec timestamp for last ack rssi */ - u32 rssi_down_time; /* msec timestamp for last down step */ - u32 probe_time; /* msec timestamp for last probe */ - u8 hw_maxretry_pktcnt; /* num packets since we got - HW max retry error */ - u8 max_valid_rate; /* maximum number of valid rate */ - u8 valid_rate_index[MAX_TX_RATE_TBL]; /* valid rate index */ - u32 per_down_time; /* msec timstamp for last - PER down step */ + struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; + int8_t rssi_last; + int8_t rssi_last_lookup; + int8_t rssi_last_prev; + int8_t rssi_last_prev2; + int32_t rssi_sum_cnt; + int32_t rssi_sum_rate; + int32_t rssi_sum; + u8 rate_table_size; + u8 probe_rate; + u32 rssi_time; + u32 rssi_down_time; + u32 probe_time; + u8 hw_maxretry_pktcnt; + u8 max_valid_rate; + u8 valid_rate_index[MAX_TX_RATE_TBL]; + u32 per_down_time; /* 11n state */ - u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; /* valid rate count */ - u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; - u8 rc_phy_mode; - u8 rate_max_phy; /* Phy index for the max rate */ - u32 rate_max_lastused; /* msec timstamp of when we - last used rateMaxPhy */ - u32 probe_interval; /* interval for ratectrl to probe - for other rates */ + u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; + u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; + u8 rc_phy_mode; + u8 rate_max_phy; + u32 probe_interval; }; struct ath_rateset { @@ -248,29 +262,32 @@ struct ath_rateset { struct ath_rate_softc { /* phy tables that contain rate control data */ const void *hw_rate_table[ATH9K_MODE_MAX]; - int fixedrix; /* -1 or index of fixed rate */ + + /* -1 or index of fixed rate */ + int fixedrix; }; /* per-node state */ struct ath_rate_node { - struct ath_tx_ratectrl tx_ratectrl; /* rate control state proper */ - u32 prev_data_rix; /* rate idx of last data frame */ + struct ath_tx_ratectrl tx_ratectrl; - /* map of rate ix -> negotiated rate set ix */ - u8 rixmap[MAX_TX_RATE_TBL]; + /* rate idx of last data frame */ + u32 prev_data_rix; - /* map of ht rate ix -> negotiated rate set ix */ - u8 ht_rixmap[MAX_TX_RATE_TBL]; + /* ht capabilities */ + u8 ht_cap; - u8 ht_cap; /* ht capabilities */ - u8 ant_tx; /* current transmit antenna */ + /* When TRUE, only single stream Tx possible */ + u8 single_stream; - u8 single_stream; /* When TRUE, only single - stream Tx possible */ - struct ath_rateset neg_rates; /* Negotiated rates */ - struct ath_rateset neg_ht_rates; /* Negotiated HT rates */ - struct ath_rate_softc *asc; /* back pointer to atheros softc */ - struct ath_vap *avp; /* back pointer to vap */ + /* Negotiated rates */ + struct ath_rateset neg_rates; + + /* Negotiated HT rates */ + struct ath_rateset neg_ht_rates; + + struct ath_rate_softc *asc; + struct ath_vap *avp; }; /* Driver data of ieee80211_tx_info */ @@ -297,17 +314,10 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv); void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp); /* - * Return the tx rate series. - */ -void ath_rate_findrate(struct ath_softc *sc, struct ath_rate_node *ath_rc_priv, - int num_tries, int num_rates, - unsigned int rcflag, struct ath_rc_series[], - int *is_probe, int isretry); -/* * Return rate index for given Dot11 Rate. */ u8 ath_rate_findrateix(struct ath_softc *sc, - u8 dot11_rate); + u8 dot11_rate); /* Routines to register/unregister rate control algorithm */ int ath_rate_control_register(void); diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 20ddb7acdb9..4983402af55 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -184,7 +184,7 @@ static int ath_ampdu_input(struct ath_softc *sc, tid = qc[0] & 0xf; } - if (sc->sc_opmode == ATH9K_M_STA) { + if (sc->sc_ah->ah_opmode == ATH9K_M_STA) { /* Drop the frame not belonging to me. */ if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) { dev_kfree_skb(skb); @@ -449,17 +449,16 @@ static int ath_rx_indicate(struct ath_softc *sc, int type; /* indicate frame to the stack, which will free the old skb. */ - type = ath__rx_indicate(sc, skb, status, keyix); + type = _ath_rx_indicate(sc, skb, status, keyix); /* allocate a new skb and queue it to for H/W processing */ nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); if (nskb != NULL) { bf->bf_mpdu = nskb; - bf->bf_buf_addr = ath_skb_map_single(sc, - nskb, - PCI_DMA_FROMDEVICE, - /* XXX: Remove get_dma_mem_context() */ - get_dma_mem_context(bf, bf_dmacontext)); + bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data, + skb_end_pointer(nskb) - nskb->head, + PCI_DMA_FROMDEVICE); + bf->bf_dmacontext = bf->bf_buf_addr; ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; /* queue the new wbuf to H/W */ @@ -505,7 +504,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) do { spin_lock_init(&sc->sc_rxflushlock); - sc->sc_rxflush = 0; + sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->sc_rxbuflock); /* @@ -542,9 +541,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) } bf->bf_mpdu = skb; - bf->bf_buf_addr = - ath_skb_map_single(sc, skb, PCI_DMA_FROMDEVICE, - get_dma_mem_context(bf, bf_dmacontext)); + bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data, + skb_end_pointer(skb) - skb->head, + PCI_DMA_FROMDEVICE); + bf->bf_dmacontext = bf->bf_buf_addr; ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; } sc->sc_rxlink = NULL; @@ -598,6 +598,7 @@ void ath_rx_cleanup(struct ath_softc *sc) u32 ath_calcrxfilter(struct ath_softc *sc) { #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) + u32 rfilt; rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) @@ -605,25 +606,29 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | ATH9K_RX_FILTER_MCAST; /* If not a STA, enable processing of Probe Requests */ - if (sc->sc_opmode != ATH9K_M_STA) + if (sc->sc_ah->ah_opmode != ATH9K_M_STA) rfilt |= ATH9K_RX_FILTER_PROBEREQ; /* Can't set HOSTAP into promiscous mode */ - if (sc->sc_opmode == ATH9K_M_MONITOR) { + if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) && + (sc->rx_filter & FIF_PROMISC_IN_BSS)) || + (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) { rfilt |= ATH9K_RX_FILTER_PROM; /* ??? To prevent from sending ACK */ rfilt &= ~ATH9K_RX_FILTER_UCAST; } - if (sc->sc_opmode == ATH9K_M_STA || sc->sc_opmode == ATH9K_M_IBSS || - sc->sc_scanning) + if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) && + (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) || + (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)) rfilt |= ATH9K_RX_FILTER_BEACON; /* If in HOSTAP mode, want to enable reception of PSPOLL frames & beacon frames */ - if (sc->sc_opmode == ATH9K_M_HOSTAP) + if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); return rfilt; + #undef RX_FILTER_PRESERVE } @@ -703,11 +708,11 @@ void ath_flushrecv(struct ath_softc *sc) * progress (see references to sc_rxflush) */ spin_lock_bh(&sc->sc_rxflushlock); - sc->sc_rxflush = 1; + sc->sc_flags |= SC_OP_RXFLUSH; ath_rx_tasklet(sc, 1); - sc->sc_rxflush = 0; + sc->sc_flags &= ~SC_OP_RXFLUSH; spin_unlock_bh(&sc->sc_rxflushlock); } @@ -720,7 +725,7 @@ int ath_rx_input(struct ath_softc *sc, struct ath_recv_status *rx_status, enum ATH_RX_TYPE *status) { - if (is_ampdu && sc->sc_rxaggr) { + if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) { *status = ATH_RX_CONSUMED; return ath_ampdu_input(sc, an, skb, rx_status); } else { @@ -751,7 +756,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) do { /* If handling rx interrupt and flush is in progress => exit */ - if (sc->sc_rxflush && (flush == 0)) + if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; spin_lock_bh(&sc->sc_rxbuflock); @@ -887,7 +892,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; - memzero(&rx_status, sizeof(struct ath_recv_status)); + memset(&rx_status, 0, sizeof(struct ath_recv_status)); if (ds->ds_rxstat.rs_more) { /* @@ -901,7 +906,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * Enable this if you want to see * error frames in Monitor mode. */ - if (sc->sc_opmode != ATH9K_M_MONITOR) + if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR) goto rx_next; #endif /* fall thru for monitor mode handling... */ @@ -946,7 +951,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) * decryption and MIC failures. For monitor mode, * we also ignore the CRC error. */ - if (sc->sc_opmode == ATH9K_M_MONITOR) { + if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) { if (ds->ds_rxstat.rs_status & ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | ATH9K_RXERR_CRC)) @@ -994,20 +999,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) rx_status.flags |= ATH_RX_SHORT_GI; } - /* sc->sc_noise_floor is only available when the station + /* sc_noise_floor is only available when the station attaches to an AP, so we use a default value if we are not yet attached. */ - - /* XXX we should use either sc->sc_noise_floor or - * ath_hal_getChanNoise(ah, &sc->sc_curchan) - * to calculate the noise floor. - * However, the value returned by ath_hal_getChanNoise - * seems to be incorrect (-31dBm on the last test), - * so we will use a hard-coded value until we - * figure out what is going on. - */ rx_status.abs_rssi = - ds->ds_rxstat.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; + ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor; pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, @@ -1090,7 +1086,7 @@ rx_next: "%s: Reset rx chain mask. " "Do internal reset\n", __func__); ASSERT(flush == 0); - ath_internal_reset(sc); + ath_reset(sc, false); } return 0; @@ -1128,7 +1124,7 @@ int ath_rx_aggr_start(struct ath_softc *sc, rxtid = &an->an_aggr.rx.tid[tid]; spin_lock_bh(&rxtid->tidlock); - if (sc->sc_rxaggr) { + if (sc->sc_flags & SC_OP_RXAGGR) { /* Allow aggregation reception * Adjust rx BA window size. Peer might indicate a * zero buffer size for a _dont_care_ condition. @@ -1161,7 +1157,7 @@ int ath_rx_aggr_start(struct ath_softc *sc, } else { /* Ensure the memory is zeroed out (all internal * pointers are null) */ - memzero(rxtid->rxbuf, ATH_TID_MAX_BUFS * + memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS * sizeof(struct ath_rxbuf)); DPRINTF(sc, ATH_DBG_AGGR, "%s: Allocated @%p\n", __func__, rxtid->rxbuf); @@ -1228,7 +1224,7 @@ void ath_rx_aggr_teardown(struct ath_softc *sc, void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) { - if (sc->sc_rxaggr) { + if (sc->sc_flags & SC_OP_RXAGGR) { struct ath_arx_tid *rxtid; int tidno; @@ -1260,7 +1256,7 @@ void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an) void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an) { - if (sc->sc_rxaggr) { + if (sc->sc_flags & SC_OP_RXAGGR) { struct ath_arx_tid *rxtid; int tidno, i; @@ -1293,27 +1289,3 @@ void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an) { ath_rx_node_cleanup(sc, an); } - -dma_addr_t ath_skb_map_single(struct ath_softc *sc, - struct sk_buff *skb, - int direction, - dma_addr_t *pa) -{ - /* - * NB: do NOT use skb->len, which is 0 on initialization. - * Use skb's entire data area instead. - */ - *pa = pci_map_single(sc->pdev, skb->data, - skb_end_pointer(skb) - skb->head, direction); - return *pa; -} - -void ath_skb_unmap_single(struct ath_softc *sc, - struct sk_buff *skb, - int direction, - dma_addr_t *pa) -{ - /* Unmap skb's entire data area */ - pci_unmap_single(sc->pdev, *pa, - skb_end_pointer(skb) - skb->head, direction); -} diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index 42b0890a468..60617ae6620 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h @@ -899,12 +899,6 @@ enum { #define AR_GPIO_OUTPUT_MUX2 0x4064 #define AR_GPIO_OUTPUT_MUX3 0x4068 -#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 - #define AR_INPUT_STATE 0x406c #define AR_EEPROM_STATUS_DATA 0x407c diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 550129f717e..3a4757942b3 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -60,79 +60,6 @@ static u32 bits_per_symbol[][2] = { #define IS_HT_RATE(_rate) ((_rate) & 0x80) /* - * Insert a chain of ath_buf (descriptors) on a multicast txq - * but do NOT start tx DMA on this queue. - * NB: must be called with txq lock held - */ - -static void ath_tx_mcastqaddbuf(struct ath_softc *sc, - struct ath_txq *txq, - struct list_head *head) -{ - struct ath_hal *ah = sc->sc_ah; - struct ath_buf *bf; - - if (list_empty(head)) - return; - - /* - * Insert the frame on the outbound list and - * pass it on to the hardware. - */ - bf = list_first_entry(head, struct ath_buf, list); - - /* - * The CAB queue is started from the SWBA handler since - * frames only go out on DTIM and to avoid possible races. - */ - ath9k_hw_set_interrupts(ah, 0); - - /* - * If there is anything in the mcastq, we want to set - * the "more data" bit in the last item in the queue to - * indicate that there is "more data". It makes sense to add - * it here since you are *always* going to have - * more data when adding to this queue, no matter where - * you call from. - */ - - if (txq->axq_depth) { - struct ath_buf *lbf; - struct ieee80211_hdr *hdr; - - /* - * Add the "more data flag" to the last frame - */ - - lbf = list_entry(txq->axq_q.prev, struct ath_buf, list); - hdr = (struct ieee80211_hdr *) - ((struct sk_buff *)(lbf->bf_mpdu))->data; - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } - - /* - * Now, concat the frame onto the queue - */ - list_splice_tail_init(head, &txq->axq_q); - txq->axq_depth++; - txq->axq_totalqueued++; - txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); - - DPRINTF(sc, ATH_DBG_QUEUE, - "%s: txq depth = %d\n", __func__, txq->axq_depth); - if (txq->axq_link != NULL) { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DBG_XMIT, - "%s: link[%u](%p)=%llx (%p)\n", - __func__, - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); - } - txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); - ath9k_hw_set_interrupts(ah, sc->sc_imask); -} - -/* * Insert a chain of ath_buf (descriptors) on a txq and * assume the descriptors are already chained together by caller. * NB: must be called with txq lock held @@ -277,8 +204,6 @@ static int ath_tx_prepare(struct ath_softc *sc, __le16 fc; u8 *qc; - memset(txctl, 0, sizeof(struct ath_tx_control)); - txctl->dev = sc; hdr = (struct ieee80211_hdr *)skb->data; hdrlen = ieee80211_get_hdrlen_from_skb(skb); @@ -302,7 +227,6 @@ static int ath_tx_prepare(struct ath_softc *sc, } txctl->if_id = 0; - txctl->nextfraglen = 0; txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3); txctl->txpower = MAX_RATE_POWER; /* FIXME */ @@ -313,13 +237,13 @@ static int ath_tx_prepare(struct ath_softc *sc, if (tx_info->control.hw_key) { txctl->keyix = tx_info->control.hw_key->hw_key_idx; - txctl->frmlen += tx_info->control.icv_len; + txctl->frmlen += tx_info->control.hw_key->icv_len; - if (sc->sc_keytype == ATH9K_CIPHER_WEP) + if (tx_info->control.hw_key->alg == ALG_WEP) txctl->keytype = ATH9K_KEY_TYPE_WEP; - else if (sc->sc_keytype == ATH9K_CIPHER_TKIP) + else if (tx_info->control.hw_key->alg == ALG_TKIP) txctl->keytype = ATH9K_KEY_TYPE_TKIP; - else if (sc->sc_keytype == ATH9K_CIPHER_AES_CCM) + else if (tx_info->control.hw_key->alg == ALG_CCMP) txctl->keytype = ATH9K_KEY_TYPE_AES; } @@ -329,12 +253,18 @@ static int ath_tx_prepare(struct ath_softc *sc, /* Fill qnum */ - txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txq = &sc->sc_txq[txctl->qnum]; + if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) { + txctl->qnum = 0; + txq = sc->sc_cabq; + } else { + txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); + txq = &sc->sc_txq[txctl->qnum]; + } spin_lock_bh(&txq->axq_lock); /* Try to avoid running out of descriptors */ - if (txq->axq_depth >= (ATH_TXBUF - 20)) { + if (txq->axq_depth >= (ATH_TXBUF - 20) && + !(txctl->flags & ATH9K_TXDESC_CAB)) { DPRINTF(sc, ATH_DBG_FATAL, "%s: TX queue: %d is full, depth: %d\n", __func__, @@ -354,7 +284,7 @@ static int ath_tx_prepare(struct ath_softc *sc, /* Fill flags */ - txctl->flags = ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ + txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) txctl->flags |= ATH9K_TXDESC_NOACK; @@ -392,7 +322,7 @@ static int ath_tx_prepare(struct ath_softc *sc, * incremented by the fragmentation routine. */ if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) && - txctl->ht && sc->sc_txaggr) { + txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { struct ath_atx_tid *tid; tid = ATH_AN_2_TID(txctl->an, txctl->tidno); @@ -413,50 +343,18 @@ static int ath_tx_prepare(struct ath_softc *sc, } rix = rcs[0].rix; - /* - * Calculate duration. This logically belongs in the 802.11 - * layer but it lacks sufficient information to calculate it. - */ - if ((txctl->flags & ATH9K_TXDESC_NOACK) == 0 && !ieee80211_is_ctl(fc)) { - u16 dur; + if (ieee80211_has_morefrags(fc) || + (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { /* - * XXX not right with fragmentation. - */ - if (sc->sc_flags & ATH_PREAMBLE_SHORT) - dur = rt->info[rix].spAckDuration; - else - dur = rt->info[rix].lpAckDuration; - - if (le16_to_cpu(hdr->frame_control) & - IEEE80211_FCTL_MOREFRAGS) { - dur += dur; /* Add additional 'SIFS + ACK' */ - - /* - ** Compute size of next fragment in order to compute - ** durations needed to update NAV. - ** The last fragment uses the ACK duration only. - ** Add time for next fragment. - */ - dur += ath9k_hw_computetxtime(sc->sc_ah, rt, - txctl->nextfraglen, - rix, sc->sc_flags & ATH_PREAMBLE_SHORT); - } - - if (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { - /* - ** Force hardware to use computed duration for next - ** fragment by disabling multi-rate retry, which - ** updates duration based on the multi-rate - ** duration table. - */ - rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; - rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; - /* reset tries but keep rate index */ - rcs[0].tries = ATH_TXMAXTRY; - } - - hdr->duration_id = cpu_to_le16(dur); + ** Force hardware to use computed duration for next + ** fragment by disabling multi-rate retry, which + ** updates duration based on the multi-rate + ** duration table. + */ + rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; + rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; + /* reset tries but keep rate index */ + rcs[0].tries = ATH_TXMAXTRY; } /* @@ -484,12 +382,8 @@ static int ath_tx_prepare(struct ath_softc *sc, if (is_multicast_ether_addr(hdr->addr1)) { antenna = sc->sc_mcastantenna + 1; sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1; - } else - antenna = sc->sc_txantenna; + } -#ifdef USE_LEGACY_HAL - txctl->antenna = antenna; -#endif return 0; } @@ -502,7 +396,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, { struct sk_buff *skb = bf->bf_mpdu; struct ath_xmit_status tx_status; - dma_addr_t *pa; /* * Set retry information. @@ -518,13 +411,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, if (!txok) { tx_status.flags |= ATH_TX_ERROR; - if (bf->bf_isxretried) + if (bf_isxretried(bf)) tx_status.flags |= ATH_TX_XRETRY; } /* Unmap this frame */ - pa = get_dma_mem_context(bf, bf_dmacontext); pci_unmap_single(sc->pdev, - *pa, + bf->bf_dmacontext, skb->len, PCI_DMA_TODEVICE); /* complete this frame */ @@ -629,7 +521,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) return 0; - isaggr = bf->bf_isaggr; + isaggr = bf_isaggr(bf); if (isaggr) { seq_st = ATH_DS_BA_SEQ(ds); memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); @@ -651,7 +543,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf) struct sk_buff *skb; struct ieee80211_hdr *hdr; - bf->bf_isretried = 1; + bf->bf_state.bf_type |= BUF_RETRY; bf->bf_retries++; skb = bf->bf_mpdu; @@ -698,7 +590,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rc; int streams, pktlen; - pktlen = bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen; + pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; rc = rt->info[rix].rateCode; /* @@ -742,7 +634,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) int i, flags, rtsctsena = 0, dynamic_mimops = 0; u32 ctsduration = 0; u8 rix = 0, cix, ctsrate = 0; - u32 aggr_limit_with_rts = sc->sc_rtsaggrlimit; + u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit; struct ath_node *an = (struct ath_node *) bf->bf_node; /* @@ -781,7 +673,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) * let rate series flags determine which rates will actually * use RTS. */ - if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf->bf_isdata) { + if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { BUG_ON(!an); /* * 802.11g protection not needed, use our default behavior @@ -793,7 +685,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) * and the second aggregate should have any protection at all. */ if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) { - if (!bf->bf_aggrburst) { + if (!bf_isaggrburst(bf)) { flags = ATH9K_TXDESC_RTSENA; dynamic_mimops = 1; } else { @@ -806,7 +698,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) * Set protection if aggregate protection on */ if (sc->sc_config.ath_aggr_prot && - (!bf->bf_isaggr || (bf->bf_isaggr && bf->bf_al < 8192))) { + (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { flags = ATH9K_TXDESC_RTSENA; cix = rt->info[sc->sc_protrix].controlRate; rtsctsena = 1; @@ -815,7 +707,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) /* * For AR5416 - RTS cannot be followed by a frame larger than 8K. */ - if (bf->bf_isaggr && (bf->bf_al > aggr_limit_with_rts)) { + if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) { /* * Ensure that in the case of SM Dynamic power save * while we are bursting the second aggregate the @@ -832,12 +724,12 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) /* NB: cix is set above where RTS/CTS is enabled */ BUG_ON(cix == 0xff); ctsrate = rt->info[cix].rateCode | - (bf->bf_shpreamble ? rt->info[cix].shortPreamble : 0); + (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0); /* * Setup HAL rate series */ - memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); + memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); for (i = 0; i < 4; i++) { if (!bf->bf_rcs[i].tries) @@ -846,7 +738,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) rix = bf->bf_rcs[i].rix; series[i].Rate = rt->info[rix].rateCode | - (bf->bf_shpreamble ? rt->info[rix].shortPreamble : 0); + (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0); series[i].Tries = bf->bf_rcs[i].tries; @@ -862,7 +754,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) sc, rix, bf, (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0, (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG), - bf->bf_shpreamble); + bf_isshpreamble(bf)); if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) && (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) { @@ -875,7 +767,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) */ series[i].ChSel = sc->sc_tx_chainmask; } else { - if (bf->bf_ht) + if (bf_isht(bf)) series[i].ChSel = ath_chainmask_sel_logic(sc, an); else @@ -908,7 +800,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) * use the precalculated ACK durations. */ if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */ - ctsduration += bf->bf_shpreamble ? + ctsduration += bf_isshpreamble(bf) ? rt->info[cix].spAckDuration : rt->info[cix].lpAckDuration; } @@ -916,7 +808,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) ctsduration += series[0].PktDuration; if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */ - ctsduration += bf->bf_shpreamble ? + ctsduration += bf_isshpreamble(bf) ? rt->info[rix].spAckDuration : rt->info[rix].lpAckDuration; } @@ -925,17 +817,17 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) * Disable multi-rate retry when using RTS/CTS by clearing * series 1, 2 and 3. */ - memzero(&series[1], sizeof(struct ath9k_11n_rate_series) * 3); + memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3); } /* * set dur_update_en for l-sig computation except for PS-Poll frames */ ath9k_hw_set11n_ratescenario(ah, ds, lastds, - !bf->bf_ispspoll, - ctsrate, - ctsduration, - series, 4, flags); + !bf_ispspoll(bf), + ctsrate, + ctsduration, + series, 4, flags); if (sc->sc_config.ath_aggr_prot && flags) ath9k_hw_set11n_burstduration(ah, ds, 8192); } @@ -958,7 +850,7 @@ static int ath_tx_send_normal(struct ath_softc *sc, BUG_ON(list_empty(bf_head)); bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_isampdu = 0; /* regular HT frame */ + bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */ skb = (struct sk_buff *)bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); @@ -998,7 +890,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) while (!list_empty(&tid->buf_q)) { bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - ASSERT(!bf->bf_isretried); + ASSERT(!bf_isretried(bf)); list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); ath_tx_send_normal(sc, txq, tid, &bf_head); } @@ -1025,7 +917,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, int isaggr, txfail, txpending, sendbar = 0, needreset = 0; int isnodegone = (an->an_flags & ATH_NODE_CLEAN); - isaggr = bf->bf_isaggr; + isaggr = bf_isaggr(bf); if (isaggr) { if (txok) { if (ATH_DS_TX_BA(ds)) { @@ -1038,7 +930,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); } else { - memzero(ba, WME_BA_BMP_SIZE >> 3); + memset(ba, 0, WME_BA_BMP_SIZE >> 3); /* * AR5416 can become deaf/mute when BA @@ -1047,11 +939,11 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, * when perform internal reset in this routine. * Only enable reset in STA mode for now. */ - if (sc->sc_opmode == ATH9K_M_STA) + if (sc->sc_ah->ah_opmode == ATH9K_M_STA) needreset = 1; } } else { - memzero(ba, WME_BA_BMP_SIZE >> 3); + memset(ba, 0, WME_BA_BMP_SIZE >> 3); } } @@ -1075,7 +967,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, ath_tx_set_retry(sc, bf); txpending = 1; } else { - bf->bf_isxretried = 1; + bf->bf_state.bf_type |= BUF_XRETRY; txfail = 1; sendbar = 1; } @@ -1175,11 +1067,8 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, tbf->bf_lastfrm->bf_desc); /* copy the DMA context */ - copy_dma_mem_context( - get_dma_mem_context(tbf, - bf_dmacontext), - get_dma_mem_context(bf_last, - bf_dmacontext)); + tbf->bf_dmacontext = + bf_last->bf_dmacontext; } list_add_tail(&tbf->list, &bf_head); } else { @@ -1188,7 +1077,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, * software retry */ ath9k_hw_cleartxdesc(sc->sc_ah, - bf->bf_lastfrm->bf_desc); + bf->bf_lastfrm->bf_desc); } /* @@ -1242,7 +1131,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, } if (needreset) - ath_internal_reset(sc); + ath_reset(sc, false); return; } @@ -1331,7 +1220,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) txq->axq_depth--; - if (bf->bf_isaggr) + if (bf_isaggr(bf)) txq->axq_aggr_depth--; txok = (ds->ds_txstat.ts_status == 0); @@ -1345,14 +1234,14 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) spin_unlock_bh(&sc->sc_txbuflock); } - if (!bf->bf_isampdu) { + if (!bf_isampdu(bf)) { /* * This frame is sent out as a single frame. * Use hardware retry status for this frame. */ bf->bf_retries = ds->ds_txstat.ts_longretry; if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) - bf->bf_isxretried = 1; + bf->bf_state.bf_type |= BUF_XRETRY; nbad = 0; } else { nbad = ath_tx_num_badfrms(sc, bf, txok); @@ -1368,7 +1257,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) if (ds->ds_txstat.ts_status == 0) nacked++; - if (bf->bf_isdata) { + if (bf_isdata(bf)) { if (isrifs) tmp_ds = bf->bf_rifslast->bf_desc; else @@ -1384,7 +1273,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) /* * Complete this transmit unit */ - if (bf->bf_isampdu) + if (bf_isampdu(bf)) ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, txok); else ath_tx_complete_buf(sc, bf, &bf_head, txok, 0); @@ -1406,7 +1295,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) /* * schedule any pending packets if aggregation is enabled */ - if (sc->sc_txaggr) + if (sc->sc_flags & SC_OP_TXAGGR) ath_txq_schedule(sc, txq); spin_unlock_bh(&txq->axq_lock); } @@ -1430,10 +1319,9 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) struct ath_hal *ah = sc->sc_ah; int i; int npend = 0; - enum ath9k_ht_macmode ht_macmode = ath_cwm_macmode(sc); /* XXX return value */ - if (!sc->sc_invalid) { + if (!(sc->sc_flags & SC_OP_INVALID)) { for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { ath_tx_stopdma(sc, &sc->sc_txq[i]); @@ -1454,10 +1342,11 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) "%s: Unable to stop TxDMA. Reset HAL!\n", __func__); spin_lock_bh(&sc->sc_resetlock); - if (!ath9k_hw_reset(ah, sc->sc_opmode, - &sc->sc_curchan, ht_macmode, - sc->sc_tx_chainmask, sc->sc_rx_chainmask, - sc->sc_ht_extprotspacing, true, &status)) { + if (!ath9k_hw_reset(ah, + sc->sc_ah->ah_curchan, + sc->sc_ht_info.tx_chan_width, + sc->sc_tx_chainmask, sc->sc_rx_chainmask, + sc->sc_ht_extprotspacing, true, &status)) { DPRINTF(sc, ATH_DBG_FATAL, "%s: unable to reset hardware; hal status %u\n", @@ -1481,7 +1370,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, { int index, cindex; - if (bf->bf_isretried) + if (bf_isretried(bf)) return; index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); @@ -1516,7 +1405,7 @@ static int ath_tx_send_ampdu(struct ath_softc *sc, BUG_ON(list_empty(bf_head)); bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_isampdu = 1; + bf->bf_state.bf_type |= BUF_AMPDU; bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */ bf->bf_tidno = txctl->tidno; @@ -1860,7 +1749,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, if (bf->bf_nframes == 1) { ASSERT(bf->bf_lastfrm == bf_last); - bf->bf_isaggr = 0; + bf->bf_state.bf_type &= ~BUF_AGGR; /* * clear aggr bits for every descriptor * XXX TODO: is there a way to optimize it? @@ -1877,7 +1766,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, /* * setup first desc with rate and aggr info */ - bf->bf_isaggr = 1; + 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); @@ -1925,7 +1814,7 @@ static void ath_tid_drain(struct ath_softc *sc, list_cut_position(&bf_head, &tid->buf_q, &bf->bf_lastfrm->list); /* update baw for software retried frame */ - if (bf->bf_isretried) + if (bf_isretried(bf)) ath_tx_update_baw(sc, tid, bf->bf_seqno); /* @@ -1990,13 +1879,18 @@ static int ath_tx_start_dma(struct ath_softc *sc, struct list_head bf_head; struct ath_desc *ds; struct ath_hal *ah = sc->sc_ah; - struct ath_txq *txq = &sc->sc_txq[txctl->qnum]; + struct ath_txq *txq; struct ath_tx_info_priv *tx_info_priv; struct ath_rc_series *rcs; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); __le16 fc = hdr->frame_control; + if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) + txq = sc->sc_cabq; + else + txq = &sc->sc_txq[txctl->qnum]; + /* For each sglist entry, allocate an ath_buf for DMA */ INIT_LIST_HEAD(&bf_head); spin_lock_bh(&sc->sc_txbuflock); @@ -2014,11 +1908,21 @@ static int ath_tx_start_dma(struct ath_softc *sc, /* set up this buffer */ ATH_TXBUF_RESET(bf); bf->bf_frmlen = txctl->frmlen; - bf->bf_isdata = ieee80211_is_data(fc); - bf->bf_isbar = ieee80211_is_back_req(fc); - bf->bf_ispspoll = ieee80211_is_pspoll(fc); + + ieee80211_is_data(fc) ? + (bf->bf_state.bf_type |= BUF_DATA) : + (bf->bf_state.bf_type &= ~BUF_DATA); + ieee80211_is_back_req(fc) ? + (bf->bf_state.bf_type |= BUF_BAR) : + (bf->bf_state.bf_type &= ~BUF_BAR); + ieee80211_is_pspoll(fc) ? + (bf->bf_state.bf_type |= BUF_PSPOLL) : + (bf->bf_state.bf_type &= ~BUF_PSPOLL); + (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? + (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : + (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); + bf->bf_flags = txctl->flags; - bf->bf_shpreamble = sc->sc_flags & ATH_PREAMBLE_SHORT; bf->bf_keytype = txctl->keytype; tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; rcs = tx_info_priv->rcs; @@ -2038,8 +1942,7 @@ static int ath_tx_start_dma(struct ath_softc *sc, /* * Save the DMA context in the first ath_buf */ - copy_dma_mem_context(get_dma_mem_context(bf, bf_dmacontext), - get_dma_mem_context(txctl, dmacontext)); + bf->bf_dmacontext = txctl->dmacontext; /* * Formulate first tx descriptor with tx controls. @@ -2060,11 +1963,13 @@ static int ath_tx_start_dma(struct ath_softc *sc, ds); /* first descriptor */ bf->bf_lastfrm = bf; - bf->bf_ht = txctl->ht; + (txctl->ht) ? + (bf->bf_state.bf_type |= BUF_HT) : + (bf->bf_state.bf_type &= ~BUF_HT); spin_lock_bh(&txq->axq_lock); - if (txctl->ht && sc->sc_txaggr) { + if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno); if (ath_aggr_query(sc, an, txctl->tidno)) { /* @@ -2090,27 +1995,7 @@ static int ath_tx_start_dma(struct ath_softc *sc, bf->bf_tidno = txctl->tidno; } - if (is_multicast_ether_addr(hdr->addr1)) { - struct ath_vap *avp = sc->sc_vaps[txctl->if_id]; - - /* - * When servicing one or more stations in power-save - * mode (or) if there is some mcast data waiting on - * mcast queue (to prevent out of order delivery of - * mcast,bcast packets) multicast frames must be - * buffered until after the beacon. We use the private - * mcast queue for that. - */ - /* XXX? more bit in 802.11 frame header */ - spin_lock_bh(&avp->av_mcastq.axq_lock); - if (txctl->ps || avp->av_mcastq.axq_depth) - ath_tx_mcastqaddbuf(sc, - &avp->av_mcastq, &bf_head); - else - ath_tx_txqaddbuf(sc, txq, &bf_head); - spin_unlock_bh(&avp->av_mcastq.axq_lock); - } else - ath_tx_txqaddbuf(sc, txq, &bf_head); + ath_tx_txqaddbuf(sc, txq, &bf_head); } spin_unlock_bh(&txq->axq_lock); return 0; @@ -2118,30 +2003,31 @@ static int ath_tx_start_dma(struct ath_softc *sc, static void xmit_map_sg(struct ath_softc *sc, struct sk_buff *skb, - dma_addr_t *pa, struct ath_tx_control *txctl) { struct ath_xmit_status tx_status; struct ath_atx_tid *tid; struct scatterlist sg; - *pa = pci_map_single(sc->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + txctl->dmacontext = pci_map_single(sc->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); /* setup S/G list */ memset(&sg, 0, sizeof(struct scatterlist)); - sg_dma_address(&sg) = *pa; + sg_dma_address(&sg) = txctl->dmacontext; sg_dma_len(&sg) = skb->len; if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) { /* * We have to do drop frame here. */ - pci_unmap_single(sc->pdev, *pa, skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(sc->pdev, txctl->dmacontext, + skb->len, PCI_DMA_TODEVICE); tx_status.retries = 0; tx_status.flags = ATH_TX_ERROR; - if (txctl->ht && sc->sc_txaggr) { + if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) { /* Reclaim the seqno. */ tid = ATH_AN_2_TID((struct ath_node *) txctl->an, txctl->tidno); @@ -2162,7 +2048,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) /* Setup tx descriptors */ error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf, - "tx", nbufs * ATH_FRAG_PER_MSDU, ATH_TXDESC); + "tx", nbufs, 1); if (error != 0) { DPRINTF(sc, ATH_DBG_FATAL, "%s: failed to allocate tx descriptors: %d\n", @@ -2212,7 +2098,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) struct ath9k_tx_queue_info qi; int qnum; - memzero(&qi, sizeof(qi)); + memset(&qi, 0, sizeof(qi)); qi.tqi_subtype = subtype; qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; @@ -2403,6 +2289,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) struct ath_tx_control txctl; int error = 0; + memset(&txctl, 0, sizeof(struct ath_tx_control)); error = ath_tx_prepare(sc, skb, &txctl); if (error == 0) /* @@ -2410,9 +2297,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) * ath_tx_start_dma() will be called either synchronously * or asynchrounsly once DMA is complete. */ - xmit_map_sg(sc, skb, - get_dma_mem_context(&txctl, dmacontext), - &txctl); + xmit_map_sg(sc, skb, &txctl); else ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); @@ -2424,8 +2309,7 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb) void ath_tx_tasklet(struct ath_softc *sc) { - u64 tsf = ath9k_hw_gettsf64(sc->sc_ah); - int i, nacked = 0; + int i; u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); @@ -2435,10 +2319,8 @@ void ath_tx_tasklet(struct ath_softc *sc) */ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) - nacked += ath_tx_processq(sc, &sc->sc_txq[i]); + ath_tx_processq(sc, &sc->sc_txq[i]); } - if (nacked) - sc->sc_lastrx = tsf; } void ath_tx_draintxq(struct ath_softc *sc, @@ -2486,14 +2368,14 @@ void ath_tx_draintxq(struct ath_softc *sc, spin_unlock_bh(&txq->axq_lock); - if (bf->bf_isampdu) + if (bf_isampdu(bf)) ath_tx_complete_aggr_rifs(sc, txq, bf, &bf_head, 0); else ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); } /* flush any pending frames if aggregation is enabled */ - if (sc->sc_txaggr) { + if (sc->sc_flags & SC_OP_TXAGGR) { if (!retry_tx) { spin_lock_bh(&txq->axq_lock); ath_txq_drain_pending_buffers(sc, txq, @@ -2509,7 +2391,7 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx) { /* stop beacon queue. The beacon will be freed when * we go to INIT state */ - if (!sc->sc_invalid) { + if (!(sc->sc_flags & SC_OP_INVALID)) { (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq); DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__, ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq)); @@ -2536,7 +2418,7 @@ enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc, struct ath_atx_tid *txtid; DECLARE_MAC_BUF(mac); - if (!sc->sc_txaggr) + if (!(sc->sc_flags & SC_OP_TXAGGR)) return AGGR_NOT_REQUIRED; /* ADDBA exchange must be completed before sending aggregates */ @@ -2583,7 +2465,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, return -1; } - if (sc->sc_txaggr) { + if (sc->sc_flags & SC_OP_TXAGGR) { txtid = ATH_AN_2_TID(an, tid); txtid->addba_exchangeinprogress = 1; ath_tx_pause_tid(sc, txtid); @@ -2647,7 +2529,7 @@ void ath_tx_aggr_teardown(struct ath_softc *sc, spin_lock_bh(&txq->axq_lock); while (!list_empty(&txtid->buf_q)) { bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); - if (!bf->bf_isretried) { + if (!bf_isretried(bf)) { /* * NB: it's based on the assumption that * software retried frame will always stay @@ -2743,7 +2625,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) { - if (sc->sc_txaggr) { + if (sc->sc_flags & SC_OP_TXAGGR) { struct ath_atx_tid *tid; struct ath_atx_ac *ac; int tidno, acno; @@ -2855,7 +2737,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) { - if (sc->sc_txaggr) { + if (sc->sc_flags & SC_OP_TXAGGR) { struct ath_atx_tid *tid; int tidno, i; @@ -2869,3 +2751,57 @@ void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an) } } } + +void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb) +{ + int hdrlen, padsize; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ath_tx_control txctl; + + /* + * 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) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + sc->seq_no += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(sc->seq_no); + } + + /* Add the padding after the header if this is not already done */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + if (hdrlen & 3) { + padsize = hdrlen % 4; + if (skb_headroom(skb) < padsize) { + DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding " + "failed\n", __func__); + dev_kfree_skb_any(skb); + return; + } + skb_push(skb, padsize); + memmove(skb->data, skb->data + padsize, hdrlen); + } + + DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n", + __func__, + skb); + + memset(&txctl, 0, sizeof(struct ath_tx_control)); + txctl.flags = ATH9K_TXDESC_CAB; + if (ath_tx_prepare(sc, skb, &txctl) == 0) { + /* + * Start DMA mapping. + * ath_tx_start_dma() will be called either synchronously + * or asynchrounsly once DMA is complete. + */ + xmit_map_sg(sc, skb, &txctl); + } else { + ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE); + DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__); + dev_kfree_skb_any(skb); + } +} + |