summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c2
-rw-r--r--drivers/net/wireless/ath/ath.h5
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c279
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h26
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c655
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c28
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c68
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c37
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h12
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h22
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h45
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c39
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c102
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c30
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h2
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h10
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c7
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h16
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h6
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c30
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.h5
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h6
39 files changed, 727 insertions, 922 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index a93dc18a45c3..5dbb5361fd51 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -54,8 +54,6 @@ MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless");
MODULE_FIRMWARE("ar9170.fw");
-MODULE_FIRMWARE("ar9170-1.fw");
-MODULE_FIRMWARE("ar9170-2.fw");
enum ar9170_requirements {
AR9170_REQ_FW1_ONLY = 1,
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index dd236c3b52f6..cee0191704f5 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -35,7 +35,6 @@ static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct ath_ani {
bool caldone;
- int16_t noise_floor;
unsigned int longcal_timer;
unsigned int shortcal_timer;
unsigned int resetcal_timer;
@@ -103,14 +102,12 @@ enum ath_cipher {
* @read: Register read
* @write: Register write
* @enable_write_buffer: Enable multiple register writes
- * @disable_write_buffer: Disable multiple register writes
- * @write_flush: Flush buffered register writes
+ * @write_flush: flush buffered register writes and disable buffering
*/
struct ath_ops {
unsigned int (*read)(void *, u32 reg_offset);
void (*write)(void *, u32 val, u32 reg_offset);
void (*enable_write_buffer)(void *);
- void (*disable_write_buffer)(void *);
void (*write_flush) (void *);
};
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 94cc3354f3a6..dad726585637 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -52,6 +52,7 @@
#include <linux/ethtool.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/etherdevice.h>
#include <net/ieee80211_radiotap.h>
@@ -509,8 +510,71 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
}
}
+struct ath_vif_iter_data {
+ const u8 *hw_macaddr;
+ u8 mask[ETH_ALEN];
+ u8 active_mac[ETH_ALEN]; /* first active MAC */
+ bool need_set_hw_addr;
+ bool found_active;
+ bool any_assoc;
+};
+
+static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct ath_vif_iter_data *iter_data = data;
+ int i;
+
+ if (iter_data->hw_macaddr)
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &=
+ ~(iter_data->hw_macaddr[i] ^ mac[i]);
+
+ if (!iter_data->found_active) {
+ iter_data->found_active = true;
+ memcpy(iter_data->active_mac, mac, ETH_ALEN);
+ }
+
+ if (iter_data->need_set_hw_addr && iter_data->hw_macaddr)
+ if (compare_ether_addr(iter_data->hw_macaddr, mac) == 0)
+ iter_data->need_set_hw_addr = false;
+
+ if (!iter_data->any_assoc) {
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
+ if (avf->assoc)
+ iter_data->any_assoc = true;
+ }
+}
+
+void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif)
+{
+ struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_vif_iter_data iter_data;
+
+ /*
+ * Use the hardware MAC address as reference, the hardware uses it
+ * together with the BSSID mask when matching addresses.
+ */
+ iter_data.hw_macaddr = common->macaddr;
+ memset(&iter_data.mask, 0xff, ETH_ALEN);
+ iter_data.found_active = false;
+ iter_data.need_set_hw_addr = true;
+
+ if (vif)
+ ath_vif_iter(&iter_data, vif->addr, vif);
+
+ /* Get list of all active MAC addresses */
+ ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+ &iter_data);
+ memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
+
+ if (iter_data.need_set_hw_addr && iter_data.found_active)
+ ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
+
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+}
+
static void
-ath5k_mode_setup(struct ath5k_softc *sc)
+ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
{
struct ath5k_hw *ah = sc->ah;
u32 rfilt;
@@ -520,7 +584,7 @@ ath5k_mode_setup(struct ath5k_softc *sc)
ath5k_hw_set_rx_filter(ah, rfilt);
if (ath5k_hw_hasbssidmask(ah))
- ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
+ ath5k_update_bssid_mask(sc, vif);
/* configure operational mode */
ath5k_hw_set_opmode(ah, sc->opmode);
@@ -698,13 +762,13 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
flags |= AR5K_TXDESC_RTSENA;
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
- sc->vif, pktlen, info));
+ info->control.vif, pktlen, info));
}
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= AR5K_TXDESC_CTSENA;
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
- sc->vif, pktlen, info));
+ info->control.vif, pktlen, info));
}
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), padsize,
@@ -806,10 +870,13 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
list_add_tail(&bf->list, &sc->txbuf);
}
- /* beacon buffer */
- bf->desc = ds;
- bf->daddr = da;
- sc->bbuf = bf;
+ /* beacon buffers */
+ INIT_LIST_HEAD(&sc->bcbuf);
+ for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->bcbuf);
+ }
return 0;
err_free:
@@ -824,11 +891,12 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
{
struct ath5k_buf *bf;
- ath5k_txbuf_free_skb(sc, sc->bbuf);
list_for_each_entry(bf, &sc->txbuf, list)
ath5k_txbuf_free_skb(sc, bf);
list_for_each_entry(bf, &sc->rxbuf, list)
ath5k_rxbuf_free_skb(sc, bf);
+ list_for_each_entry(bf, &sc->bcbuf, list)
+ ath5k_txbuf_free_skb(sc, bf);
/* Free memory associated with all descriptors */
pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
@@ -837,7 +905,6 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
kfree(sc->bufptr);
sc->bufptr = NULL;
- sc->bbuf = NULL;
}
@@ -1083,7 +1150,7 @@ ath5k_rx_start(struct ath5k_softc *sc)
spin_unlock_bh(&sc->rxbuflock);
ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
- ath5k_mode_setup(sc); /* set filters, etc. */
+ ath5k_mode_setup(sc, NULL); /* set filters, etc. */
ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
return 0;
@@ -1366,6 +1433,7 @@ static bool
ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
{
sc->stats.rx_all_count++;
+ sc->stats.rx_bytes_count += rs->rs_datalen;
if (unlikely(rs->rs_status)) {
if (rs->rs_status & AR5K_RXERR_CRC)
@@ -1544,6 +1612,7 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
int i;
sc->stats.tx_all_count++;
+ sc->stats.tx_bytes_count += skb->len;
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
@@ -1642,7 +1711,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
}
}
spin_unlock(&txq->lock);
- if (txq->txq_len < ATH5K_TXQ_LEN_LOW)
+ if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4)
ieee80211_wake_queue(sc->hw, txq->qnum);
}
@@ -1750,6 +1819,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
struct ath5k_softc *sc = hw->priv;
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
struct sk_buff *skb;
if (WARN_ON(!vif)) {
@@ -1766,11 +1836,11 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ath5k_debug_dump_skb(sc, skb, "BC ", 1);
- ath5k_txbuf_free_skb(sc, sc->bbuf);
- sc->bbuf->skb = skb;
- ret = ath5k_beacon_setup(sc, sc->bbuf);
+ ath5k_txbuf_free_skb(sc, avf->bbuf);
+ avf->bbuf->skb = skb;
+ ret = ath5k_beacon_setup(sc, avf->bbuf);
if (ret)
- sc->bbuf->skb = NULL;
+ avf->bbuf->skb = NULL;
out:
return ret;
}
@@ -1786,16 +1856,14 @@ out:
static void
ath5k_beacon_send(struct ath5k_softc *sc)
{
- struct ath5k_buf *bf = sc->bbuf;
struct ath5k_hw *ah = sc->ah;
+ struct ieee80211_vif *vif;
+ struct ath5k_vif *avf;
+ struct ath5k_buf *bf;
struct sk_buff *skb;
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
- if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION)) {
- ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
- return;
- }
/*
* Check if the previous beacon has gone out. If
* not, don't don't try to post another: skip this
@@ -1824,6 +1892,28 @@ ath5k_beacon_send(struct ath5k_softc *sc)
sc->bmisscount = 0;
}
+ if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+ int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval;
+ vif = sc->bslot[(slot + 1) % ATH_BCBUF];
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ "tsf %llx tsftu %x intval %u slot %u vif %p\n",
+ (unsigned long long)tsf, tsftu, sc->bintval, slot, vif);
+ } else /* only one interface */
+ vif = sc->bslot[0];
+
+ if (!vif)
+ return;
+
+ avf = (void *)vif->drv_priv;
+ bf = avf->bbuf;
+ if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+ sc->opmode == NL80211_IFTYPE_MONITOR)) {
+ ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+ return;
+ }
+
/*
* Stop any current dma and put the new frame on the queue.
* This should never fail since we check above that no frames
@@ -1836,17 +1926,17 @@ ath5k_beacon_send(struct ath5k_softc *sc)
/* refresh the beacon for AP mode */
if (sc->opmode == NL80211_IFTYPE_AP)
- ath5k_beacon_update(sc->hw, sc->vif);
+ ath5k_beacon_update(sc->hw, vif);
ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
ath5k_hw_start_tx_dma(ah, sc->bhalq);
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
- skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
while (skb) {
ath5k_tx_queue(sc->hw, skb, sc->cabq);
- skb = ieee80211_get_buffered_bc(sc->hw, sc->vif);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
}
sc->bsent++;
@@ -1876,6 +1966,12 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
u64 hw_tsf;
intval = sc->bintval & AR5K_BEACON_PERIOD;
+ if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+ intval);
+ }
if (WARN_ON(!intval))
return;
@@ -2323,6 +2419,10 @@ ath5k_init(struct ath5k_softc *sc)
ath_hw_keyreset(common, (u16) i);
ath5k_hw_set_ack_bitrate_high(ah, true);
+
+ for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
+ sc->bslot[i] = NULL;
+
ret = 0;
done:
mmiowb();
@@ -2382,7 +2482,6 @@ ath5k_stop_hw(struct ath5k_softc *sc)
ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
"putting device to sleep\n");
}
- ath5k_txbuf_free_skb(sc, sc->bbuf);
mmiowb();
mutex_unlock(&sc->lock);
@@ -2587,9 +2686,9 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
}
SET_IEEE80211_PERM_ADDR(hw, mac);
+ memcpy(&sc->lladdr, mac, ETH_ALEN);
/* All MAC address bits matter for ACKs */
- memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN);
- ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+ ath5k_update_bssid_mask(sc, NULL);
regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
@@ -2687,31 +2786,91 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
{
struct ath5k_softc *sc = hw->priv;
int ret;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
mutex_lock(&sc->lock);
- if (sc->vif) {
- ret = 0;
+
+ if ((vif->type == NL80211_IFTYPE_AP ||
+ vif->type == NL80211_IFTYPE_ADHOC)
+ && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
+ ret = -ELNRNG;
goto end;
}
- sc->vif = vif;
+ /* Don't allow other interfaces if one ad-hoc is configured.
+ * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+ * We would need to operate the HW in ad-hoc mode to allow TSF updates
+ * for the IBSS, but this breaks with additional AP or STA interfaces
+ * at the moment. */
+ if (sc->num_adhoc_vifs ||
+ (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+ ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+ }
switch (vif->type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
- sc->opmode = vif->type;
+ avf->opmode = vif->type;
break;
default:
ret = -EOPNOTSUPP;
goto end;
}
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode);
+ sc->nvifs++;
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
+ /* Assign the vap/adhoc to a beacon xmit slot. */
+ if ((avf->opmode == NL80211_IFTYPE_AP) ||
+ (avf->opmode == NL80211_IFTYPE_ADHOC)) {
+ int slot;
+
+ WARN_ON(list_empty(&sc->bcbuf));
+ avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
+ list);
+ list_del(&avf->bbuf->list);
+
+ avf->bslot = 0;
+ for (slot = 0; slot < ATH_BCBUF; slot++) {
+ if (!sc->bslot[slot]) {
+ avf->bslot = slot;
+ break;
+ }
+ }
+ BUG_ON(sc->bslot[avf->bslot] != NULL);
+ sc->bslot[avf->bslot] = vif;
+ if (avf->opmode == NL80211_IFTYPE_AP)
+ sc->num_ap_vifs++;
+ else
+ sc->num_adhoc_vifs++;
+ }
+
+ /* Set combined mode - when APs are configured, operate in AP mode.
+ * Otherwise use the mode of the new interface. This can currently
+ * only deal with combinations of APs and STAs. Only one ad-hoc
+ * interfaces is allowed above.
+ */
+ if (sc->num_ap_vifs)
+ sc->opmode = NL80211_IFTYPE_AP;
+ else
+ sc->opmode = vif->type;
+
+ ath5k_hw_set_opmode(ah, sc->opmode);
+
+ /* Any MAC address is fine, all others are included through the
+ * filter.
+ */
+ memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
ath5k_hw_set_lladdr(sc->ah, vif->addr);
- ath5k_mode_setup(sc);
+
+ memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
+
+ ath5k_mode_setup(sc, vif);
ret = 0;
end:
@@ -2724,15 +2883,29 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath5k_softc *sc = hw->priv;
- u8 mac[ETH_ALEN] = {};
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
+ unsigned int i;
mutex_lock(&sc->lock);
- if (sc->vif != vif)
- goto end;
+ sc->nvifs--;
+
+ if (avf->bbuf) {
+ ath5k_txbuf_free_skb(sc, avf->bbuf);
+ list_add_tail(&avf->bbuf->list, &sc->bcbuf);
+ for (i = 0; i < ATH_BCBUF; i++) {
+ if (sc->bslot[i] == vif) {
+ sc->bslot[i] = NULL;
+ break;
+ }
+ }
+ avf->bbuf = NULL;
+ }
+ if (avf->opmode == NL80211_IFTYPE_AP)
+ sc->num_ap_vifs--;
+ else if (avf->opmode == NL80211_IFTYPE_ADHOC)
+ sc->num_adhoc_vifs--;
- ath5k_hw_set_lladdr(sc->ah, mac);
- sc->vif = NULL;
-end:
+ ath5k_update_bssid_mask(sc, NULL);
mutex_unlock(&sc->lock);
}
@@ -2815,6 +2988,19 @@ static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
return ((u64)(mfilt[1]) << 32) | mfilt[0];
}
+static bool ath_any_vif_assoc(struct ath5k_softc *sc)
+{
+ struct ath_vif_iter_data iter_data;
+ iter_data.hw_macaddr = NULL;
+ iter_data.any_assoc = false;
+ iter_data.need_set_hw_addr = false;
+ iter_data.found_active = true;
+
+ ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+ &iter_data);
+ return iter_data.any_assoc;
+}
+
#define SUPPORTED_FIF_FLAGS \
FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
@@ -2885,7 +3071,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
/* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
* and probes for any BSSID */
- if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
+ if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
rfilt |= AR5K_RX_FILTER_BEACON;
/* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
@@ -3070,14 +3256,13 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u32 changes)
{
+ struct ath5k_vif *avf = (void *)vif->drv_priv;
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
unsigned long flags;
mutex_lock(&sc->lock);
- if (WARN_ON(sc->vif != vif))
- goto unlock;
if (changes & BSS_CHANGED_BSSID) {
/* Cache for later use during resets */
@@ -3091,7 +3276,12 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
sc->bintval = bss_conf->beacon_int;
if (changes & BSS_CHANGED_ASSOC) {
- sc->assoc = bss_conf->assoc;
+ avf->assoc = bss_conf->assoc;
+ if (bss_conf->assoc)
+ sc->assoc = bss_conf->assoc;
+ else
+ sc->assoc = ath_any_vif_assoc(sc);
+
if (sc->opmode == NL80211_IFTYPE_STATION)
set_beacon_filter(hw, sc->assoc);
ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
@@ -3119,7 +3309,6 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
BSS_CHANGED_BEACON_INT))
ath5k_beacon_config(sc);
- unlock:
mutex_unlock(&sc->lock);
}
@@ -3394,6 +3583,8 @@ ath5k_pci_probe(struct pci_dev *pdev,
hw->max_rate_tries = 11;
}
+ hw->vif_data_size = sizeof(struct ath5k_vif);
+
/* Finish private driver data initialization */
ret = ath5k_attach(pdev, hw);
if (ret)
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 7f9d0d3018e8..9a79773cdc2a 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -58,8 +58,7 @@
#define ATH_RXBUF 40 /* number of RX buffers */
#define ATH_TXBUF 200 /* number of TX buffers */
-#define ATH_BCBUF 1 /* number of beacon buffers */
-
+#define ATH_BCBUF 4 /* number of beacon buffers */
#define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */
#define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */
@@ -122,6 +121,13 @@ struct ath5k_statistics {
/* frame errors */
unsigned int rx_all_count; /* all RX frames, including errors */
unsigned int tx_all_count; /* all TX frames, including errors */
+ unsigned int rx_bytes_count; /* all RX bytes, including errored pks
+ * and the MAC headers for each packet
+ */
+ unsigned int tx_bytes_count; /* all TX bytes, including errored pkts
+ * and the MAC headers and padding for
+ * each packet.
+ */
unsigned int rxerr_crc;
unsigned int rxerr_phy;
unsigned int rxerr_phy_code[32];
@@ -152,6 +158,14 @@ struct ath5k_statistics {
#define ATH_CHAN_MAX (14+14+14+252+20)
#endif
+struct ath5k_vif {
+ bool assoc; /* are we associated or not */
+ enum nl80211_iftype opmode;
+ int bslot;
+ struct ath5k_buf *bbuf; /* beacon buffer */
+ u8 lladdr[ETH_ALEN];
+};
+
/* Software Carrier, keeps track of the driver state
* associated with an instance of a device */
struct ath5k_softc {
@@ -188,10 +202,11 @@ struct ath5k_softc {
unsigned int curmode; /* current phy mode */
struct ieee80211_channel *curchan; /* current h/w channel */
- struct ieee80211_vif *vif;
+ u16 nvifs;
enum ath5k_int imask; /* interrupt mask copy */
+ u8 lladdr[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
unsigned int led_pin, /* GPIO pin for driving LED */
@@ -219,7 +234,10 @@ struct ath5k_softc {
spinlock_t block; /* protects beacon */
struct tasklet_struct beacontq; /* beacon intr tasklet */
- struct ath5k_buf *bbuf; /* beacon buffer */
+ struct list_head bcbuf; /* beacon buffer */
+ struct ieee80211_vif *bslot[ATH_BCBUF];
+ u16 num_ap_vifs;
+ u16 num_adhoc_vifs;
unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */
bintval, /* beacon interval in TU */
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 0f06e8490314..c2d549f871f9 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -587,6 +587,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
st->rxerr_jumbo*100/st->rx_all_count : 0);
len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
st->rx_all_count);
+ len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+ st->rx_bytes_count);
len += snprintf(buf+len, sizeof(buf)-len,
"\nTX\n---------------------\n");
@@ -604,6 +606,8 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
st->txerr_filt*100/st->tx_all_count : 0);
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
st->tx_all_count);
+ len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+ st->tx_bytes_count);
if (len > sizeof(buf))
len = sizeof(buf);
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 58912cd762d9..5b179d01f97d 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -167,7 +167,7 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
* ieee80211_duration() for a brief description of
* what rate we should choose to TX ACKs. */
tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
- sc->vif, 10, rate));
+ NULL, 10, rate));
ath5k_hw_reg_write(ah, tx_time, reg);
@@ -1060,7 +1060,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
* XXX: rethink this after new mode changes to
* mac80211 are integrated */
if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->vif != NULL)
+ ah->ah_sc->nvifs)
ath5k_hw_write_rate_duration(ah, mode);
/*
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 0496f965314f..f2a907b4acb8 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -103,31 +103,9 @@ static const struct ani_cck_level_entry cck_level_table[] = {
#define ATH9K_ANI_CCK_DEF_LEVEL \
2 /* default level - matches the INI settings */
-/* Private to ani.c */
-static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
-{
- ath9k_hw_private_ops(ah)->ani_lower_immunity(ah);
-}
-
-int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
- struct ath9k_channel *chan)
+static bool use_new_ani(struct ath_hw *ah)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
- if (ah->ani[i].c &&
- ah->ani[i].c->channel == chan->channel)
- return i;
- if (ah->ani[i].c == NULL) {
- ah->ani[i].c = chan;
- return i;
- }
- }
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANI,
- "No more channel states left. Using channel 0\n");
-
- return 0;
+ return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani;
}
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
@@ -140,82 +118,34 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah,
stats->beacons += REG_READ(ah, AR_BEACON_CNT);
}
-static void ath9k_ani_restart_old(struct ath_hw *ah)
+static void ath9k_ani_restart(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
+ u32 ofdm_base = 0, cck_base = 0;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
aniState->listenTime = 0;
- if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
- aniState->ofdmPhyErrBase = 0;
- ath_print(common, ATH_DBG_ANI,
- "OFDM Trigger is too high for hw counters\n");
- } else {
- aniState->ofdmPhyErrBase =
- AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
}
- if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
- aniState->cckPhyErrBase = 0;
- ath_print(common, ATH_DBG_ANI,
- "CCK Trigger is too high for hw counters\n");
- } else {
- aniState->cckPhyErrBase =
- AR_PHY_COUNTMAX - aniState->cckTrigHigh;
- }
- ath_print(common, ATH_DBG_ANI,
- "Writing ofdmbase=%u cckbase=%u\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
-
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- aniState->ofdmPhyErrCount = 0;
- aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_ani_restart_new(struct ath_hw *ah)
-{
- struct ar5416AniState *aniState;
- struct ath_common *common = ath9k_hw_common(ah);
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
- aniState->listenTime = 0;
-
- aniState->ofdmPhyErrBase = 0;
- aniState->cckPhyErrBase = 0;
ath_print(common, ATH_DBG_ANI,
- "Writing ofdmbase=%08x cckbase=%08x\n",
- aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
+ "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base);
ENABLE_REGWRITE_BUFFER(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -229,10 +159,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
@@ -301,10 +228,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
aniState->noiseImmunityLevel + 1)) {
@@ -336,7 +260,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah)
/* Adjust the OFDM Noise Immunity Level */
static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -381,14 +305,19 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
}
}
-static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_ofdm_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL)
ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1);
@@ -399,7 +328,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah)
*/
static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -438,14 +367,19 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
entry_cck->mrc_cck_on);
}
-static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah)
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_cck_err_trigger_old(ah);
+ return;
+ }
+
+ aniState = &ah->curchan->ani;
if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL)
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1);
@@ -456,7 +390,7 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
struct ar5416AniState *aniState;
int32_t rssi;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (ah->opmode == NL80211_IFTYPE_AP) {
if (aniState->firstepLevel > 0) {
@@ -508,11 +442,16 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah)
* only lower either OFDM or CCK errors per turn
* we lower the other one next time
*/
-static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah)
+static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
{
struct ar5416AniState *aniState;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
+
+ if (!use_new_ani(ah)) {
+ ath9k_hw_ani_lower_immunity_old(ah);
+ return;
+ }
/* lower OFDM noise immunity */
if (aniState->ofdmNoiseImmunityLevel > 0 &&
@@ -544,52 +483,20 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
if (conf_is_ht40(conf))
return clockrate * 2;
- return clockrate * 2;
+ return clockrate;
}
static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
{
- struct ar5416AniState *aniState;
- struct ath_common *common = ath9k_hw_common(ah);
- u32 txFrameCount, rxFrameCount, cycleCount;
- int32_t listenTime;
-
- txFrameCount = REG_READ(ah, AR_TFCNT);
- rxFrameCount = REG_READ(ah, AR_RFCNT);
- cycleCount = REG_READ(ah, AR_CCCNT);
-
- aniState = ah->curani;
- if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
- listenTime = 0;
- ah->stats.ast_ani_lzero++;
- ath_print(common, ATH_DBG_ANI,
- "1st call: aniState->cycleCount=%d\n",
- aniState->cycleCount);
- } else {
- int32_t ccdelta = cycleCount - aniState->cycleCount;
- int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
- int32_t tfdelta = txFrameCount - aniState->txFrameCount;
- int32_t clock_rate;
+ int32_t listen_time;
+ int32_t clock_rate;
- /*
- * convert HW counter values to ms using mode
- * specifix clock rate
- */
- clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;;
+ ath9k_hw_update_cycle_counters(ah);
+ clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
+ listen_time = ah->listen_time / clock_rate;
+ ah->listen_time = 0;
- listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate;
-
- ath_print(common, ATH_DBG_ANI,
- "cyclecount=%d, rfcount=%d, "
- "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n",
- ccdelta, rfdelta, tfdelta, listenTime, clock_rate);
- }
-
- aniState->cycleCount = cycleCount;
- aniState->txFrameCount = txFrameCount;
- aniState->rxFrameCount = rxFrameCount;
-
- return listenTime;
+ return listen_time;
}
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
@@ -597,16 +504,13 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
struct ar5416AniState *aniState;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
- int index;
if (!DO_ANI(ah))
return;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
+ aniState = &ah->curchan->ani;
- if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION
+ if (ah->opmode != NL80211_IFTYPE_STATION
&& ah->opmode != NL80211_IFTYPE_ADHOC) {
ath_print(common, ATH_DBG_ANI,
"Reset ANI state opmode %u\n", ah->opmode);
@@ -635,17 +539,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
ATH9K_RX_FILTER_PHYERR);
- if (ah->opmode == NL80211_IFTYPE_AP) {
- ah->curani->ofdmTrigHigh =
- ah->config.ofdm_trig_high;
- ah->curani->ofdmTrigLow =
- ah->config.ofdm_trig_low;
- ah->curani->cckTrigHigh =
- ah->config.cck_trig_high;
- ah->curani->cckTrigLow =
- ah->config.cck_trig_low;
- }
- ath9k_ani_restart_old(ah);
+ ath9k_ani_restart(ah);
return;
}
@@ -667,7 +561,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart_old(ah);
+ ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
@@ -675,7 +569,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/*
@@ -683,15 +576,18 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
* This routine should be called for every hardware reset and for
* every channel change.
*/
-static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath9k_channel *chan = ah->curchan;
struct ath_common *common = ath9k_hw_common(ah);
if (!DO_ANI(ah))
return;
+ if (!use_new_ani(ah))
+ return ath9k_ani_reset_old(ah, is_scanning);
+
BUG_ON(aniState == NULL);
ah->stats.ast_ani_reset++;
@@ -761,7 +657,7 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
* enable phy counters if hw supports or if not, enable phy
* interrupts (so we can count each one)
*/
- ath9k_ani_restart_new(ah);
+ ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
@@ -769,30 +665,30 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
-static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
- struct ath9k_channel *chan)
+static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
{
- struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
- int32_t listenTime;
- u32 phyCnt1, phyCnt2;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
+ u32 ofdm_base = 0;
+ u32 cck_base = 0;
u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ah->curani;
+ u32 phyCnt1, phyCnt2;
+ int32_t listenTime;
listenTime = ath9k_hw_ani_get_listen_time(ah);
if (listenTime < 0) {
ah->stats.ast_ani_lneg++;
- ath9k_ani_restart_old(ah);
+ ath9k_ani_restart(ah);
return;
}
+ if (!use_new_ani(ah)) {
+ ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high;
+ cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high;
+ }
+
aniState->listenTime += listenTime;
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
@@ -800,145 +696,54 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah,
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
+ if (phyCnt1 < ofdm_base) {
ath_print(common, ATH_DBG_ANI,
"phyCnt1 0x%x, resetting "
"counter value to 0x%x\n",
- phyCnt1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
+ phyCnt1, ofdm_base);
+ REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_1,
AR_PHY_ERR_OFDM_TIMING);
}
- if (phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt2 < cck_base) {
ath_print(common, ATH_DBG_ANI,
"phyCnt2 0x%x, resetting "
"counter value to 0x%x\n",
- phyCnt2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
+ phyCnt2, cck_base);
+ REG_WRITE(ah, AR_PHY_ERR_2, cck_base);
REG_WRITE(ah, AR_PHY_ERR_MASK_2,
AR_PHY_ERR_CCK_TIMING);
}
return;
}
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ofdmPhyErrCnt = phyCnt1 - ofdm_base;
ah->stats.ast_ani_ofdmerrs +=
ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ cckPhyErrCnt = phyCnt2 - cck_base;
ah->stats.ast_ani_cckerrs +=
cckPhyErrCnt - aniState->cckPhyErrCount;
aniState->cckPhyErrCount = cckPhyErrCnt;
- if (aniState->listenTime > 5 * ah->aniperiod) {
- if (aniState->ofdmPhyErrCount <= aniState->listenTime *
- aniState->ofdmTrigLow / 1000 &&
- aniState->cckPhyErrCount <= aniState->listenTime *
- aniState->cckTrigLow / 1000)
- ath9k_hw_ani_lower_immunity(ah);
- ath9k_ani_restart_old(ah);
- } else if (aniState->listenTime > ah->aniperiod) {
- if (aniState->ofdmPhyErrCount > aniState->listenTime *
- aniState->ofdmTrigHigh / 1000) {
- ath9k_hw_ani_ofdm_err_trigger_old(ah);
- ath9k_ani_restart_old(ah);
- } else if (aniState->cckPhyErrCount >
- aniState->listenTime * aniState->cckTrigHigh /
- 1000) {
- ath9k_hw_ani_cck_err_trigger_old(ah);
- ath9k_ani_restart_old(ah);
- }
- }
}
-static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
- struct ath9k_channel *chan)
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
- int32_t listenTime;
- u32 phyCnt1, phyCnt2;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
u32 ofdmPhyErrRate, cckPhyErrRate;
if (!DO_ANI(ah))
return;
- aniState = ah->curani;
+ aniState = &ah->curchan->ani;
if (WARN_ON(!aniState))
return;
- listenTime = ath9k_hw_ani_get_listen_time(ah);
- if (listenTime <= 0) {
- ah->stats.ast_ani_lneg++;
- /* restart ANI period if listenTime is invalid */
- ath_print(common, ATH_DBG_ANI,
- "listenTime=%d - on new ani monitor\n",
- listenTime);
- ath9k_ani_restart_new(ah);
- return;
- }
-
- aniState->listenTime += listenTime;
-
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
-
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
- ath_print(common, ATH_DBG_ANI,
- "phyCnt1 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < aniState->cckPhyErrBase) {
- ath_print(common, ATH_DBG_ANI,
- "phyCnt2 0x%x, resetting "
- "counter value to 0x%x\n",
- phyCnt2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
- return;
- }
-
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
-
- ath_print(common, ATH_DBG_ANI,
- "Errors: OFDM=0x%08x-0x%08x=%d "
- "CCK=0x%08x-0x%08x=%d\n",
- phyCnt1,
- aniState->ofdmPhyErrBase,
- ofdmPhyErrCnt,
- phyCnt2,
- aniState->cckPhyErrBase,
- cckPhyErrCnt);
+ ath9k_hw_ani_read_counters(ah);
ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
aniState->listenTime;
@@ -948,61 +753,34 @@ static void ath9k_hw_ani_monitor_new(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"listenTime=%d OFDM:%d errs=%d/s CCK:%d "
"errs=%d/s ofdm_turn=%d\n",
- listenTime, aniState->ofdmNoiseImmunityLevel,
+ aniState->listenTime,
+ aniState->ofdmNoiseImmunityLevel,
ofdmPhyErrRate, aniState->cckNoiseImmunityLevel,
cckPhyErrRate, aniState->ofdmsTurn);
if (aniState->listenTime > 5 * ah->aniperiod) {
- if (ofdmPhyErrRate <= aniState->ofdmTrigLow &&
- cckPhyErrRate <= aniState->cckTrigLow) {
- ath_print(common, ATH_DBG_ANI,
- "1. listenTime=%d OFDM:%d errs=%d/s(<%d) "
- "CCK:%d errs=%d/s(<%d) -> "
- "ath9k_hw_ani_lower_immunity()\n",
- aniState->listenTime,
- aniState->ofdmNoiseImmunityLevel,
- ofdmPhyErrRate,
- aniState->ofdmTrigLow,
- aniState->cckNoiseImmunityLevel,
- cckPhyErrRate,
- aniState->cckTrigLow);
+ if (ofdmPhyErrRate <= ah->config.ofdm_trig_low &&
+ cckPhyErrRate <= ah->config.cck_trig_low) {
ath9k_hw_ani_lower_immunity(ah);
aniState->ofdmsTurn = !aniState->ofdmsTurn;
}
- ath_print(common, ATH_DBG_ANI,
- "1 listenTime=%d ofdm=%d/s cck=%d/s - "
- "calling ath9k_ani_restart_new()\n",
- aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate);
- ath9k_ani_restart_new(ah);
+ ath9k_ani_restart(ah);
} else if (aniState->listenTime > ah->aniperiod) {
/* check to see if need to raise immunity */
- if (ofdmPhyErrRate > aniState->ofdmTrigHigh &&
- (cckPhyErrRate <= aniState->cckTrigHigh ||
+ if (ofdmPhyErrRate > ah->config.ofdm_trig_high &&
+ (cckPhyErrRate <= ah->config.cck_trig_high ||
aniState->ofdmsTurn)) {
- ath_print(common, ATH_DBG_ANI,
- "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> "
- "ath9k_hw_ani_ofdm_err_trigger_new()\n",
- aniState->listenTime,
- aniState->ofdmNoiseImmunityLevel,
- ofdmPhyErrRate,
- aniState->ofdmTrigHigh);
- ath9k_hw_ani_ofdm_err_trigger_new(ah);
- ath9k_ani_restart_new(ah);
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ ath9k_ani_restart(ah);
aniState->ofdmsTurn = false;
- } else if (cckPhyErrRate > aniState->cckTrigHigh) {
- ath_print(common, ATH_DBG_ANI,
- "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> "
- "ath9k_hw_ani_cck_err_trigger_new()\n",
- aniState->listenTime,
- aniState->cckNoiseImmunityLevel,
- cckPhyErrRate,
- aniState->cckTrigHigh);
- ath9k_hw_ani_cck_err_trigger_new(ah);
- ath9k_ani_restart_new(ah);
+ } else if (cckPhyErrRate > ah->config.cck_trig_high) {
+ ath9k_hw_ani_cck_err_trigger(ah);
+ ath9k_ani_restart(ah);
aniState->ofdmsTurn = true;
}
}
}
+EXPORT_SYMBOL(ath9k_hw_ani_monitor);
void ath9k_enable_mib_counters(struct ath_hw *ah)
{
@@ -1023,7 +801,6 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/* Freeze the MIB counters, get the stats and then clear them */
@@ -1041,107 +818,52 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
- u32 *rxc_pcnt,
- u32 *rxf_pcnt,
- u32 *txf_pcnt)
+void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
{
- struct ath_common *common = ath9k_hw_common(ah);
- static u32 cycles, rx_clear, rx_frame, tx_frame;
- u32 good = 1;
+ struct ath_cycle_counters cc;
+ bool clear;
- u32 rc = REG_READ(ah, AR_RCCNT);
- u32 rf = REG_READ(ah, AR_RFCNT);
- u32 tf = REG_READ(ah, AR_TFCNT);
- u32 cc = REG_READ(ah, AR_CCCNT);
+ memcpy(&cc, &ah->cc, sizeof(cc));
- if (cycles == 0 || cycles > cc) {
- ath_print(common, ATH_DBG_ANI,
- "cycle counter wrap. ExtBusy = 0\n");
- good = 0;
- } else {
- u32 cc_d = cc - cycles;
- u32 rc_d = rc - rx_clear;
- u32 rf_d = rf - rx_frame;
- u32 tf_d = tf - tx_frame;
-
- if (cc_d != 0) {
- *rxc_pcnt = rc_d * 100 / cc_d;
- *rxf_pcnt = rf_d * 100 / cc_d;
- *txf_pcnt = tf_d * 100 / cc_d;
- } else {
- good = 0;
- }
- }
+ /* freeze counters */
+ REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
- cycles = cc;
- rx_frame = rf;
- rx_clear = rc;
- tx_frame = tf;
+ ah->cc.cycles = REG_READ(ah, AR_CCCNT);
+ if (ah->cc.cycles < cc.cycles) {
+ clear = true;
+ goto skip;
+ }
- return good;
-}
+ ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
+ ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
+ ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
-/*
- * 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.
- */
-static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
-{
- u32 phyCnt1, phyCnt2;
+ /* prevent wraparound */
+ if (ah->cc.cycles & BIT(31))
+ clear = true;
- /* 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);
+#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
+ CC_DELTA(cycles, AR_CCCNT);
+ CC_DELTA(rx_frame, AR_RFCNT);
+ CC_DELTA(rx_clear, AR_RCCNT);
+ CC_DELTA(tx_frame, AR_TFCNT);
+#undef CC_DELTA
- /* Clear the mib counters and save them in the stats */
- ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
+ ah->listen_time += (ah->cc.cycles - cc.cycles) -
+ ((ah->cc.rx_frame - cc.rx_frame) +
+ (ah->cc.tx_frame - cc.tx_frame));
- if (!DO_ANI(ah)) {
- /*
- * We must always clear the interrupt cause by
- * resetting the phy error regs.
- */
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- return;
+skip:
+ if (clear) {
+ REG_WRITE(ah, AR_CCCNT, 0);
+ REG_WRITE(ah, AR_RFCNT, 0);
+ REG_WRITE(ah, AR_RCCNT, 0);
+ REG_WRITE(ah, AR_TFCNT, 0);
+ memset(&ah->cc, 0, sizeof(ah->cc));
}
- /* 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) ||
- ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
- struct ar5416AniState *aniState = ah->curani;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
- /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ah->stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ah->stats.ast_ani_cckerrs +=
- 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_new(ah);
- if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
- ath9k_hw_ani_cck_err_trigger_old(ah);
- /* NB: always restart to insure the h/w counters are reset */
- ath9k_ani_restart_old(ah);
- }
+ /* unfreeze counters */
+ REG_WRITE(ah, AR_MIBC, 0);
}
/*
@@ -1149,7 +871,7 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah)
* any of the MIB counters overflow/trigger so don't assume we're
* here because a PHY error counter triggered.
*/
-static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
+void ath9k_hw_proc_mib_event(struct ath_hw *ah)
{
u32 phyCnt1, phyCnt2;
@@ -1175,12 +897,17 @@ static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah)
/* NB: these are not reset-on-read */
phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- /* NB: always restart to insure the h/w counters are reset */
if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
- ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK))
- ath9k_ani_restart_new(ah);
+ ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+
+ if (!use_new_ani(ah))
+ ath9k_hw_ani_read_counters(ah);
+
+ /* NB: always restart to insure the h/w counters are reset */
+ ath9k_ani_restart(ah);
+ }
}
+EXPORT_SYMBOL(ath9k_hw_proc_mib_event);
void ath9k_hw_ani_setup(struct ath_hw *ah)
{
@@ -1206,61 +933,58 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ath_print(common, ATH_DBG_ANI, "Initialize ANI\n");
- memset(ah->ani, 0, sizeof(ah->ani));
- for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
- if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
- ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
- ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
+ if (use_new_ani(ah)) {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW;
- ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
- ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW;
+ } else {
+ ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
+ ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
- ah->ani[i].spurImmunityLevel =
- ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
+ ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
+ ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ah->channels); i++) {
+ struct ath9k_channel *chan = &ah->channels[i];
+ struct ar5416AniState *ani = &chan->ani;
- ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
+ if (use_new_ani(ah)) {
+ ani->spurImmunityLevel =
+ ATH9K_ANI_SPUR_IMMUNE_LVL_NEW;
- ah->ani[i].ofdmPhyErrBase = 0;
- ah->ani[i].cckPhyErrBase = 0;
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
if (AR_SREV_9300_20_OR_LATER(ah))
- ah->ani[i].mrcCCKOff =
+ ani->mrcCCKOff =
!ATH9K_ANI_ENABLE_MRC_CCK;
else
- ah->ani[i].mrcCCKOff = true;
+ ani->mrcCCKOff = true;
- ah->ani[i].ofdmsTurn = true;
+ ani->ofdmsTurn = true;
} else {
- ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
- ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
-
- ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
- ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD;
-
- ah->ani[i].spurImmunityLevel =
+ ani->spurImmunityLevel =
ATH9K_ANI_SPUR_IMMUNE_LVL_OLD;
- ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
+ ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD;
- ah->ani[i].ofdmPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
- ah->ani[i].cckPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD;
- ah->ani[i].cckWeakSigThreshold =
+ ani->cckWeakSigThreshold =
ATH9K_ANI_CCK_WEAK_SIG_THR;
}
- ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
- ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
- ah->ani[i].ofdmWeakSigDetectOff =
+ ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+ ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+ ani->ofdmWeakSigDetectOff =
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
- ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+ ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
}
/*
* since we expect some ongoing maintenance on the tables, let's sanity
* check here default level should not modify INI setting.
*/
- if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) {
+ if (use_new_ani(ah)) {
const struct ani_ofdm_level_entry *entry_ofdm;
const struct ani_cck_level_entry *entry_cck;
@@ -1274,50 +998,9 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD;
}
- ath_print(common, ATH_DBG_ANI,
- "Setting OfdmErrBase = 0x%08x\n",
- ah->ani[0].ofdmPhyErrBase);
- ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
- ah->ani[0].cckPhyErrBase);
-
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
-
- REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
-
- ath9k_enable_mib_counters(ah);
-
if (ah->config.enable_ani)
ah->proc_phyerr |= HAL_PROCESS_ANI;
-}
-
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah)
-{
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- struct ath_hw_ops *ops = ath9k_hw_ops(ah);
- priv_ops->ani_reset = ath9k_ani_reset_old;
- priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old;
-
- ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old;
- ops->ani_monitor = ath9k_hw_ani_monitor_old;
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n");
-}
-
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah)
-{
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- struct ath_hw_ops *ops = ath9k_hw_ops(ah);
-
- priv_ops->ani_reset = ath9k_ani_reset_new;
- priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new;
-
- ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new;
- ops->ani_monitor = ath9k_hw_ani_monitor_new;
-
- ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n");
+ ath9k_ani_restart(ah);
+ ath9k_enable_mib_counters(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index f4d0a4d48b37..98cfd8154c71 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -19,7 +19,7 @@
#define HAL_PROCESS_ANI 0x00000001
-#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI))
+#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan)
#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi)
@@ -93,6 +93,13 @@ struct ath9k_mib_stats {
u32 beacons;
};
+struct ath_cycle_counters {
+ u32 cycles;
+ u32 rx_frame;
+ u32 rx_clear;
+ u32 tx_frame;
+};
+
/* INI default values for ANI registers */
struct ath9k_ani_default {
u16 m1ThreshLow;
@@ -123,20 +130,11 @@ struct ar5416AniState {
u8 ofdmWeakSigDetectOff;
u8 cckWeakSigThreshold;
u32 listenTime;
- u32 ofdmTrigHigh;
- u32 ofdmTrigLow;
- int32_t cckTrigHigh;
- int32_t cckTrigLow;
int32_t rssiThrLow;
int32_t rssiThrHigh;
u32 noiseFloor;
- u32 txFrameCount;
- u32 rxFrameCount;
- u32 cycleCount;
u32 ofdmPhyErrCount;
u32 cckPhyErrCount;
- u32 ofdmPhyErrBase;
- u32 cckPhyErrBase;
int16_t pktRssi[2];
int16_t ofdmErrRssi[2];
int16_t cckErrRssi[2];
@@ -166,8 +164,7 @@ struct ar5416Stats {
void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
- u32 *rxf_pcnt, u32 *txf_pcnt);
+void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 525671f52b45..ea9f4497f58c 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -613,14 +613,11 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
rx_chainmask = ah->rxchainmask;
tx_chainmask = ah->txchainmask;
- ENABLE_REGWRITE_BUFFER(ah);
switch (rx_chainmask) {
case 0x5:
- DISABLE_REGWRITE_BUFFER(ah);
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
AR_PHY_SWAP_ALT_CHAIN);
- ENABLE_REGWRITE_BUFFER(ah);
case 0x3:
if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
@@ -630,17 +627,18 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
case 0x1:
case 0x2:
case 0x7:
+ ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
break;
default:
+ ENABLE_REGWRITE_BUFFER(ah);
break;
}
REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (tx_chainmask == 0x5) {
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
@@ -726,7 +724,6 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah,
REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
@@ -818,7 +815,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
@@ -849,7 +845,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9271(ah)) {
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
@@ -1053,7 +1048,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
- struct ar5416AniState *aniState = ah->curani;
+ struct ar5416AniState *aniState = &ah->curchan->ani;
struct ath_common *common = ath9k_hw_common(ah);
switch (cmd & ah->ani_function) {
@@ -1225,8 +1220,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
aniState->firstepLevel,
aniState->listenTime);
ath_print(common, ATH_DBG_ANI,
- "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
- aniState->cycleCount,
+ "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
@@ -1237,9 +1231,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
enum ath9k_ani_cmd cmd,
int param)
{
- struct ar5416AniState *aniState = ah->curani;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
s32 value, value2;
switch (cmd & ah->ani_function) {
@@ -1478,15 +1472,13 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d "
- "MRCcck=%s listenTime=%d CC=%d listen=%d "
+ "MRCcck=%s listenTime=%d "
"ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->listenTime,
- aniState->cycleCount,
- aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
@@ -1526,16 +1518,12 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
*/
static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
{
- struct ar5416AniState *aniState;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
struct ath9k_ani_default *iniDef;
- int index;
u32 val;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
iniDef = &aniState->iniDef;
ath_print(common, ATH_DBG_ANI,
@@ -1579,8 +1567,6 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = true; /* not available on pre AR9003 */
-
- aniState->cycleCount = 0;
}
static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index d7d1d55362e6..15f62cd0cc38 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -20,6 +20,13 @@
#define AR9285_CLCAL_REDO_THRESH 1
+enum ar9002_cal_types {
+ ADC_GAIN_CAL = BIT(0),
+ ADC_DC_CAL = BIT(1),
+ IQ_MISMATCH_CAL = BIT(2),
+};
+
+
static void ar9002_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
@@ -45,13 +52,6 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah,
ath_print(common, ATH_DBG_CALIBRATE,
"starting ADC DC Calibration\n");
break;
- case ADC_DC_INIT_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
- ath_print(common, ATH_DBG_CALIBRATE,
- "starting Init ADC DC Calibration\n");
- break;
- case TEMP_COMP_CAL:
- break; /* Not supported */
}
REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
@@ -96,25 +96,6 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah,
return iscaldone;
}
-/* Assumes you are talking about the currently configured channel */
-static bool ar9002_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-
- switch (calType & ah->supp_cals) {
- case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
- return true;
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
- conf_is_ht20(conf)))
- return true;
- break;
- }
- return false;
-}
-
static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
{
int i;
@@ -541,7 +522,6 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
REG_WRITE(ah, regList[i][0], regList[i][1]);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
@@ -877,24 +857,28 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
/* Enable IQ, ADC Gain and ADC DC offset CALs */
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
- if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
+ ah->supp_cals = IQ_MISMATCH_CAL;
+
+ if (AR_SREV_9160_10_OR_LATER(ah) &&
+ !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) {
+ ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
+
+
INIT_CAL(&ah->adcgain_caldata);
INSERT_CAL(ah, &ah->adcgain_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling ADC Gain Calibration.\n");
- }
- if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) {
+
INIT_CAL(&ah->adcdc_caldata);
INSERT_CAL(ah, &ah->adcdc_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling ADC DC Calibration.\n");
}
- if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
- INIT_CAL(&ah->iq_caldata);
- INSERT_CAL(ah, &ah->iq_caldata);
- ath_print(common, ATH_DBG_CALIBRATE,
- "enabling IQ Calibration.\n");
- }
+
+ INIT_CAL(&ah->iq_caldata);
+ INSERT_CAL(ah, &ah->iq_caldata);
+ ath_print(common, ATH_DBG_CALIBRATE,
+ "enabling IQ Calibration.\n");
ah->cal_list_curr = ah->cal_list;
@@ -950,13 +934,6 @@ static const struct ath9k_percal_data adc_dc_cal_single_sample = {
ar9002_hw_adc_dccal_collect,
ar9002_hw_adc_dccal_calibrate
};
-static const struct ath9k_percal_data adc_init_dc_cal = {
- ADC_DC_INIT_CAL,
- MIN_CAL_SAMPLES,
- INIT_LOG_COUNT,
- ar9002_hw_adc_dccal_collect,
- ar9002_hw_adc_dccal_calibrate
-};
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
{
@@ -973,16 +950,12 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
&adc_gain_cal_single_sample;
ah->adcdc_caldata.calData =
&adc_dc_cal_single_sample;
- ah->adcdc_calinitdata.calData =
- &adc_init_dc_cal;
} else {
ah->iq_caldata.calData = &iq_cal_multi_sample;
ah->adcgain_caldata.calData =
&adc_gain_cal_multi_sample;
ah->adcdc_caldata.calData =
&adc_dc_cal_multi_sample;
- ah->adcdc_calinitdata.calData =
- &adc_init_dc_cal;
}
ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
}
@@ -996,7 +969,6 @@ void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
priv_ops->init_cal = ar9002_hw_init_cal;
priv_ops->setup_calibration = ar9002_hw_setup_calibration;
- priv_ops->iscal_supported = ar9002_hw_iscal_supported;
ops->calibrate = ar9002_hw_calibrate;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index fde45082a13b..a0471f2e1c7a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -371,7 +371,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
udelay(1000);
@@ -468,7 +467,6 @@ static int ar9002_hw_get_radiorev(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
@@ -574,11 +572,6 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
ar9002_hw_attach_calib_ops(ah);
ar9002_hw_attach_mac_ops(ah);
-
- if (modparam_force_new_ani)
- ath9k_hw_attach_ani_ops_new(ah);
- else
- ath9k_hw_attach_ani_ops_old(ah);
}
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
@@ -627,6 +620,4 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
-
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index cd56c8692705..c00cdc67b55b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -415,7 +415,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ar9002_olc_init(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 4674ea8c9c99..9e6edffe0bd1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -18,6 +18,11 @@
#include "hw-ops.h"
#include "ar9003_phy.h"
+enum ar9003_cal_types {
+ IQ_MISMATCH_CAL = BIT(0),
+ TEMP_COMP_CAL = BIT(1),
+};
+
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
@@ -50,11 +55,6 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
ath_print(common, ATH_DBG_CALIBRATE,
"starting Temperature Compensation Calibration\n");
break;
- case ADC_DC_INIT_CAL:
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- /* Not yet */
- break;
}
}
@@ -314,27 +314,6 @@ static const struct ath9k_percal_data iq_cal_single_sample = {
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
{
ah->iq_caldata.calData = &iq_cal_single_sample;
- ah->supp_cals = IQ_MISMATCH_CAL;
-}
-
-static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- switch (calType & ah->supp_cals) {
- case IQ_MISMATCH_CAL:
- /*
- * XXX: Run IQ Mismatch for non-CCK only
- * Note that CHANNEL_B is never set though.
- */
- return true;
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- return false;
- case TEMP_COMP_CAL:
- return true;
- }
-
- return false;
}
/*
@@ -773,15 +752,16 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
/* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
+ ah->supp_cals = IQ_MISMATCH_CAL;
- if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
+ if (ah->supp_cals & IQ_MISMATCH_CAL) {
INIT_CAL(&ah->iq_caldata);
INSERT_CAL(ah, &ah->iq_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling IQ Calibration.\n");
}
- if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) {
+ if (ah->supp_cals & TEMP_COMP_CAL) {
INIT_CAL(&ah->tempCompCalData);
INSERT_CAL(ah, &ah->tempCompCalData);
ath_print(common, ATH_DBG_CALIBRATE,
@@ -808,7 +788,6 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
priv_ops->init_cal = ar9003_hw_init_cal;
priv_ops->setup_calibration = ar9003_hw_setup_calibration;
- priv_ops->iscal_supported = ar9003_hw_iscal_supported;
ops->calibrate = ar9003_hw_calibrate;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 064168909108..02c970819f79 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -333,6 +333,4 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
ar9003_hw_attach_phy_ops(ah);
ar9003_hw_attach_calib_ops(ah);
ar9003_hw_attach_mac_ops(ah);
-
- ath9k_hw_attach_ani_ops_new(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index a491854fa38a..efb05599b84c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -747,9 +747,9 @@ static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
static bool ar9003_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
- struct ar5416AniState *aniState = ah->curani;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &chan->ani;
s32 value, value2;
switch (cmd & ah->ani_function) {
@@ -1005,15 +1005,13 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
ath_print(common, ATH_DBG_ANI,
"ANI parameters: SI=%d, ofdmWS=%s FS=%d "
- "MRCcck=%s listenTime=%d CC=%d listen=%d "
+ "MRCcck=%s listenTime=%d "
"ofdmErrs=%d cckErrs=%d\n",
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff ? "on" : "off",
aniState->firstepLevel,
!aniState->mrcCCKOff ? "on" : "off",
aniState->listenTime,
- aniState->cycleCount,
- aniState->listenTime,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
@@ -1067,12 +1065,9 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_channel *chan = ah->curchan;
struct ath9k_ani_default *iniDef;
- int index;
u32 val;
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ah->ani[index];
- ah->curani = aniState;
+ aniState = &ah->curchan->ani;
iniDef = &aniState->iniDef;
ath_print(common, ATH_DBG_ANI,
@@ -1116,8 +1111,6 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW;
aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG;
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
-
- aniState->cycleCount = 0;
}
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
@@ -1232,7 +1225,7 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status;
+ u32 status;
if (likely(!(common->debug_mask & ATH_DBG_RESET)))
return;
@@ -1261,11 +1254,13 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
"** BB mode: BB_gen_controls=0x%08x **\n",
REG_READ(ah, AR_PHY_GEN_CTRL));
- if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt))
+ ath9k_hw_update_cycle_counters(ah);
+#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles)
+ if (ah->cc_delta.cycles)
ath_print(common, ATH_DBG_RESET,
"** BB busy times: rx_clear=%d%%, "
"rx_frame=%d%%, tx_frame=%d%% **\n",
- rxc_pcnt, rxf_pcnt, txf_pcnt);
+ PCT(rx_clear), PCT(rx_frame), PCT(tx_frame));
ath_print(common, ATH_DBG_RESET,
"==== BB update: done ====\n\n");
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 9f8e542ef47e..de2b18ee7f77 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -241,7 +241,6 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
bool bf_stale;
- bool bf_isnullfunc;
bool bf_tx_aborted;
u16 bf_flags;
struct ath_buf_state bf_state;
@@ -349,7 +348,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-void ath9k_enable_ps(struct ath_softc *sc);
/********/
/* VIFs */
@@ -573,8 +571,6 @@ struct ath_ant_comb {
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
#define PS_WAIT_FOR_TX_ACK BIT(3)
#define PS_BEACON_SYNC BIT(4)
-#define PS_NULLFUNC_COMPLETED BIT(5)
-#define PS_ENABLED BIT(6)
struct ath_wiphy;
struct ath_rate_table;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 67ee5d735cc1..6d509484b5f6 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -186,7 +186,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
return true;
}
- if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
+ if (!(ah->supp_cals & currCal->calData->calType))
return true;
ath_print(common, ATH_DBG_CALIBRATE,
@@ -300,7 +300,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
}
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
@@ -346,34 +345,34 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
struct ieee80211_channel *c = chan->chan;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- if (!caldata)
- return false;
-
chan->channelFlags &= (~CHANNEL_CW_INT);
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
ath_print(common, ATH_DBG_CALIBRATE,
"NF did not complete in calibration window\n");
- nf = 0;
- caldata->rawNoiseFloor = nf;
return false;
- } else {
- ath9k_hw_do_getnf(ah, nfarray);
- ath9k_hw_nf_sanitize(ah, nfarray);
- nf = nfarray[0];
- if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
- && nf > nfThresh) {
- ath_print(common, ATH_DBG_CALIBRATE,
- "noise floor failed detected; "
- "detected %d, threshold %d\n",
- nf, nfThresh);
- chan->channelFlags |= CHANNEL_CW_INT;
- }
+ }
+
+ ath9k_hw_do_getnf(ah, nfarray);
+ ath9k_hw_nf_sanitize(ah, nfarray);
+ nf = nfarray[0];
+ if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
+ && nf > nfThresh) {
+ ath_print(common, ATH_DBG_CALIBRATE,
+ "noise floor failed detected; "
+ "detected %d, threshold %d\n",
+ nf, nfThresh);
+ chan->channelFlags |= CHANNEL_CW_INT;
+ }
+
+ if (!caldata) {
+ chan->noisefloor = nf;
+ return false;
}
h = caldata->nfCalHist;
caldata->nfcal_pending = false;
ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
- caldata->rawNoiseFloor = h[0].privNF;
+ chan->noisefloor = h[0].privNF;
return true;
}
@@ -401,10 +400,10 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
{
- if (!ah->caldata || !ah->caldata->rawNoiseFloor)
+ if (!ah->curchan || !ah->curchan->noisefloor)
return ath9k_hw_get_default_nf(ah, chan);
- return ah->caldata->rawNoiseFloor;
+ return ah->curchan->noisefloor;
}
EXPORT_SYMBOL(ath9k_hw_getchan_noise);
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 5b053a6260b2..b8973eb8d858 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -58,14 +58,6 @@ struct ar5416IniArray {
} \
} while (0)
-enum ath9k_cal_types {
- ADC_DC_INIT_CAL = 0x1,
- ADC_GAIN_CAL = 0x2,
- ADC_DC_CAL = 0x4,
- IQ_MISMATCH_CAL = 0x8,
- TEMP_COMP_CAL = 0x10,
-};
-
enum ath9k_cal_state {
CAL_INACTIVE,
CAL_WAITING,
@@ -80,7 +72,7 @@ enum ath9k_cal_state {
#define PER_MAX_LOG_COUNT 10
struct ath9k_percal_data {
- enum ath9k_cal_types calType;
+ u32 calType;
u32 calNumSamples;
u32 calCountMax;
void (*calCollect) (struct ath_hw *);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d65a896a421d..74a4570dc87f 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -488,6 +488,8 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
+ struct ath_wiphy *aphy = sc->pri_wiphy;
+ struct ieee80211_channel *chan = aphy->hw->conf.channel;
char buf[512];
unsigned int len = 0;
int i;
@@ -498,7 +500,8 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
"primary: %s (%s chan=%d ht=%d)\n",
wiphy_name(sc->pri_wiphy->hw->wiphy),
ath_wiphy_state_str(sc->pri_wiphy->state),
- sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
+ ieee80211_frequency_to_channel(chan->center_freq),
+ aphy->chan_is_ht);
put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
@@ -545,11 +548,13 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
struct ath_wiphy *aphy = sc->sec_wiphy[i];
if (aphy == NULL)
continue;
+ chan = aphy->hw->conf.channel;
len += snprintf(buf + len, sizeof(buf) - len,
- "secondary: %s (%s chan=%d ht=%d)\n",
- wiphy_name(aphy->hw->wiphy),
- ath_wiphy_state_str(aphy->state),
- aphy->chan_idx, aphy->chan_is_ht);
+ "secondary: %s (%s chan=%d ht=%d)\n",
+ wiphy_name(aphy->hw->wiphy),
+ ath_wiphy_state_str(aphy->state),
+ ieee80211_frequency_to_channel(chan->center_freq),
+ aphy->chan_is_ht);
}
if (len > sizeof(buf))
len = sizeof(buf);
@@ -696,6 +701,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("DESC CFG Error: ", desc_cfg_err);
PR("DATA Underrun: ", data_underrun);
PR("DELIM Underrun: ", delim_underrun);
+ PR("TX-Pkts-All: ", tx_pkts_all);
+ PR("TX-Bytes-All: ", tx_bytes_all);
if (len > size)
len = size;
@@ -709,6 +716,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct ath_tx_status *ts)
{
+ TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
+ sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
+
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
TX_STAT_INC(txq->axq_qnum, a_xretries);
@@ -803,6 +813,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+ len += snprintf(buf + len, size - len,
+ "%18s : %10u\n", "RX-Pkts-All",
+ sc->debug.stats.rxstats.rx_pkts_all);
+ len += snprintf(buf + len, size - len,
+ "%18s : %10u\n", "RX-Bytes-All",
+ sc->debug.stats.rxstats.rx_bytes_all);
+
if (len > size)
len = size;
@@ -821,6 +838,9 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
u32 phyerr;
+ RX_STAT_INC(rx_pkts_all);
+ sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
+
if (rs->rs_status & ATH9K_RXERR_CRC)
RX_STAT_INC(crc_err);
if (rs->rs_status & ATH9K_RXERR_DECRYPT)
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 5d21704e87ff..822b6f3f23c5 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -89,6 +89,10 @@ struct ath_rc_stats {
/**
* struct ath_tx_stats - Statistics about TX
+ * @tx_pkts_all: No. of total frames transmitted, including ones that
+ may have had errors.
+ * @tx_bytes_all: No. of total bytes transmitted, including ones that
+ may have had errors.
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
* @a_aggr: Total no. of aggregates queued
@@ -107,6 +111,8 @@ struct ath_rc_stats {
* @delim_urn: TX delimiter underrun errors
*/
struct ath_tx_stats {
+ u32 tx_pkts_all;
+ u32 tx_bytes_all;
u32 queued;
u32 completed;
u32 a_aggr;
@@ -124,6 +130,10 @@ struct ath_tx_stats {
/**
* struct ath_rx_stats - RX Statistics
+ * @rx_pkts_all: No. of total frames received, including ones that
+ may have had errors.
+ * @rx_bytes_all: No. of total bytes received, including ones that
+ may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
decryption process completed
@@ -136,6 +146,8 @@ struct ath_tx_stats {
* @phy_err_stats: Individual PHY error statistics
*/
struct ath_rx_stats {
+ u32 rx_pkts_all;
+ u32 rx_bytes_all;
u32 crc_err;
u32 decrypt_crc_err;
u32 phy_err;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index d6eed1f02e84..4fa4d8e28c64 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -179,6 +179,9 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader;
struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+ u16 ver_minor;
+
+ ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
switch (param) {
case EEP_NFTHRESH_2:
@@ -204,7 +207,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
case EEP_DB_2:
return pModal->db1_1;
case EEP_MINOR_REV:
- return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+ return ver_minor;
case EEP_TX_MASK:
return pBase->txMask;
case EEP_RX_MASK:
@@ -217,6 +220,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
return pModal->version;
case EEP_ANT_DIV_CTL1:
return pModal->antdiv_ctl1;
+ case EEP_TXGAIN_TYPE:
+ if (ver_minor >= AR5416_EEP_MINOR_VER_19)
+ return pBase->txGainType;
+ else
+ return AR5416_EEP_TXGAIN_ORIGINAL;
default:
return 0;
}
@@ -500,7 +508,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
}
@@ -832,7 +839,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index b100db2766cf..bbb54bc28a44 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -380,15 +380,6 @@ static void ath9k_enable_regwrite_buffer(void *hw_priv)
atomic_inc(&priv->wmi->mwrite_cnt);
}
-static void ath9k_disable_regwrite_buffer(void *hw_priv)
-{
- struct ath_hw *ah = (struct ath_hw *) hw_priv;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-
- atomic_dec(&priv->wmi->mwrite_cnt);
-}
-
static void ath9k_regwrite_flush(void *hw_priv)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -397,6 +388,8 @@ static void ath9k_regwrite_flush(void *hw_priv)
u32 rsp_status;
int r;
+ atomic_dec(&priv->wmi->mwrite_cnt);
+
mutex_lock(&priv->wmi->multi_write_mutex);
if (priv->wmi->multi_write_idx) {
@@ -420,7 +413,6 @@ static const struct ath_ops ath9k_common_ops = {
.read = ath9k_regread,
.write = ath9k_regwrite,
.enable_write_buffer = ath9k_enable_regwrite_buffer,
- .disable_write_buffer = ath9k_disable_regwrite_buffer,
.write_flush = ath9k_regwrite_flush,
};
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 5124d04b240b..f12591f5d02a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -760,23 +760,12 @@ void ath9k_ani_work(struct work_struct *work)
ath9k_hw_ani_monitor(ah, ah->curchan);
/* Perform calibration if necessary */
- if (longcal || shortcal) {
+ if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
common->rx_chainmask,
longcal);
- if (longcal)
- common->ani.noise_floor =
- ath9k_hw_getchan_noise(ah, ah->curchan);
-
- ath_print(common, ATH_DBG_ANI,
- " calibrate chan %u/%x nf: %d\n",
- ah->curchan->channel,
- ah->curchan->channelFlags,
- common->ani.noise_floor);
- }
-
ath9k_htc_ps_restore(priv);
}
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index ffecbadaea4a..0a4ad348b699 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -128,17 +128,6 @@ static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
}
-static inline void ath9k_hw_procmibevent(struct ath_hw *ah)
-{
- ath9k_hw_ops(ah)->ani_proc_mib_event(ah);
-}
-
-static inline void ath9k_hw_ani_monitor(struct ath_hw *ah,
- struct ath9k_channel *chan)
-{
- ath9k_hw_ops(ah)->ani_monitor(ah, chan);
-}
-
/* Private hardware call ops */
/* PHY ops */
@@ -276,15 +265,4 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}
-static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah,
- enum ath9k_cal_types calType)
-{
- return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType);
-}
-
-static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
-{
- ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning);
-}
-
#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 25ed65ac992c..05e9935ef160 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -299,7 +299,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
/* This should work for all families including legacy */
@@ -371,10 +370,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
ah->config.pcie_clock_req = 0;
ah->config.pcie_waen = 0;
ah->config.analog_shiftreg = 1;
- ah->config.ofdm_trig_low = 200;
- ah->config.ofdm_trig_high = 500;
- ah->config.cck_trig_high = 200;
- ah->config.cck_trig_low = 100;
ah->config.enable_ani = true;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -676,7 +671,6 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
static void ath9k_hw_init_pll(struct ath_hw *ah,
@@ -741,7 +735,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
@@ -885,7 +878,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* Restore TX Trigger Level to its pre-reset value.
@@ -933,7 +925,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah))
ath9k_hw_reset_txstatus_ring(ah);
@@ -1031,7 +1022,6 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
REG_WRITE(ah, AR_RTC_RC, rst_flags);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
udelay(50);
@@ -1070,7 +1060,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
udelay(2);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
udelay(2);
@@ -1239,7 +1228,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO;
- if (curchan && !ah->chip_fullsleep && ah->caldata)
+ if (curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, curchan);
ah->caldata = caldata;
@@ -1374,7 +1363,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
r = ath9k_hw_rf_set_freq(ah, chan);
if (r)
@@ -1386,7 +1374,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
ah->intr_txqs = 0;
for (i = 0; i < ah->caps.total_queues; i++)
@@ -1434,7 +1421,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* For big endian systems turn on swapping for descriptors
@@ -1684,7 +1670,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
beacon_period &= ~ATH9K_BEACON_ENA;
if (beacon_period & ATH9K_BEACON_RESET_TSF) {
@@ -1712,7 +1697,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
REG_RMW_FIELD(ah, AR_RSSI_THR,
AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
@@ -1758,7 +1742,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
REG_SET_BIT(ah, AR_TIMER_MODE,
AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
@@ -2176,7 +2159,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
EXPORT_SYMBOL(ath9k_hw_setrxfilter);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index df47f792cf4e..87627dd63463 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -70,19 +70,13 @@
#define ENABLE_REGWRITE_BUFFER(_ah) \
do { \
- if (AR_SREV_9271(_ah)) \
+ if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \
ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \
} while (0)
-#define DISABLE_REGWRITE_BUFFER(_ah) \
- do { \
- if (AR_SREV_9271(_ah)) \
- ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \
- } while (0)
-
#define REGWRITE_BUFFER_FLUSH(_ah) \
do { \
- if (AR_SREV_9271(_ah)) \
+ if (ath9k_hw_common(_ah)->ops->write_flush) \
ath9k_hw_common(_ah)->ops->write_flush((_ah)); \
} while (0)
@@ -342,7 +336,6 @@ struct ath9k_hw_cal_data {
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
- int16_t rawNoiseFloor;
bool paprd_done;
bool nfcal_pending;
bool nfcal_interference;
@@ -353,9 +346,11 @@ struct ath9k_hw_cal_data {
struct ath9k_channel {
struct ieee80211_channel *chan;
+ struct ar5416AniState ani;
u16 channel;
u32 channelFlags;
u32 chanmode;
+ s16 noisefloor;
};
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
@@ -514,14 +509,6 @@ struct ath_hw_antcomb_conf {
* @setup_calibration: set up calibration
* @iscal_supported: used to query if a type of calibration is supported
*
- * @ani_reset: reset ANI parameters to default values
- * @ani_lower_immunity: lower the noise immunity level. The level controls
- * the power-based packet detection on hardware. If a power jump is
- * detected the adapter takes it as an indication that a packet has
- * arrived. The level ranges from 0-5. Each level corresponds to a
- * few dB more of noise immunity. If you have a strong time-varying
- * interference that is causing false detections (OFDM timing errors or
- * CCK timing errors) the level can be increased.
* @ani_cache_ini_regs: cache the values for ANI from the initial
* register settings through the register initialization.
*/
@@ -535,8 +522,6 @@ struct ath_hw_private_ops {
bool (*macversion_supported)(u32 macversion);
void (*setup_calibration)(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
- bool (*iscal_supported)(struct ath_hw *ah,
- enum ath9k_cal_types calType);
/* PHY ops */
int (*rf_set_freq)(struct ath_hw *ah,
@@ -568,8 +553,6 @@ struct ath_hw_private_ops {
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
/* ANI */
- void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
- void (*ani_lower_immunity)(struct ath_hw *ah);
void (*ani_cache_ini_regs)(struct ath_hw *ah);
};
@@ -581,11 +564,6 @@ struct ath_hw_private_ops {
*
* @config_pci_powersave:
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
- *
- * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI
- * thresholds being reached or having overflowed.
- * @ani_monitor: called periodically by the core driver to collect
- * MIB stats and adjust ANI if specific thresholds have been reached.
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
@@ -626,9 +604,6 @@ struct ath_hw_ops {
u32 burstDuration);
void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
u32 vmf);
-
- void (*ani_proc_mib_event)(struct ath_hw *ah);
- void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan);
};
struct ath_nf_limits {
@@ -689,10 +664,9 @@ struct ath_hw {
u32 atim_window;
/* Calibration */
- enum ath9k_cal_types supp_cals;
+ u32 supp_cals;
struct ath9k_cal_list iq_caldata;
struct ath9k_cal_list adcgain_caldata;
- struct ath9k_cal_list adcdc_calinitdata;
struct ath9k_cal_list adcdc_caldata;
struct ath9k_cal_list tempCompCalData;
struct ath9k_cal_list *cal_list;
@@ -761,13 +735,13 @@ struct ath_hw {
/* ANI */
u32 proc_phyerr;
u32 aniperiod;
- struct ar5416AniState *curani;
- struct ar5416AniState ani[255];
int totalSizeDesired[5];
int coarse_high[5];
int coarse_low[5];
int firpwr[5];
enum ath9k_ani_cmd ani_function;
+ struct ath_cycle_counters cc, cc_delta;
+ int32_t listen_time;
/* Bluetooth coexistance */
struct ath_btcoex_hw btcoex_hw;
@@ -988,8 +962,9 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
* older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani.
*/
extern int modparam_force_new_ani;
-void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah);
-void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah);
+void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
+void ath9k_hw_proc_mib_event(struct ath_hw *ah);
+void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#define ATH_PCIE_CAP_LINK_CTRL 0x70
#define ATH_PCIE_CAP_LINK_L0S 1
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index de3393867e37..d76003c06fe4 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
* on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make
* this static */
-static struct ieee80211_channel ath9k_2ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_2ghz_chantable[] = {
CHAN2G(2412, 0), /* Channel 1 */
CHAN2G(2417, 1), /* Channel 2 */
CHAN2G(2422, 2), /* Channel 3 */
@@ -77,7 +77,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = {
* on 5 MHz steps, we support the channels which we know
* we have calibration data for all cards though to make
* this static */
-static struct ieee80211_channel ath9k_5ghz_chantable[] = {
+static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
/* _We_ call this UNII 1 */
CHAN5G(5180, 14), /* Channel 36 */
CHAN5G(5200, 15), /* Channel 40 */
@@ -477,10 +477,17 @@ err:
return -EIO;
}
-static void ath9k_init_channels_rates(struct ath_softc *sc)
+static int ath9k_init_channels_rates(struct ath_softc *sc)
{
+ void *channels;
+
if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
+ channels = kmemdup(ath9k_2ghz_chantable,
+ sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
+ if (!channels)
+ return -ENOMEM;
+
+ sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
ARRAY_SIZE(ath9k_2ghz_chantable);
@@ -490,7 +497,15 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
}
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
- sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
+ channels = kmemdup(ath9k_5ghz_chantable,
+ sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
+ if (!channels) {
+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+ return -ENOMEM;
+ }
+
+ sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
ARRAY_SIZE(ath9k_5ghz_chantable);
@@ -499,6 +514,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc)
sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
ARRAY_SIZE(ath9k_legacy_rates) - 4;
}
+ return 0;
}
static void ath9k_init_misc(struct ath_softc *sc)
@@ -506,7 +522,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
- common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX;
@@ -595,8 +610,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret)
goto err_btcoex;
+ ret = ath9k_init_channels_rates(sc);
+ if (ret)
+ goto err_btcoex;
+
ath9k_init_crypto(sc);
- ath9k_init_channels_rates(sc);
ath9k_init_misc(sc);
return 0;
@@ -639,6 +657,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_WDS) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
@@ -756,6 +775,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
{
int i = 0;
+ if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
+
+ if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
+ kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
+
if ((sc->btcoex.no_stomp_timer) &&
sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 3efda8a8a3c1..8c13479b17cd 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -40,7 +40,6 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
}
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
@@ -492,8 +491,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_WRITE(ah, AR_DMISC(q),
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
- REGWRITE_BUFFER_FLUSH(ah);
-
if (qi->tqi_cbrPeriod) {
REG_WRITE(ah, AR_QCBRCFG(q),
SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
@@ -509,8 +506,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_Q_RDYTIMECFG_EN);
}
- REGWRITE_BUFFER_FLUSH(ah);
-
REG_WRITE(ah, AR_DCHNTIME(q),
SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
(qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
@@ -530,7 +525,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
}
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
REG_WRITE(ah, AR_DMISC(q),
@@ -553,7 +547,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
| AR_D_MISC_POST_FR_BKOFF_DIS);
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
/*
* cwmin and cwmax should be 0 for beacon queue
@@ -585,7 +578,6 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
REGWRITE_BUFFER_FLUSH(ah);
- DISABLE_REGWRITE_BUFFER(ah);
break;
case ATH9K_TX_QUEUE_PSPOLL:
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a13387882636..74c2dc8a8b8a 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -459,16 +459,6 @@ void ath_ani_calibrate(unsigned long data)
ah->curchan,
common->rx_chainmask,
longcal);
-
- if (longcal)
- common->ani.noise_floor = ath9k_hw_getchan_noise(ah,
- ah->curchan);
-
- ath_print(common, ATH_DBG_ANI,
- " calibrate chan %u/%x nf: %d\n",
- ah->curchan->channel,
- ah->curchan->channelFlags,
- common->ani.noise_floor);
}
}
@@ -723,7 +713,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* it will clear whatever condition caused
* the interrupt.
*/
- ath9k_hw_procmibevent(ah);
+ ath9k_hw_proc_mib_event(ah);
ath9k_hw_set_interrupts(ah, ah->imask);
}
@@ -1384,6 +1374,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
case NL80211_IFTYPE_STATION:
ic_opmode = NL80211_IFTYPE_STATION;
break;
+ case NL80211_IFTYPE_WDS:
+ ic_opmode = NL80211_IFTYPE_WDS;
+ break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
@@ -1491,7 +1484,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&sc->mutex);
}
-void ath9k_enable_ps(struct ath_softc *sc)
+static void ath9k_enable_ps(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
@@ -1505,13 +1498,32 @@ void ath9k_enable_ps(struct ath_softc *sc)
}
}
+static void ath9k_disable_ps(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ sc->ps_enabled = false;
+ ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ ath9k_hw_setrxabort(ah, 0);
+ sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
+ PS_WAIT_FOR_CAB |
+ PS_WAIT_FOR_PSPOLL_DATA |
+ PS_WAIT_FOR_TX_ACK);
+ if (ah->imask & ATH9K_INT_TIM_TIMER) {
+ ah->imask &= ~ATH9K_INT_TIM_TIMER;
+ ath9k_hw_set_interrupts(ah, ah->imask);
+ }
+ }
+
+}
+
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_conf *conf = &hw->conf;
- struct ath_hw *ah = sc->sc_ah;
bool disable_radio;
mutex_lock(&sc->mutex);
@@ -1558,35 +1570,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_PS) {
unsigned long flags;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
- if (conf->flags & IEEE80211_CONF_PS) {
- sc->ps_flags |= PS_ENABLED;
- /*
- * At this point we know hardware has received an ACK
- * of a previously sent null data frame.
- */
- if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) {
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
- ath9k_enable_ps(sc);
- }
- } else {
- sc->ps_enabled = false;
- sc->ps_flags &= ~(PS_ENABLED |
- PS_NULLFUNC_COMPLETED);
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
- if (!(ah->caps.hw_caps &
- ATH9K_HW_CAP_AUTOSLEEP)) {
- ath9k_hw_setrxabort(sc->sc_ah, 0);
- sc->ps_flags &= ~(PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK);
- if (ah->imask & ATH9K_INT_TIM_TIMER) {
- ah->imask &= ~ATH9K_INT_TIM_TIMER;
- ath9k_hw_set_interrupts(sc->sc_ah,
- ah->imask);
- }
- }
- }
+ if (conf->flags & IEEE80211_CONF_PS)
+ ath9k_enable_ps(sc);
+ else
+ ath9k_disable_ps(sc);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
}
@@ -2004,15 +1991,32 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_conf *conf = &hw->conf;
+ struct ieee80211_supported_band *sband;
+ struct ath9k_channel *chan;
+
+ sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+ if (sband && idx >= sband->n_channels) {
+ idx -= sband->n_channels;
+ sband = NULL;
+ }
+
+ if (!sband)
+ sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
- if (idx != 0)
- return -ENOENT;
+ if (!sband || idx >= sband->n_channels)
+ return -ENOENT;
- survey->channel = conf->channel;
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = common->ani.noise_floor;
+ survey->channel = &sband->channels[idx];
+ chan = &ah->channels[survey->channel->hw_value];
+ survey->filled = 0;
+
+ if (chan == ah->curchan)
+ survey->filled |= SURVEY_INFO_IN_USE;
+
+ if (chan->noisefloor) {
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
+ survey->noise = chan->noisefloor;
+ }
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f7da6b20a925..aa447770eb2b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1648,13 +1648,6 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_buf_addr = bf->bf_dmacontext;
- /* tag if this is a nullfunc frame to enable PS when AP acks it */
- if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
- bf->bf_isnullfunc = true;
- sc->ps_flags &= ~PS_NULLFUNC_COMPLETED;
- } else
- bf->bf_isnullfunc = false;
-
bf->bf_tx_aborted = false;
return 0;
@@ -2082,18 +2075,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
}
/*
- * We now know the nullfunc frame has been ACKed so we
- * can disable RX.
- */
- if (bf->bf_isnullfunc &&
- (ts.ts_status & ATH9K_TX_ACKED)) {
- if ((sc->ps_flags & PS_ENABLED))
- ath9k_enable_ps(sc);
- else
- sc->ps_flags |= PS_NULLFUNC_COMPLETED;
- }
-
- /*
* Remove ath_buf's of the same transmit unit from txq,
* however leave the last descriptor back as the holding
* descriptor for hw.
@@ -2236,17 +2217,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
txok = !(txs.ts_status & ATH9K_TXERR_MASK);
- /*
- * Make sure null func frame is acked before configuring
- * hw into ps mode.
- */
- if (bf->bf_isnullfunc && txok) {
- if ((sc->ps_flags & PS_ENABLED))
- ath9k_enable_ps(sc);
- else
- sc->ps_flags |= PS_NULLFUNC_COMPLETED;
- }
-
if (!bf_isampdu(bf)) {
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 20f2a77e54d2..6cf0c9ef47aa 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -279,6 +279,7 @@ struct ar9170 {
unsigned int beacon_max_len;
bool rx_stream;
bool tx_stream;
+ bool rx_filter;
unsigned int mem_blocks;
unsigned int mem_block_size;
unsigned int rx_size;
@@ -314,6 +315,7 @@ struct ar9170 {
u64 cur_mc_hash;
u32 cur_filter;
unsigned int filter_state;
+ unsigned int rx_filter_caps;
bool sniffer_enabled;
/* MAC */
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index 0fc83d2336fd..f78728c38294 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -59,6 +59,16 @@ static inline int carl9170_flush_cab(struct ar9170 *ar,
return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0);
}
+static inline int carl9170_rx_filter(struct ar9170 *ar,
+ const unsigned int _rx_filter)
+{
+ __le32 rx_filter = cpu_to_le32(_rx_filter);
+
+ return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER,
+ sizeof(rx_filter), (u8 *)&rx_filter,
+ 0, NULL);
+}
+
struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
const enum carl9170_cmd_oids cmd, const unsigned int len);
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 36615462b87a..ae6c006bbc56 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -257,6 +257,13 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if (SUPP(CARL9170FW_USB_UP_STREAM))
ar->fw.rx_stream = true;
+ if (SUPP(CARL9170FW_RX_FILTER)) {
+ ar->fw.rx_filter = true;
+ ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
+ FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS |
+ FIF_PROMISC_IN_BSS;
+ }
+
ar->fw.vif_num = otus_desc->vif_num;
ar->fw.cmd_bufs = otus_desc->cmd_bufs;
ar->fw.address = le32_to_cpu(otus_desc->fw_address);
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index d4a4e1dbef06..d552166db505 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -53,6 +53,7 @@ enum carl9170_cmd_oids {
CARL9170_CMD_REBOOT = 0x04,
CARL9170_CMD_BCN_CTRL = 0x05,
CARL9170_CMD_READ_TSF = 0x06,
+ CARL9170_CMD_RX_FILTER = 0x07,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
@@ -153,6 +154,20 @@ struct carl9170_psm {
} __packed;
#define CARL9170_PSM_SIZE 4
+struct carl9170_rx_filter_cmd {
+ __le32 rx_filter;
+} __packed;
+#define CARL9170_RX_FILTER_CMD_SIZE 4
+
+#define CARL9170_RX_FILTER_BAD 0x01
+#define CARL9170_RX_FILTER_OTHER_RA 0x02
+#define CARL9170_RX_FILTER_DECRY_FAIL 0x04
+#define CARL9170_RX_FILTER_CTL_OTHER 0x08
+#define CARL9170_RX_FILTER_CTL_PSPOLL 0x10
+#define CARL9170_RX_FILTER_CTL_BACKR 0x20
+#define CARL9170_RX_FILTER_MGMT 0x40
+#define CARL9170_RX_FILTER_DATA 0x80
+
struct carl9170_bcn_ctrl_cmd {
__le32 vif_id;
__le32 mode;
@@ -188,6 +203,7 @@ struct carl9170_cmd {
struct carl9170_rf_init rf_init;
struct carl9170_psm psm;
struct carl9170_bcn_ctrl_cmd bcn_ctrl;
+ struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed;
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 7cd811708fe5..71f3821f6058 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -66,6 +66,9 @@ enum carl9170fw_feature_list {
/* Firmware PSM support | CARL9170_CMD_PSM */
CARL9170FW_PSM,
+ /* Firmware RX filter | CARL9170_CMD_RX_FILTER */
+ CARL9170FW_RX_FILTER,
+
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
@@ -142,7 +145,7 @@ struct carl9170fw_fix_desc {
(sizeof(struct carl9170fw_fix_desc))
#define CARL9170FW_DBG_DESC_MIN_VER 1
-#define CARL9170FW_DBG_DESC_CUR_VER 2
+#define CARL9170FW_DBG_DESC_CUR_VER 3
struct carl9170fw_dbg_desc {
struct carl9170fw_desc_head head;
@@ -150,6 +153,7 @@ struct carl9170fw_dbg_desc {
__le32 counter_addr;
__le32 rx_total_addr;
__le32 rx_overrun_addr;
+ __le32 rx_filter;
/* Put your debugging definitions here */
} __packed;
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index b1292ac5b703..2f471b3f05af 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -731,6 +731,9 @@ struct ar9170_stream {
#define SET_VAL(reg, value, newvalue) \
(value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+#define SET_CONSTVAL(reg, newvalue) \
+ (((newvalue) << reg##_S) & reg)
+
#define MOD_VAL(reg, value, newvalue) \
(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
#endif /* __CARL9170_SHARED_HW_H */
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 84bd38e9961c..3cc99f3f7ab5 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -380,6 +380,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
if (err)
goto out;
+ if (ar->fw.rx_filter) {
+ err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA |
+ CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD);
+ if (err)
+ goto out;
+ }
+
err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER,
AR9170_DMA_TRIGGER_RXQ);
if (err)
@@ -840,8 +847,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
struct ar9170 *ar = hw->priv;
/* mask supported flags */
- *new_flags &= FIF_ALLMULTI | FIF_FCSFAIL | FIF_PLCPFAIL |
- FIF_OTHER_BSS | FIF_PROMISC_IN_BSS;
+ *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
if (!IS_ACCEPTING_CMD(ar))
return;
@@ -867,6 +873,26 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
WARN_ON(carl9170_set_operating_mode(ar));
}
+ if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
+ u32 rx_filter = 0;
+
+ if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
+ rx_filter |= CARL9170_RX_FILTER_BAD;
+
+ if (!(*new_flags & FIF_CONTROL))
+ rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
+
+ if (!(*new_flags & FIF_PSPOLL))
+ rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
+
+ if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) {
+ rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
+ rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
+ }
+
+ WARN_ON(carl9170_rx_filter(ar, rx_filter));
+ }
+
mutex_unlock(&ar->mutex);
}
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h
index 53c18d34ffcc..02c34eb4ebde 100644
--- a/drivers/net/wireless/ath/carl9170/phy.h
+++ b/drivers/net/wireless/ath/carl9170/phy.h
@@ -423,8 +423,8 @@
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
-#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
#define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c)
+#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00
@@ -561,7 +561,4 @@
#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
-#define REDUCE_CHAIN_0 0x00000050
-#define REDUCE_CHAIN_1 0x00000051
-
#endif /* __CARL9170_SHARED_PHY_H */
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index 0e917f80eab4..ff53f078a0b5 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 8
-#define CARL9170FW_VERSION_DAY 30
-#define CARL9170FW_VERSION_GIT "1.8.8.1"
+#define CARL9170FW_VERSION_MONTH 9
+#define CARL9170FW_VERSION_DAY 28
+#define CARL9170FW_VERSION_GIT "1.8.8.3"
#endif /* __CARL9170_SHARED_VERSION_H */