aboutsummaryrefslogtreecommitdiff
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/cmd.c2
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c6
-rw-r--r--drivers/net/wireless/ath/ath.h8
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig18
-rw-r--r--drivers/net/wireless/ath/ath5k/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c219
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c40
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h286
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c28
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c827
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h5
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c6
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c33
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.h2
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c24
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.h18
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c180
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c127
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h2
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c409
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c11
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c326
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c571
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c649
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c692
-rw-r--r--drivers/net/wireless/ath/ath5k/reg.h31
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c1221
-rw-r--r--drivers/net/wireless/ath/ath5k/rfbuffer.h1169
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c93
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_mac.c123
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_phy.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c27
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c2656
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.h27
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c95
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c71
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h59
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c23
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c83
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c21
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c47
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c79
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c180
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c38
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.h22
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c38
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h58
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c126
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c94
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c202
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c82
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c60
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c42
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/virtual.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c738
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h5
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h13
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h7
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c56
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c19
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c17
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.h24
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c80
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c5
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h6
-rw-r--r--drivers/net/wireless/ath/debug.c9
-rw-r--r--drivers/net/wireless/ath/debug.h2
-rw-r--r--drivers/net/wireless/ath/key.c9
87 files changed, 7984 insertions, 4473 deletions
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c
index 4604de09a8b2..6452c5055a63 100644
--- a/drivers/net/wireless/ath/ar9170/cmd.c
+++ b/drivers/net/wireless/ath/ar9170/cmd.c
@@ -54,7 +54,7 @@ int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len)
int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
{
- __le32 buf[2] = {
+ const __le32 buf[2] = {
cpu_to_le32(reg),
cpu_to_le32(val),
};
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 5dbb5361fd51..d3be6f9816b5 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -161,8 +161,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
{
struct sk_buff *skb = urb->context;
- struct ar9170_usb *aru = (struct ar9170_usb *)
- usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+ struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
if (unlikely(!aru)) {
dev_kfree_skb_irq(skb);
@@ -219,8 +218,7 @@ free:
static void ar9170_usb_rx_completed(struct urb *urb)
{
struct sk_buff *skb = urb->context;
- struct ar9170_usb *aru = (struct ar9170_usb *)
- usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+ struct ar9170_usb *aru = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
int err;
if (!aru)
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 501050c0296f..26bdbeee424f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -104,6 +104,11 @@ enum ath_cipher {
ATH_CIPHER_MIC = 127
};
+enum ath_drv_info {
+ AR7010_DEVICE = BIT(0),
+ AR9287_DEVICE = BIT(1),
+};
+
/**
* struct ath_ops - Register read/write operations
*
@@ -147,6 +152,7 @@ struct ath_common {
u8 rx_chainmask;
u32 rx_bufsize;
+ u32 driver_info;
u32 keymax;
DECLARE_BITMAP(keymap, ATH_KEYMAX);
@@ -162,6 +168,8 @@ struct ath_common {
struct ath_regulatory regulatory;
const struct ath_ops *ops;
const struct ath_bus_ops *bus_ops;
+
+ bool btcoex_enabled;
};
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index eb83b7b4d0e3..e0793319389d 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,9 +1,12 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
- depends on PCI && MAC80211
+ depends on (PCI || ATHEROS_AR231X) && MAC80211
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
+ select AVERAGE
+ select ATH5K_AHB if (ATHEROS_AR231X && !PCI)
+ select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
@@ -37,3 +40,16 @@ config ATH5K_DEBUG
modprobe ath5k debug=0x00000400
+config ATH5K_AHB
+ bool "Atheros 5xxx AHB bus support"
+ depends on (ATHEROS_AR231X && !PCI)
+ ---help---
+ This adds support for WiSoC type chipsets of the 5xxx Atheros
+ family.
+
+config ATH5K_PCI
+ bool "Atheros 5xxx PCI bus support"
+ depends on (!ATHEROS_AR231X && PCI)
+ ---help---
+ This adds support for PCI type chipsets of the 5xxx Atheros
+ family.
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 2242a140e4fe..67dd9fd0650e 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -15,4 +15,6 @@ ath5k-y += rfkill.o
ath5k-y += ani.o
ath5k-y += sysfs.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
+ath5k-$(CONFIG_ATH5K_AHB) += ahb.o
+ath5k-$(CONFIG_ATH5K_PCI) += pci.o
obj-$(CONFIG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
new file mode 100644
index 000000000000..707cde149248
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/platform_device.h>
+#include <ar231x_platform.h>
+#include "ath5k.h"
+#include "debug.h"
+#include "base.h"
+#include "reg.h"
+#include "debug.h"
+
+/* return bus cachesize in 4B word units */
+static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
+{
+ *csz = L1_CACHE_BYTES >> 2;
+}
+
+bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+{
+ struct ath5k_softc *sc = common->priv;
+ struct platform_device *pdev = to_platform_device(sc->dev);
+ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ u16 *eeprom, *eeprom_end;
+
+
+
+ bcfg = pdev->dev.platform_data;
+ eeprom = (u16 *) bcfg->radio;
+ eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
+
+ eeprom += off;
+ if (eeprom > eeprom_end)
+ return -EINVAL;
+
+ *data = *eeprom;
+ return 0;
+}
+
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct platform_device *pdev = to_platform_device(sc->dev);
+ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ ah->ah_mac_srev = bcfg->devid;
+ return 0;
+}
+
+static const struct ath_bus_ops ath_ahb_bus_ops = {
+ .ath_bus_type = ATH_AHB,
+ .read_cachesize = ath5k_ahb_read_cachesize,
+ .eeprom_read = ath5k_ahb_eeprom_read,
+};
+
+/*Initialization*/
+static int ath_ahb_probe(struct platform_device *pdev)
+{
+ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ath5k_softc *sc;
+ struct ieee80211_hw *hw;
+ struct resource *res;
+ void __iomem *mem;
+ int irq;
+ int ret = 0;
+ u32 reg;
+
+ if (!pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "no platform data specified\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no memory resource found\n");
+ ret = -ENXIO;
+ goto err_out;
+ }
+
+ mem = ioremap_nocache(res->start, res->end - res->start + 1);
+ if (mem == NULL) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no IRQ resource found\n");
+ ret = -ENXIO;
+ goto err_out;
+ }
+
+ irq = res->start;
+
+ hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops);
+ if (hw == NULL) {
+ dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ sc = hw->priv;
+ sc->hw = hw;
+ sc->dev = &pdev->dev;
+ sc->iobase = mem;
+ sc->irq = irq;
+ sc->devid = bcfg->devid;
+
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+ /* Enable WMAC AHB arbitration */
+ reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
+ __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+
+ /* Enable global WMAC swapping */
+ reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP);
+ reg |= AR5K_AR2315_BYTESWAP_WMAC;
+ __raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
+ } else {
+ /* Enable WMAC DMA access (assuming 5312 or 231x*/
+ /* TODO: check other platforms */
+ reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
+ if (to_platform_device(sc->dev)->id == 0)
+ reg |= AR5K_AR5312_ENABLE_WLAN0;
+ else
+ reg |= AR5K_AR5312_ENABLE_WLAN1;
+ __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+ }
+
+ ret = ath5k_init_softc(sc, &ath_ahb_bus_ops);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
+ ret = -ENODEV;
+ goto err_free_hw;
+ }
+
+ platform_set_drvdata(pdev, hw);
+
+ return 0;
+
+ err_free_hw:
+ ieee80211_free_hw(hw);
+ platform_set_drvdata(pdev, NULL);
+ err_out:
+ return ret;
+}
+
+static int ath_ahb_remove(struct platform_device *pdev)
+{
+ struct ar231x_board_config *bcfg = pdev->dev.platform_data;
+ struct ieee80211_hw *hw = platform_get_drvdata(pdev);
+ struct ath5k_softc *sc;
+ u32 reg;
+
+ if (!hw)
+ return 0;
+
+ sc = hw->priv;
+
+ if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
+ /* Disable WMAC AHB arbitration */
+ reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
+ __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
+ } else {
+ /*Stop DMA access */
+ reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE);
+ if (to_platform_device(sc->dev)->id == 0)
+ reg &= ~AR5K_AR5312_ENABLE_WLAN0;
+ else
+ reg &= ~AR5K_AR5312_ENABLE_WLAN1;
+ __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
+ }
+
+ ath5k_deinit_softc(sc);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver ath_ahb_driver = {
+ .probe = ath_ahb_probe,
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ar231x-wmac",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init
+ath5k_ahb_init(void)
+{
+ return platform_driver_register(&ath_ahb_driver);
+}
+
+static void __exit
+ath5k_ahb_exit(void)
+{
+ platform_driver_unregister(&ath_ahb_driver);
+}
+
+module_init(ath5k_ahb_init);
+module_exit(ath5k_ahb_exit);
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index f1419198a479..f915f404302d 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -58,20 +58,20 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
{
/* TODO:
* ANI documents suggest the following five levels to use, but the HAL
- * and ath9k use only use the last two levels, making this
+ * and ath9k use only the last two levels, making this
* essentially an on/off option. There *may* be a reason for this (???),
* so i stick with the HAL version for now...
*/
#if 0
- const s8 hi[] = { -18, -18, -16, -14, -12 };
- const s8 lo[] = { -52, -56, -60, -64, -70 };
- const s8 sz[] = { -34, -41, -48, -55, -62 };
- const s8 fr[] = { -70, -72, -75, -78, -80 };
+ static const s8 lo[] = { -52, -56, -60, -64, -70 };
+ static const s8 hi[] = { -18, -18, -16, -14, -12 };
+ static const s8 sz[] = { -34, -41, -48, -55, -62 };
+ static const s8 fr[] = { -70, -72, -75, -78, -80 };
#else
- const s8 sz[] = { -55, -62 };
- const s8 lo[] = { -64, -70 };
- const s8 hi[] = { -14, -12 };
- const s8 fr[] = { -78, -80 };
+ static const s8 lo[] = { -64, -70 };
+ static const s8 hi[] = { -14, -12 };
+ static const s8 sz[] = { -55, -62 };
+ static const s8 fr[] = { -78, -80 };
#endif
if (level < 0 || level >= ARRAY_SIZE(sz)) {
ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range",
@@ -102,7 +102,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
void
ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
{
- const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
+ static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
if (level < 0 || level >= ARRAY_SIZE(val) ||
level > ah->ah_sc->ani_state.max_spur_level) {
@@ -127,7 +127,7 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
void
ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
{
- const int val[] = { 0, 4, 8 };
+ static const int val[] = { 0, 4, 8 };
if (level < 0 || level >= ARRAY_SIZE(val)) {
ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level);
@@ -151,12 +151,12 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
void
ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
{
- const int m1l[] = { 127, 50 };
- const int m2l[] = { 127, 40 };
- const int m1[] = { 127, 0x4d };
- const int m2[] = { 127, 0x40 };
- const int m2cnt[] = { 31, 16 };
- const int m2lcnt[] = { 63, 48 };
+ static const int m1l[] = { 127, 50 };
+ static const int m2l[] = { 127, 40 };
+ static const int m1[] = { 127, 0x4d };
+ static const int m2[] = { 127, 0x40 };
+ static const int m2cnt[] = { 31, 16 };
+ static const int m2lcnt[] = { 63, 48 };
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR,
AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]);
@@ -192,7 +192,7 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
void
ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
{
- const int val[] = { 8, 6 };
+ static const int val[] = { 8, 6 };
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR,
AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]);
ah->ah_sc->ani_state.cck_weak_sig = on;
@@ -216,7 +216,7 @@ static void
ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
bool ofdm_trigger)
{
- int rssi = ah->ah_beacon_rssi_avg.avg;
+ int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)",
ofdm_trigger ? "ODFM" : "CCK");
@@ -301,7 +301,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
static void
ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
{
- int rssi = ah->ah_beacon_rssi_avg.avg;
+ int rssi = ewma_read(&ah->ah_beacon_rssi_avg);
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity");
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 308b79e1ff08..d6e744088bc6 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -25,6 +25,7 @@
#include <linux/io.h>
#include <linux/types.h>
+#include <linux/average.h>
#include <net/mac80211.h>
/* RX/TX descriptor hw structs
@@ -157,15 +158,6 @@
#define AR5K_INI_RFGAIN_5GHZ 0
#define AR5K_INI_RFGAIN_2GHZ 1
-/* TODO: Clean this up */
-#define AR5K_INI_VAL_11A 0
-#define AR5K_INI_VAL_11A_TURBO 1
-#define AR5K_INI_VAL_11B 2
-#define AR5K_INI_VAL_11G 3
-#define AR5K_INI_VAL_11G_TURBO 4
-#define AR5K_INI_VAL_XR 0
-#define AR5K_INI_VAL_MAX 5
-
/*
* Some tuneable values (these should be changeable by the user)
* TODO: Make use of them and add more options OR use debug/configfs
@@ -221,42 +213,66 @@
/* Initial values */
#define AR5K_INIT_CYCRSSI_THR1 2
-#define AR5K_INIT_TX_LATENCY 502
-#define AR5K_INIT_USEC 39
-#define AR5K_INIT_USEC_TURBO 79
-#define AR5K_INIT_USEC_32 31
-#define AR5K_INIT_SLOT_TIME 396
-#define AR5K_INIT_SLOT_TIME_TURBO 480
-#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
-#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
-#define AR5K_INIT_PROG_IFS 920
-#define AR5K_INIT_PROG_IFS_TURBO 960
-#define AR5K_INIT_EIFS 3440
-#define AR5K_INIT_EIFS_TURBO 6880
-#define AR5K_INIT_SIFS 560
-#define AR5K_INIT_SIFS_TURBO 480
+
+/* Tx retry limits */
#define AR5K_INIT_SH_RETRY 10
#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+/* For station mode */
#define AR5K_INIT_SSH_RETRY 32
#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
#define AR5K_INIT_TX_RETRY 10
-#define AR5K_INIT_TRANSMIT_LATENCY ( \
- (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
- (AR5K_INIT_USEC) \
-)
-#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
- (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
- (AR5K_INIT_USEC_TURBO) \
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
- (AR5K_INIT_PROG_IFS) \
-)
-#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
- (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
- (AR5K_INIT_PROG_IFS_TURBO) \
-)
+
+/* Slot time */
+#define AR5K_INIT_SLOT_TIME_TURBO 6
+#define AR5K_INIT_SLOT_TIME_DEFAULT 9
+#define AR5K_INIT_SLOT_TIME_HALF_RATE 13
+#define AR5K_INIT_SLOT_TIME_QUARTER_RATE 21
+#define AR5K_INIT_SLOT_TIME_B 20
+#define AR5K_SLOT_TIME_MAX 0xffff
+
+/* SIFS */
+#define AR5K_INIT_SIFS_TURBO 6
+/* XXX: 8 from initvals 10 from standard */
+#define AR5K_INIT_SIFS_DEFAULT_BG 8
+#define AR5K_INIT_SIFS_DEFAULT_A 16
+#define AR5K_INIT_SIFS_HALF_RATE 32
+#define AR5K_INIT_SIFS_QUARTER_RATE 64
+
+/* Used to calculate tx time for non 5/10/40MHz
+ * operation */
+/* It's preamble time + signal time (16 + 4) */
+#define AR5K_INIT_OFDM_PREAMPLE_TIME 20
+/* Preamble time for 40MHz (turbo) operation (min ?) */
+#define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14
+#define AR5K_INIT_OFDM_SYMBOL_TIME 4
+#define AR5K_INIT_OFDM_PLCP_BITS 22
+
+/* Rx latency for 5 and 10MHz operation (max ?) */
+#define AR5K_INIT_RX_LAT_MAX 63
+/* Tx latencies from initvals (5212 only but no problem
+ * because we only tweak them on 5212) */
+#define AR5K_INIT_TX_LAT_A 54
+#define AR5K_INIT_TX_LAT_BG 384
+/* Tx latency for 40MHz (turbo) operation (min ?) */
+#define AR5K_INIT_TX_LAT_MIN 32
+/* Default Tx/Rx latencies (same for 5211)*/
+#define AR5K_INIT_TX_LATENCY_5210 54
+#define AR5K_INIT_RX_LATENCY_5210 29
+
+/* Tx frame to Tx data start delay */
+#define AR5K_INIT_TXF2TXD_START_DEFAULT 14
+#define AR5K_INIT_TXF2TXD_START_DELAY_10MHZ 12
+#define AR5K_INIT_TXF2TXD_START_DELAY_5MHZ 13
+
+/* We need to increase PHY switch and agc settling time
+ * on turbo mode */
+#define AR5K_SWITCH_SETTLING 5760
+#define AR5K_SWITCH_SETTLING_TURBO 7168
+
+#define AR5K_AGC_SETTLING 28
+/* 38 on 5210 but shouldn't matter */
+#define AR5K_AGC_SETTLING_TURBO 37
/* GENERIC CHIPSET DEFINITIONS */
@@ -303,12 +319,19 @@ struct ath5k_srev_name {
#define AR5K_SREV_AR5311B 0x30 /* Spirit */
#define AR5K_SREV_AR5211 0x40 /* Oahu */
#define AR5K_SREV_AR5212 0x50 /* Venice */
+#define AR5K_SREV_AR5312_R2 0x52 /* AP31 */
#define AR5K_SREV_AR5212_V4 0x54 /* ??? */
#define AR5K_SREV_AR5213 0x55 /* ??? */
+#define AR5K_SREV_AR5312_R7 0x57 /* AP30 */
+#define AR5K_SREV_AR2313_R8 0x58 /* AP43 */
#define AR5K_SREV_AR5213A 0x59 /* Hainan */
#define AR5K_SREV_AR2413 0x78 /* Griffin lite */
#define AR5K_SREV_AR2414 0x70 /* Griffin */
+#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */
+#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */
#define AR5K_SREV_AR5424 0x90 /* Condor */
+#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */
+#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */
#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
#define AR5K_SREV_AR5414 0xa0 /* Eagle */
#define AR5K_SREV_AR2415 0xb0 /* Talon */
@@ -404,12 +427,10 @@ struct ath5k_srev_name {
enum ath5k_driver_mode {
AR5K_MODE_11A = 0,
- AR5K_MODE_11A_TURBO = 1,
- AR5K_MODE_11B = 2,
- AR5K_MODE_11G = 3,
- AR5K_MODE_11G_TURBO = 4,
+ AR5K_MODE_11B = 1,
+ AR5K_MODE_11G = 2,
AR5K_MODE_XR = 0,
- AR5K_MODE_MAX = 5
+ AR5K_MODE_MAX = 3
};
enum ath5k_ant_mode {
@@ -423,6 +444,12 @@ enum ath5k_ant_mode {
AR5K_ANTMODE_MAX,
};
+enum ath5k_bw_mode {
+ AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */
+ AR5K_BWMODE_5MHZ = 1, /* Quarter rate */
+ AR5K_BWMODE_10MHZ = 2, /* Half rate */
+ AR5K_BWMODE_40MHZ = 3 /* Turbo */
+};
/****************\
TX DEFINITIONS
@@ -655,7 +682,6 @@ struct ath5k_gain {
/* channel_flags */
#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
-#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
#define CHANNEL_CCK 0x0020 /* CCK channel */
#define CHANNEL_OFDM 0x0040 /* OFDM channel */
#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
@@ -667,16 +693,10 @@ struct ath5k_gain {
#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
-#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
-#define CHANNEL_108A CHANNEL_T
-#define CHANNEL_108G CHANNEL_TG
#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
-#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
- CHANNEL_TURBO)
+#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ)
-#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
#define CHANNEL_MODES CHANNEL_ALL
/*
@@ -1025,7 +1045,6 @@ struct ath5k_hw {
enum ath5k_int ah_imr;
struct ieee80211_channel *ah_current_channel;
- bool ah_turbo;
bool ah_calibration;
bool ah_single_chip;
@@ -1034,6 +1053,7 @@ struct ath5k_hw {
u32 ah_phy;
u32 ah_mac_srev;
u16 ah_mac_version;
+ u16 ah_mac_revision;
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
@@ -1043,6 +1063,8 @@ struct ath5k_hw {
u32 ah_limit_tx_retries;
u8 ah_coverage_class;
+ bool ah_ack_bitrate_high;
+ u8 ah_bwmode;
/* Antenna Control */
u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
@@ -1102,7 +1124,7 @@ struct ath5k_hw {
struct ath5k_nfcal_hist ah_nfcal_hist;
/* average beacon RSSI in our BSS (used by ANI) */
- struct ath5k_avg_val ah_beacon_rssi_avg;
+ struct ewma ah_beacon_rssi_avg;
/* noise floor from last periodic calibration */
s32 ah_noise_floor;
@@ -1131,36 +1153,50 @@ struct ath5k_hw {
/*
* Prototypes
*/
+extern const struct ieee80211_ops ath5k_hw_ops;
-/* Attach/Detach Functions */
-int ath5k_hw_attach(struct ath5k_softc *sc);
-void ath5k_hw_detach(struct ath5k_hw *ah);
+/* Initialization and detach functions */
+int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops);
+void ath5k_deinit_softc(struct ath5k_softc *sc);
+int ath5k_hw_init(struct ath5k_softc *sc);
+void ath5k_hw_deinit(struct ath5k_hw *ah);
int ath5k_sysfs_register(struct ath5k_softc *sc);
void ath5k_sysfs_unregister(struct ath5k_softc *sc);
+/*Chip id helper functions */
+const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
+int ath5k_hw_read_srev(struct ath5k_hw *ah);
+
/* LED functions */
int ath5k_init_leds(struct ath5k_softc *sc);
void ath5k_led_enable(struct ath5k_softc *sc);
void ath5k_led_off(struct ath5k_softc *sc);
void ath5k_unregister_leds(struct ath5k_softc *sc);
+
/* Reset Functions */
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
int ath5k_hw_on_hold(struct ath5k_hw *ah);
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
- struct ieee80211_channel *channel, bool change_channel);
+ struct ieee80211_channel *channel, bool fast, bool skip_pcu);
int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
bool is_set);
/* Power management functions */
+
+/* Clock rate related functions */
+unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
+unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
+void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
+
+
/* DMA Related Functions */
void ath5k_hw_start_rx_dma(struct ath5k_hw *ah);
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah);
-void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
+int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr);
int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue);
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue);
u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue);
int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue,
u32 phys_addr);
@@ -1170,38 +1206,43 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask);
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah);
+/* Init/Stop functions */
+void ath5k_hw_dma_init(struct ath5k_hw *ah);
+int ath5k_hw_dma_stop(struct ath5k_hw *ah);
/* EEPROM access functions */
int ath5k_eeprom_init(struct ath5k_hw *ah);
void ath5k_eeprom_detach(struct ath5k_hw *ah);
int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac);
+
/* Protocol Control Unit Functions */
+/* Helpers */
+int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+ int len, struct ieee80211_rate *rate);
+unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
+unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
-/* BSSID Functions */
+/* RX filter control*/
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
void ath5k_hw_set_bssid(struct ath5k_hw *ah);
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
-/* Receive start/stop functions */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
-void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
-/* RX Filter functions */
void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* Receive (DRU) start/stop functions */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
/* Beacon control functions */
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
-/* ACK bit rate */
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
-/* Clock rate related functions */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
-void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
+/* Init function */
+void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ u8 mode);
/* Queue Control Unit, DFS Control Unit Functions */
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
@@ -1214,7 +1255,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time);
+/* Init function */
+int ath5k_hw_init_queues(struct ath5k_hw *ah);
/* Hardware Descriptor Functions */
int ath5k_hw_init_desc_functions(struct ath5k_hw *ah);
@@ -1224,6 +1267,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2,
u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3);
+
/* GPIO Functions */
void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
@@ -1233,11 +1277,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
u32 interrupt_level);
-/* rfkill Functions */
+
+/* RFkill Functions */
void ath5k_rfkill_hw_start(struct ath5k_hw *ah);
void ath5k_rfkill_hw_stop(struct ath5k_hw *ah);
-/* Misc functions */
+
+/* Misc functions TODO: Cleanup */
int ath5k_hw_set_capabilities(struct ath5k_hw *ah);
int ath5k_hw_get_capability(struct ath5k_hw *ah,
enum ath5k_capability_type cap_type, u32 capability,
@@ -1245,19 +1291,20 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah,
int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id);
int ath5k_hw_disable_pspoll(struct ath5k_hw *ah);
+
/* Initial register settings functions */
int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
-/* Initialize RF */
-int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
- struct ieee80211_channel *channel,
- unsigned int mode);
-int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq);
+
+/* PHY functions */
+/* Misc PHY functions */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* Gain_F optimization */
enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
/* PHY/RF channel functions */
bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
-int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
/* PHY calibration */
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
@@ -1266,18 +1313,14 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah);
/* Spur mitigation */
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
struct ieee80211_channel *channel);
-void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
- struct ieee80211_channel *channel);
-/* Misc PHY functions */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
-int ath5k_hw_phy_disable(struct ath5k_hw *ah);
/* Antenna control */
void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode);
void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode);
/* TX power setup */
-int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
- u8 ee_mode, u8 txpower);
int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower);
+/* Init function */
+int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ u8 mode, u8 ee_mode, u8 freq, bool fast);
/*
* Functions used internaly
@@ -1293,6 +1336,32 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
return &(ath5k_hw_common(ah)->regulatory);
}
+#ifdef CONFIG_ATHEROS_AR231X
+#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)
+
+static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
+{
+ /* On AR2315 and AR2317 the PCI clock domain registers
+ * are outside of the WMAC register space */
+ if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
+ (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
+ return AR5K_AR2315_PCI_BASE + reg;
+
+ return ah->ah_iobase + reg;
+}
+
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+ return __raw_readl(ath5k_ahb_reg(ah, reg));
+}
+
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+ __raw_writel(val, ath5k_ahb_reg(ah, reg));
+}
+
+#else
+
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
return ioread32(ah->ah_iobase + reg);
@@ -1303,6 +1372,24 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
iowrite32(val, ah->ah_iobase + reg);
}
+#endif
+
+static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
+{
+ return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
+}
+
+static inline void ath5k_read_cachesize(struct ath_common *common, int *csz)
+{
+ common->bus_ops->read_cachesize(common, csz);
+}
+
+static inline bool ath5k_hw_nvram_read(struct ath5k_hw *ah, u32 off, u16 *data)
+{
+ struct ath_common *common = ath5k_hw_common(ah);
+ return common->bus_ops->eeprom_read(common, off, data);
+}
+
static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
{
u32 retval = 0, bit, i;
@@ -1315,27 +1402,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
return retval;
}
-#define AVG_SAMPLES 8
-#define AVG_FACTOR 1000
-
-/**
- * ath5k_moving_average - Exponentially weighted moving average
- * @avg: average structure
- * @val: current value
- *
- * This implementation make use of a struct ath5k_avg_val to prevent rounding
- * errors.
- */
-static inline struct ath5k_avg_val
-ath5k_moving_average(const struct ath5k_avg_val avg, const int val)
-{
- struct ath5k_avg_val new;
- new.avg_weight = avg.avg_weight ?
- (((avg.avg_weight * ((AVG_SAMPLES) - 1)) +
- (val * (AVG_FACTOR))) / (AVG_SAMPLES)) :
- (val * (AVG_FACTOR));
- new.avg = new.avg_weight / (AVG_FACTOR);
- return new;
-}
-
#endif
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index fbe8aca975d8..9dbc1fa81795 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -93,16 +93,16 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
}
/**
- * ath5k_hw_attach - Check if hw is supported and init the needed structs
+ * ath5k_hw_init - Check if hw is supported and init the needed structs
*
- * @sc: The &struct ath5k_softc we got from the driver's attach function
+ * @sc: The &struct ath5k_softc we got from the driver's init_softc function
*
* Check if the device is supported, perform a POST and initialize the needed
* structs. Returns -ENOMEM if we don't have memory for the needed structs,
* -ENODEV if the device is not supported or prints an error msg if something
* else went wrong.
*/
-int ath5k_hw_attach(struct ath5k_softc *sc)
+int ath5k_hw_init(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
@@ -115,7 +115,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
* HW information
*/
ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
- ah->ah_turbo = false;
+ ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
ah->ah_imr = 0;
ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
@@ -128,7 +128,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
/*
* Find the mac version
*/
- srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ ath5k_hw_read_srev(ah);
+ srev = ah->ah_mac_srev;
if (srev < AR5K_SREV_AR5311)
ah->ah_version = AR5K_AR5210;
else if (srev < AR5K_SREV_AR5212)
@@ -136,6 +137,10 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
else
ah->ah_version = AR5K_AR5212;
+ /* Get the MAC revision */
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+
/* Fill the ath5k_hw struct with the needed functions */
ret = ath5k_hw_init_desc_functions(ah);
if (ret)
@@ -146,9 +151,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
if (ret)
goto err;
- /* Get MAC, PHY and RADIO revisions */
- ah->ah_mac_srev = srev;
- ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ /* Get PHY and RADIO revisions */
ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
0xffffffff;
ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
@@ -273,7 +276,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
/*
* Write PCI-E power save settings
*/
- if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
+ if ((ah->ah_version == AR5K_AR5212) && pdev && (pdev->is_pcie)) {
ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
@@ -305,8 +308,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
/* Get misc capabilities */
ret = ath5k_hw_set_capabilities(ah);
if (ret) {
- ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
- sc->pdev->device);
+ ATH5K_ERR(sc, "unable to get device capabilities\n");
goto err;
}
@@ -346,11 +348,11 @@ err:
}
/**
- * ath5k_hw_detach - Free the ath5k_hw struct
+ * ath5k_hw_deinit - Free the ath5k_hw struct
*
* @ah: The &struct ath5k_hw
*/
-void ath5k_hw_detach(struct ath5k_hw *ah)
+void ath5k_hw_deinit(struct ath5k_hw *ah)
{
__set_bit(ATH_STAT_INVALID, ah->ah_sc->status);
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 8251946842e6..0a7071a6dd7a 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -47,8 +47,6 @@
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/cache.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
#include <linux/ethtool.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
@@ -80,37 +78,24 @@ MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("0.6.0 (EXPERIMENTAL)");
-static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+static int ath5k_init(struct ieee80211_hw *hw);
+static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ bool skip_pcu);
static int ath5k_beacon_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-/* Known PCI ids */
-static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
- { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
- { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
- { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
- { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
- { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
- { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
- { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
- { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
- { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
- { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
- { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
- { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
- { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
-
/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
+#ifdef CONFIG_ATHEROS_AR231X
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
+ { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
+ { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 },
+ { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 },
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 },
+ { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 },
+#else
{ "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
{ "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
{ "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
@@ -129,6 +114,7 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
{ "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
{ "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
+#endif
{ "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
@@ -142,10 +128,12 @@ static const struct ath5k_srev_name srev_names[] = {
{ "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B },
{ "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 },
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
- { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
- { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+#ifdef CONFIG_ATHEROS_AR231X
+ { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
+ { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
+#endif
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
};
@@ -197,8 +185,8 @@ static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc,
BUG_ON(!bf);
if (!bf->skb)
return;
- pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
- PCI_DMA_TODEVICE);
+ dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
+ DMA_TO_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
bf->skbaddr = 0;
@@ -214,8 +202,8 @@ static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc,
BUG_ON(!bf);
if (!bf->skb)
return;
- pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
- PCI_DMA_FROMDEVICE);
+ dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
+ DMA_FROM_DEVICE);
dev_kfree_skb_any(bf->skb);
bf->skb = NULL;
bf->skbaddr = 0;
@@ -233,7 +221,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
return (tsf & ~0x7fff) | rstamp;
}
-static const char *
+const char *
ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
{
const char *name = "xxxxx";
@@ -327,14 +315,12 @@ ath5k_copy_channels(struct ath5k_hw *ah,
switch (mode) {
case AR5K_MODE_11A:
- case AR5K_MODE_11A_TURBO:
/* 1..220, but 2GHz frequencies are filtered by check_channel */
size = 220 ;
chfreq = CHANNEL_5GHZ;
break;
case AR5K_MODE_11B:
case AR5K_MODE_11G:
- case AR5K_MODE_11G_TURBO:
size = 26;
chfreq = CHANNEL_2GHZ;
break;
@@ -363,11 +349,6 @@ ath5k_copy_channels(struct ath5k_hw *ah,
case AR5K_MODE_11G:
channels[count].hw_value = chfreq | CHANNEL_OFDM;
break;
- case AR5K_MODE_11A_TURBO:
- case AR5K_MODE_11G_TURBO:
- channels[count].hw_value = chfreq |
- CHANNEL_OFDM | CHANNEL_TURBO;
- break;
case AR5K_MODE_11B:
channels[count].hw_value = CHANNEL_B;
}
@@ -496,7 +477,7 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- return ath5k_reset(sc, chan);
+ return ath5k_reset(sc, chan, true);
}
static void
@@ -549,7 +530,7 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
/* Calculate combined mode - when APs are active, operate in AP mode.
* Otherwise use the mode of the new interface. This can currently
* only deal with combinations of APs and STAs. Only one ad-hoc
- * interfaces is allowed above.
+ * interfaces is allowed.
*/
if (avf->opmode == NL80211_IFTYPE_AP)
iter_data->opmode = NL80211_IFTYPE_AP;
@@ -558,16 +539,8 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
iter_data->opmode = avf->opmode;
}
-static void ath_do_set_opmode(struct ath5k_softc *sc)
-{
- struct ath5k_hw *ah = sc->ah;
- ath5k_hw_set_opmode(ah, sc->opmode);
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
- sc->opmode, ath_opmode_to_string(sc->opmode));
-}
-
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
- struct ieee80211_vif *vif)
+static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+ struct ieee80211_vif *vif)
{
struct ath_common *common = ath5k_hw_common(sc->ah);
struct ath_vif_iter_data iter_data;
@@ -595,7 +568,9 @@ void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
/* Nothing active, default to station mode */
sc->opmode = NL80211_IFTYPE_STATION;
- ath_do_set_opmode(sc);
+ ath5k_hw_set_opmode(sc->ah, sc->opmode);
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n",
+ sc->opmode, ath_opmode_to_string(sc->opmode));
if (iter_data.need_set_hw_addr && iter_data.found_active)
ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac);
@@ -659,10 +634,11 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
return NULL;
}
- *skb_addr = pci_map_single(sc->pdev,
+ *skb_addr = dma_map_single(sc->dev,
skb->data, common->rx_bufsize,
- PCI_DMA_FROMDEVICE);
- if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
+ DMA_FROM_DEVICE);
+
+ if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) {
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
dev_kfree_skb(skb);
return NULL;
@@ -758,8 +734,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
/* XXX endianness */
- bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
+ bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
rate = ieee80211_get_tx_rate(sc->hw, info);
if (!rate) {
@@ -839,7 +815,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
return 0;
err_unmap:
- pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -848,7 +824,7 @@ err_unmap:
\*******************/
static int
-ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
+ath5k_desc_alloc(struct ath5k_softc *sc)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
@@ -859,7 +835,9 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
/* allocate descriptors */
sc->desc_len = sizeof(struct ath5k_desc) *
(ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
- sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
+
+ sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len,
+ &sc->desc_daddr, GFP_KERNEL);
if (sc->desc == NULL) {
ATH5K_ERR(sc, "can't allocate descriptors\n");
ret = -ENOMEM;
@@ -905,14 +883,14 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
return 0;
err_free:
- pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+ dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
err:
sc->desc = NULL;
return ret;
}
static void
-ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
+ath5k_desc_free(struct ath5k_softc *sc)
{
struct ath5k_buf *bf;
@@ -924,7 +902,7 @@ ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
ath5k_txbuf_free_skb(sc, bf);
/* Free memory associated with all descriptors */
- pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+ dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr);
sc->desc = NULL;
sc->desc_daddr = 0;
@@ -1069,62 +1047,44 @@ err:
return ret;
}
+/**
+ * ath5k_drain_tx_buffs - Empty tx buffers
+ *
+ * @sc The &struct ath5k_softc
+ *
+ * Empty tx buffers from all queues in preparation
+ * of a reset or during shutdown.
+ *
+ * NB: this assumes output has been stopped and
+ * we do not need to block ath5k_tx_tasklet
+ */
static void
-ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+ath5k_drain_tx_buffs(struct ath5k_softc *sc)
{
+ struct ath5k_txq *txq;
struct ath5k_buf *bf, *bf0;
+ int i;
- /*
- * NB: this assumes output has been stopped and
- * we do not need to block ath5k_tx_tasklet
- */
- spin_lock_bh(&txq->lock);
- list_for_each_entry_safe(bf, bf0, &txq->q, list) {
- ath5k_debug_printtxbuf(sc, bf);
-
- ath5k_txbuf_free_skb(sc, bf);
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {
+ if (sc->txqs[i].setup) {
+ txq = &sc->txqs[i];
+ spin_lock_bh(&txq->lock);
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ath5k_debug_printtxbuf(sc, bf);
- spin_lock_bh(&sc->txbuflock);
- list_move_tail(&bf->list, &sc->txbuf);
- sc->txbuf_len++;
- txq->txq_len--;
- spin_unlock_bh(&sc->txbuflock);
- }
- txq->link = NULL;
- txq->txq_poll_mark = false;
- spin_unlock_bh(&txq->lock);
-}
+ ath5k_txbuf_free_skb(sc, bf);
-/*
- * Drain the transmit queues and reclaim resources.
- */
-static void
-ath5k_txq_cleanup(struct ath5k_softc *sc)
-{
- struct ath5k_hw *ah = sc->ah;
- unsigned int i;
-
- /* XXX return value */
- if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
- /* don't touch the hardware if marked invalid */
- ath5k_hw_stop_tx_dma(ah, sc->bhalq);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
- ath5k_hw_get_txdp(ah, sc->bhalq));
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
- if (sc->txqs[i].setup) {
- ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
- "link %p\n",
- sc->txqs[i].qnum,
- ath5k_hw_get_txdp(ah,
- sc->txqs[i].qnum),
- sc->txqs[i].link);
+ spin_lock_bh(&sc->txbuflock);
+ list_move_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ txq->txq_len--;
+ spin_unlock_bh(&sc->txbuflock);
}
+ txq->link = NULL;
+ txq->txq_poll_mark = false;
+ spin_unlock_bh(&txq->lock);
+ }
}
-
- for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
- if (sc->txqs[i].setup)
- ath5k_txq_drainq(sc, &sc->txqs[i]);
}
static void
@@ -1184,16 +1144,19 @@ err:
}
/*
- * Disable the receive h/w in preparation for a reset.
+ * Disable the receive logic on PCU (DRU)
+ * In preparation for a shutdown.
+ *
+ * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop
+ * does.
*/
static void
ath5k_rx_stop(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
- ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
- ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
+ ath5k_hw_stop_rx_pcu(ah); /* disable PCU */
ath5k_debug_printrxbuffs(sc, ah);
}
@@ -1307,8 +1270,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)
memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0)
return;
- ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg,
- rssi);
+ ewma_add(&ah->ah_beacon_rssi_avg, rssi);
/* in IBSS mode we should keep RSSI statistics per neighbour */
/* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */
@@ -1551,9 +1513,9 @@ ath5k_tasklet_rx(unsigned long data)
if (!next_skb)
goto next;
- pci_unmap_single(sc->pdev, bf->skbaddr,
+ dma_unmap_single(sc->dev, bf->skbaddr,
common->rx_bufsize,
- PCI_DMA_FROMDEVICE);
+ DMA_FROM_DEVICE);
skb_put(skb, rs.rs_datalen);
@@ -1716,8 +1678,9 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
skb = bf->skb;
bf->skb = NULL;
- pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
- PCI_DMA_TODEVICE);
+
+ dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
+ DMA_TO_DEVICE);
ath5k_tx_frame_completed(sc, skb, &ts);
}
@@ -1771,12 +1734,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
u32 flags;
const int padsize = 0;
- bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
- PCI_DMA_TODEVICE);
+ bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len,
+ DMA_TO_DEVICE);
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
"skbaddr %llx\n", skb, skb->data, skb->len,
(unsigned long long)bf->skbaddr);
- if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) {
+
+ if (dma_mapping_error(sc->dev, bf->skbaddr)) {
ATH5K_ERR(sc, "beacon DMA mapping failed\n");
return -EIO;
}
@@ -1828,7 +1792,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
return 0;
err_unmap:
- pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+ dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE);
return ret;
}
@@ -1944,7 +1908,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* This should never fail since we check above that no frames
* are still pending on the queue.
*/
- if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
+ if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) {
ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq);
/* NB: hw still stops DMA, so proceed */
}
@@ -2113,7 +2077,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
} else
ath5k_beacon_update_timers(sc, -1);
} else {
- ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
+ ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq);
}
ath5k_hw_set_imr(ah, sc->imask);
@@ -2175,7 +2139,7 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
* AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
}
-static irqreturn_t
+irqreturn_t
ath5k_intr(int irq, void *dev_id)
{
struct ath5k_softc *sc = dev_id;
@@ -2184,7 +2148,8 @@ ath5k_intr(int irq, void *dev_id)
unsigned int counter = 1000;
if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
- !ath5k_hw_is_intr_pending(ah)))
+ ((ath5k_get_bus_type(ah) != ATH_AHB) &&
+ !ath5k_hw_is_intr_pending(ah))))
return IRQ_NONE;
do {
@@ -2250,6 +2215,10 @@ ath5k_intr(int irq, void *dev_id)
tasklet_schedule(&sc->rf_kill.toggleq);
}
+
+ if (ath5k_get_bus_type(ah) == ATH_AHB)
+ break;
+
} while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
if (unlikely(!counter))
@@ -2349,7 +2318,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
"TX queues stuck, resetting\n");
- ath5k_reset(sc, sc->curchan);
+ ath5k_reset(sc, NULL, true);
}
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
@@ -2361,6 +2330,158 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
* Initialization routines *
\*************************/
+int
+ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath_common *common;
+ int ret;
+ int csz;
+
+ /* Initialize driver private data */
+ SET_IEEE80211_DEV(hw, sc->dev);
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM;
+
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
+
+ hw->extra_tx_headroom = 2;
+ hw->channel_change_time = 5000;
+
+ /*
+ * Mark the device as detached to avoid processing
+ * interrupts until setup is complete.
+ */
+ __set_bit(ATH_STAT_INVALID, sc->status);
+
+ sc->opmode = NL80211_IFTYPE_STATION;
+ sc->bintval = 1000;
+ mutex_init(&sc->lock);
+ spin_lock_init(&sc->rxbuflock);
+ spin_lock_init(&sc->txbuflock);
+ spin_lock_init(&sc->block);
+
+
+ /* Setup interrupt handler */
+ ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+ if (ret) {
+ ATH5K_ERR(sc, "request_irq failed\n");
+ goto err;
+ }
+
+ /* If we passed the test, malloc an ath5k_hw struct */
+ sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+ if (!sc->ah) {
+ ret = -ENOMEM;
+ ATH5K_ERR(sc, "out of memory\n");
+ goto err_irq;
+ }
+
+ sc->ah->ah_sc = sc;
+ sc->ah->ah_iobase = sc->iobase;
+ common = ath5k_hw_common(sc->ah);
+ common->ops = &ath5k_common_ops;
+ common->bus_ops = bus_ops;
+ common->ah = sc->ah;
+ common->hw = hw;
+ common->priv = sc;
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ ath5k_read_cachesize(common, &csz);
+ common->cachelsz = csz << 2; /* convert to bytes */
+
+ spin_lock_init(&common->cc_lock);
+
+ /* Initialize device */
+ ret = ath5k_hw_init(sc);
+ if (ret)
+ goto err_free_ah;
+
+ /* set up multi-rate retry capabilities */
+ if (sc->ah->ah_version == AR5K_AR5212) {
+ hw->max_rates = 4;
+ hw->max_rate_tries = 11;
+ }
+
+ hw->vif_data_size = sizeof(struct ath5k_vif);
+
+ /* Finish private driver data initialization */
+ ret = ath5k_init(hw);
+ if (ret)
+ goto err_ah;
+
+ ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
+ sc->ah->ah_mac_srev,
+ sc->ah->ah_phy_revision);
+
+ if (!sc->ah->ah_single_chip) {
+ /* Single chip radio (!RF5111) */
+ if (sc->ah->ah_radio_5ghz_revision &&
+ !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+ if (!test_bit(AR5K_MODE_11A,
+ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* No 2GHz support (5110 and some
+ * 5Ghz only cards) -> report 5Ghz radio */
+ } else if (!test_bit(AR5K_MODE_11B,
+ sc->ah->ah_capabilities.cap_mode)) {
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ ATH5K_INFO(sc, "RF%s multiband radio found"
+ " (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+ /* Multi chip radio (RF5111 - RF2111) ->
+ * report both 2GHz/5GHz radios */
+ else if (sc->ah->ah_radio_5ghz_revision &&
+ sc->ah->ah_radio_2ghz_revision){
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,
+ sc->ah->ah_radio_2ghz_revision),
+ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+
+ ath5k_debug_init_device(sc);
+
+ /* ready to process interrupts */
+ __clear_bit(ATH_STAT_INVALID, sc->status);
+
+ return 0;
+err_ah:
+ ath5k_hw_deinit(sc->ah);
+err_free_ah:
+ kfree(sc->ah);
+err_irq:
+ free_irq(sc->irq, sc);
+err:
+ return ret;
+}
+
static int
ath5k_stop_locked(struct ath5k_softc *sc)
{
@@ -2389,11 +2510,10 @@ ath5k_stop_locked(struct ath5k_softc *sc)
if (!test_bit(ATH_STAT_INVALID, sc->status)) {
ath5k_led_off(sc);
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->pdev->irq);
- }
- ath5k_txq_cleanup(sc);
- if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+ synchronize_irq(sc->irq);
ath5k_rx_stop(sc);
+ ath5k_hw_dma_stop(ah);
+ ath5k_drain_tx_buffs(sc);
ath5k_hw_phy_disable(ah);
}
@@ -2401,7 +2521,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
}
static int
-ath5k_init(struct ath5k_softc *sc)
+ath5k_init_hw(struct ath5k_softc *sc)
{
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
@@ -2430,7 +2550,7 @@ ath5k_init(struct ath5k_softc *sc)
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
- ret = ath5k_reset(sc, NULL);
+ ret = ath5k_reset(sc, NULL, false);
if (ret)
goto done;
@@ -2443,7 +2563,9 @@ ath5k_init(struct ath5k_softc *sc)
for (i = 0; i < common->keymax; i++)
ath_hw_keyreset(common, (u16) i);
- ath5k_hw_set_ack_bitrate_high(ah, true);
+ /* Use higher rates for acks instead of base
+ * rate */
+ ah->ah_ack_bitrate_high = true;
for (i = 0; i < ARRAY_SIZE(sc->bslot); i++)
sc->bslot[i] = NULL;
@@ -2527,7 +2649,8 @@ ath5k_stop_hw(struct ath5k_softc *sc)
* This should be called with sc->lock.
*/
static int
-ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ bool skip_pcu)
{
struct ath5k_hw *ah = sc->ah;
int ret;
@@ -2535,17 +2658,17 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
ath5k_hw_set_imr(ah, 0);
- synchronize_irq(sc->pdev->irq);
+ synchronize_irq(sc->irq);
stop_tasklets(sc);
if (chan) {
- ath5k_txq_cleanup(sc);
- ath5k_rx_stop(sc);
+ ath5k_drain_tx_buffs(sc);
sc->curchan = chan;
sc->curband = &sc->sbands[chan->band];
}
- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL);
+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
+ skip_pcu);
if (ret) {
ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
goto err;
@@ -2562,6 +2685,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan)
ah->ah_cal_next_full = jiffies;
ah->ah_cal_next_ani = jiffies;
ah->ah_cal_next_nf = jiffies;
+ ewma_init(&ah->ah_beacon_rssi_avg, 1000, 8);
/*
* Change channels and update the h/w rate map if we're switching;
@@ -2590,13 +2714,14 @@ static void ath5k_reset_work(struct work_struct *work)
reset_work);
mutex_lock(&sc->lock);
- ath5k_reset(sc, sc->curchan);
+ ath5k_reset(sc, NULL, true);
mutex_unlock(&sc->lock);
}
static int
-ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+ath5k_init(struct ieee80211_hw *hw)
{
+
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
@@ -2604,7 +2729,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
u8 mac[ETH_ALEN] = {};
int ret;
- ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
/*
* Check if the MAC has multi-rate retry support.
@@ -2641,7 +2765,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
/*
* Allocate tx+rx descriptors and populate the lists.
*/
- ret = ath5k_desc_alloc(sc, pdev);
+ ret = ath5k_desc_alloc(sc);
if (ret) {
ATH5K_ERR(sc, "can't allocate descriptors\n");
goto err;
@@ -2705,8 +2829,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
ret = ath5k_eeprom_read_mac(ah, mac);
if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
- sc->pdev->device);
+ ATH5K_ERR(sc, "unable to read address from EEPROM\n");
goto err_queues;
}
@@ -2741,15 +2864,15 @@ err_queues:
err_bhal:
ath5k_hw_release_tx_queue(ah, sc->bhalq);
err_desc:
- ath5k_desc_free(sc, pdev);
+ ath5k_desc_free(sc);
err:
return ret;
}
-static void
-ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+void
+ath5k_deinit_softc(struct ath5k_softc *sc)
{
- struct ath5k_softc *sc = hw->priv;
+ struct ieee80211_hw *hw = sc->hw;
/*
* NB: the order of these is important:
@@ -2764,8 +2887,9 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
* XXX: ??? detach ath5k_hw ???
* Other than that, it's straightforward...
*/
+ ath5k_debug_finish_device(sc);
ieee80211_unregister_hw(hw);
- ath5k_desc_free(sc, pdev);
+ ath5k_desc_free(sc);
ath5k_txq_release(sc);
ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
ath5k_unregister_leds(sc);
@@ -2776,6 +2900,8 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
* returns because we'll get called back to reclaim node
* state and potentially want to use them.
*/
+ ath5k_hw_deinit(sc->ah);
+ free_irq(sc->irq, sc);
}
/********************\
@@ -2798,7 +2924,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
static int ath5k_start(struct ieee80211_hw *hw)
{
- return ath5k_init(hw->priv);
+ return ath5k_init_hw(hw->priv);
}
static void ath5k_stop(struct ieee80211_hw *hw)
@@ -3206,14 +3332,32 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
{
struct ath5k_softc *sc = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
+ struct ath_common *common = ath5k_hw_common(sc->ah);
+ struct ath_cycle_counters *cc = &common->cc_survey;
+ unsigned int div = common->clockrate * 1000;
- if (idx != 0)
+ if (idx != 0)
return -ENOENT;
survey->channel = conf->channel;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = sc->ah->ah_noise_floor;
+ spin_lock_bh(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ if (cc->cycles > 0) {
+ survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY |
+ SURVEY_INFO_CHANNEL_TIME_RX |
+ SURVEY_INFO_CHANNEL_TIME_TX;
+ survey->channel_time += cc->cycles / div;
+ survey->channel_time_busy += cc->rx_busy / div;
+ survey->channel_time_rx += cc->rx_frame / div;
+ survey->channel_time_tx += cc->tx_frame / div;
+ }
+ memset(cc, 0, sizeof(*cc));
+ spin_unlock_bh(&common->cc_lock);
+
return 0;
}
@@ -3395,7 +3539,37 @@ static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
return ret;
}
-static const struct ieee80211_ops ath5k_hw_ops = {
+static int ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ if (tx_ant == 1 && rx_ant == 1)
+ ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
+ else if (tx_ant == 2 && rx_ant == 2)
+ ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
+ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
+ ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
+ else
+ return -EINVAL;
+ return 0;
+}
+
+static int ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ switch (sc->ah->ah_ant_mode) {
+ case AR5K_ANTMODE_FIXED_A:
+ *tx_ant = 1; *rx_ant = 1; break;
+ case AR5K_ANTMODE_FIXED_B:
+ *tx_ant = 2; *rx_ant = 2; break;
+ case AR5K_ANTMODE_DEFAULT:
+ *tx_ant = 3; *rx_ant = 3; break;
+ }
+ return 0;
+}
+
+const struct ieee80211_ops ath5k_hw_ops = {
.tx = ath5k_tx,
.start = ath5k_start,
.stop = ath5k_stop,
@@ -3415,341 +3589,6 @@ static const struct ieee80211_ops ath5k_hw_ops = {
.sw_scan_start = ath5k_sw_scan_start,
.sw_scan_complete = ath5k_sw_scan_complete,
.set_coverage_class = ath5k_set_coverage_class,
+ .set_antenna = ath5k_set_antenna,
+ .get_antenna = ath5k_get_antenna,
};
-
-/********************\
-* PCI Initialization *
-\********************/
-
-static int __devinit
-ath5k_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- void __iomem *mem;
- struct ath5k_softc *sc;
- struct ath_common *common;
- struct ieee80211_hw *hw;
- int ret;
- u8 csz;
-
- /*
- * L0s needs to be disabled on all ath5k cards.
- *
- * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
- * by default in the future in 2.6.36) this will also mean both L1 and
- * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
- * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
- * though but cannot currently undue the effect of a blacklist, for
- * details you can read pcie_aspm_sanity_check() and see how it adjusts
- * the device link capability.
- *
- * It may be possible in the future to implement some PCI API to allow
- * drivers to override blacklists for pre 1.1 PCIe but for now it is
- * best to accept that both L0s and L1 will be disabled completely for
- * distributions shipping with CONFIG_PCIEASPM rather than having this
- * issue present. Motivation for adding this new API will be to help
- * with power consumption for some of these devices.
- */
- pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
-
- ret = pci_enable_device(pdev);
- if (ret) {
- dev_err(&pdev->dev, "can't enable device\n");
- goto err;
- }
-
- /* XXX 32-bit addressing only */
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret) {
- dev_err(&pdev->dev, "32-bit DMA not available\n");
- goto err_dis;
- }
-
- /*
- * Cache line size is used to size and align various
- * structures used to communicate with the hardware.
- */
- pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
- if (csz == 0) {
- /*
- * Linux 2.4.18 (at least) writes the cache line size
- * register as a 16-bit wide register which is wrong.
- * We must have this setup properly for rx buffer
- * DMA to work so force a reasonable value here if it
- * comes up zero.
- */
- csz = L1_CACHE_BYTES >> 2;
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
- }
- /*
- * The default setting of latency timer yields poor results,
- * set it to the value used by other systems. It may be worth
- * tweaking this setting more.
- */
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
-
- /* Enable bus mastering */
- pci_set_master(pdev);
-
- /*
- * Disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state.
- */
- pci_write_config_byte(pdev, 0x41, 0);
-
- ret = pci_request_region(pdev, 0, "ath5k");
- if (ret) {
- dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
- goto err_dis;
- }
-
- mem = pci_iomap(pdev, 0, 0);
- if (!mem) {
- dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
- ret = -EIO;
- goto err_reg;
- }
-
- /*
- * Allocate hw (mac80211 main struct)
- * and hw->priv (driver private data)
- */
- hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
- if (hw == NULL) {
- dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
- ret = -ENOMEM;
- goto err_map;
- }
-
- dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
-
- /* Initialize driver private data */
- SET_IEEE80211_DEV(hw, &pdev->dev);
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_SIGNAL_DBM;
-
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_MESH_POINT);
-
- hw->extra_tx_headroom = 2;
- hw->channel_change_time = 5000;
- sc = hw->priv;
- sc->hw = hw;
- sc->pdev = pdev;
-
- /*
- * Mark the device as detached to avoid processing
- * interrupts until setup is complete.
- */
- __set_bit(ATH_STAT_INVALID, sc->status);
-
- sc->iobase = mem; /* So we can unmap it on detach */
- sc->opmode = NL80211_IFTYPE_STATION;
- sc->bintval = 1000;
- mutex_init(&sc->lock);
- spin_lock_init(&sc->rxbuflock);
- spin_lock_init(&sc->txbuflock);
- spin_lock_init(&sc->block);
-
- /* Set private data */
- pci_set_drvdata(pdev, sc);
-
- /* Setup interrupt handler */
- ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
- if (ret) {
- ATH5K_ERR(sc, "request_irq failed\n");
- goto err_free;
- }
-
- /* If we passed the test, malloc an ath5k_hw struct */
- sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
- if (!sc->ah) {
- ret = -ENOMEM;
- ATH5K_ERR(sc, "out of memory\n");
- goto err_irq;
- }
-
- sc->ah->ah_sc = sc;
- sc->ah->ah_iobase = sc->iobase;
- common = ath5k_hw_common(sc->ah);
- common->ops = &ath5k_common_ops;
- common->ah = sc->ah;
- common->hw = hw;
- common->cachelsz = csz << 2; /* convert to bytes */
- spin_lock_init(&common->cc_lock);
-
- /* Initialize device */
- ret = ath5k_hw_attach(sc);
- if (ret) {
- goto err_free_ah;
- }
-
- /* set up multi-rate retry capabilities */
- if (sc->ah->ah_version == AR5K_AR5212) {
- hw->max_rates = 4;
- hw->max_rate_tries = 11;
- }
-
- hw->vif_data_size = sizeof(struct ath5k_vif);
-
- /* Finish private driver data initialization */
- ret = ath5k_attach(pdev, hw);
- if (ret)
- goto err_ah;
-
- ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev),
- sc->ah->ah_mac_srev,
- sc->ah->ah_phy_revision);
-
- if (!sc->ah->ah_single_chip) {
- /* Single chip radio (!RF5111) */
- if (sc->ah->ah_radio_5ghz_revision &&
- !sc->ah->ah_radio_2ghz_revision) {
- /* No 5GHz support -> report 2GHz radio */
- if (!test_bit(AR5K_MODE_11A,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- /* No 2GHz support (5110 and some
- * 5Ghz only cards) -> report 5Ghz radio */
- } else if (!test_bit(AR5K_MODE_11B,
- sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- /* Multiband radio */
- } else {
- ATH5K_INFO(sc, "RF%s multiband radio found"
- " (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- }
- }
- /* Multi chip radio (RF5111 - RF2111) ->
- * report both 2GHz/5GHz radios */
- else if (sc->ah->ah_radio_5ghz_revision &&
- sc->ah->ah_radio_2ghz_revision){
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
- ath5k_chip_name(AR5K_VERSION_RAD,
- sc->ah->ah_radio_2ghz_revision),
- sc->ah->ah_radio_2ghz_revision);
- }
- }
-
- ath5k_debug_init_device(sc);
-
- /* ready to process interrupts */
- __clear_bit(ATH_STAT_INVALID, sc->status);
-
- return 0;
-err_ah:
- ath5k_hw_detach(sc->ah);
-err_free_ah:
- kfree(sc->ah);
-err_irq:
- free_irq(pdev->irq, sc);
-err_free:
- ieee80211_free_hw(hw);
-err_map:
- pci_iounmap(pdev, mem);
-err_reg:
- pci_release_region(pdev, 0);
-err_dis:
- pci_disable_device(pdev);
-err:
- return ret;
-}
-
-static void __devexit
-ath5k_pci_remove(struct pci_dev *pdev)
-{
- struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
- ath5k_debug_finish_device(sc);
- ath5k_detach(pdev, sc->hw);
- ath5k_hw_detach(sc->ah);
- kfree(sc->ah);
- free_irq(pdev->irq, sc);
- pci_iounmap(pdev, sc->iobase);
- pci_release_region(pdev, 0);
- pci_disable_device(pdev);
- ieee80211_free_hw(sc->hw);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int ath5k_pci_suspend(struct device *dev)
-{
- struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
-
- ath5k_led_off(sc);
- return 0;
-}
-
-static int ath5k_pci_resume(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- struct ath5k_softc *sc = pci_get_drvdata(pdev);
-
- /*
- * Suspend/Resume resets the PCI configuration space, so we have to
- * re-disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state
- */
- pci_write_config_byte(pdev, 0x41, 0);
-
- ath5k_led_enable(sc);
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
-#define ATH5K_PM_OPS (&ath5k_pm_ops)
-#else
-#define ATH5K_PM_OPS NULL
-#endif /* CONFIG_PM_SLEEP */
-
-static struct pci_driver ath5k_pci_driver = {
- .name = KBUILD_MODNAME,
- .id_table = ath5k_pci_id_table,
- .probe = ath5k_pci_probe,
- .remove = __devexit_p(ath5k_pci_remove),
- .driver.pm = ATH5K_PM_OPS,
-};
-
-/*
- * Module init/exit functions
- */
-static int __init
-init_ath5k_pci(void)
-{
- int ret;
-
- ret = pci_register_driver(&ath5k_pci_driver);
- if (ret) {
- printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
- return ret;
- }
-
- return 0;
-}
-
-static void __exit
-exit_ath5k_pci(void)
-{
- pci_unregister_driver(&ath5k_pci_driver);
-}
-
-module_init(init_ath5k_pci);
-module_exit(exit_ath5k_pci);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 9a79773cdc2a..aa6c32aafb59 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -169,7 +169,10 @@ struct ath5k_vif {
/* Software Carrier, keeps track of the driver state
* associated with an instance of a device */
struct ath5k_softc {
- struct pci_dev *pdev; /* for dma mapping */
+ struct pci_dev *pdev;
+ struct device *dev; /* for dma mapping */
+ int irq;
+ u16 devid;
void __iomem *iobase; /* address of the device */
struct mutex lock; /* dev-level lock */
struct ieee80211_hw *hw; /* IEEE 802.11 common */
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index beae519aa735..31cad80e9b01 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -49,7 +49,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
/* Set supported modes */
__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
- __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
} else {
/*
* XXX The tranceiver supports frequencies from 4920 to 6100GHz
@@ -74,11 +73,6 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
/* Set supported modes */
__set_bit(AR5K_MODE_11A,
ah->ah_capabilities.cap_mode);
- __set_bit(AR5K_MODE_11A_TURBO,
- ah->ah_capabilities.cap_mode);
- if (ah->ah_version == AR5K_AR5212)
- __set_bit(AR5K_MODE_11G_TURBO,
- ah->ah_capabilities.cap_mode);
}
/* Enable 802.11b if a 2GHz capable radio (2111/5112) is
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index acda56ee521b..5341dd2860d3 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -312,6 +312,7 @@ static const struct {
{ ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
{ ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
{ ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
+ { ATH5K_DEBUG_DMA, "dma", "dma start/stop" },
{ ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
{ ATH5K_DEBUG_DESC, "desc", "descriptor chains" },
{ ATH5K_DEBUG_ANY, "all", "show all debug levels" },
@@ -554,63 +555,63 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
len += snprintf(buf+len, sizeof(buf)-len,
"RX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
st->rxerr_crc,
st->rx_all_count > 0 ?
st->rxerr_crc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
st->rxerr_phy,
st->rx_all_count > 0 ?
st->rxerr_phy*100/st->rx_all_count : 0);
for (i = 0; i < 32; i++) {
if (st->rxerr_phy_code[i])
len += snprintf(buf+len, sizeof(buf)-len,
- " phy_err[%d]\t%d\n",
+ " phy_err[%u]\t%u\n",
i, st->rxerr_phy_code[i]);
}
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
st->rxerr_fifo,
st->rx_all_count > 0 ?
st->rxerr_fifo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
st->rxerr_decrypt,
st->rx_all_count > 0 ?
st->rxerr_decrypt*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
st->rxerr_mic,
st->rx_all_count > 0 ?
st->rxerr_mic*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
st->rxerr_proc,
st->rx_all_count > 0 ?
st->rxerr_proc*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
st->rxerr_jumbo,
st->rx_all_count > 0 ?
st->rxerr_jumbo*100/st->rx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
st->rx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
st->rx_bytes_count);
len += snprintf(buf+len, sizeof(buf)-len,
"\nTX\n---------------------\n");
- len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
st->txerr_retry,
st->tx_all_count > 0 ?
st->txerr_retry*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
st->txerr_fifo,
st->tx_all_count > 0 ?
st->txerr_fifo*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
st->txerr_filt,
st->tx_all_count > 0 ?
st->txerr_filt*100/st->tx_all_count : 0);
- len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
st->tx_all_count);
- len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+ len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
st->tx_bytes_count);
if (len > sizeof(buf))
@@ -719,7 +720,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,
st->mib_intr);
len += snprintf(buf+len, sizeof(buf)-len,
"beacon RSSI average:\t%d\n",
- sc->ah->ah_beacon_rssi_avg.avg);
+ (int)ewma_read(&sc->ah->ah_beacon_rssi_avg));
#define CC_PRINT(_struct, _field) \
_struct._field, \
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 236edbd2507d..3e34428d5126 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -95,6 +95,7 @@ struct ath5k_dbg_info {
* @ATH5K_DEBUG_DUMP_RX: print received skb content
* @ATH5K_DEBUG_DUMP_TX: print transmit skb content
* @ATH5K_DEBUG_DUMPBANDS: dump bands
+ * @ATH5K_DEBUG_DMA: debug dma start/stop
* @ATH5K_DEBUG_TRACE: trace function calls
* @ATH5K_DEBUG_DESC: descriptor setup
* @ATH5K_DEBUG_ANY: show at any debug level
@@ -118,6 +119,7 @@ enum ath5k_debug_level {
ATH5K_DEBUG_DUMP_RX = 0x00000100,
ATH5K_DEBUG_DUMP_TX = 0x00000200,
ATH5K_DEBUG_DUMPBANDS = 0x00000400,
+ ATH5K_DEBUG_DMA = 0x00000800,
ATH5K_DEBUG_ANI = 0x00002000,
ATH5K_DEBUG_DESC = 0x00004000,
ATH5K_DEBUG_ANY = 0xffffffff
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index 43244382f213..16b44ff7dd3e 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -26,9 +26,10 @@
#include "debug.h"
#include "base.h"
-/*
- * TX Descriptors
- */
+
+/************************\
+* TX Control descriptors *
+\************************/
/*
* Initialize the 2-word tx control descriptor on 5210/5211
@@ -335,6 +336,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
return 0;
}
+
+/***********************\
+* TX Status descriptors *
+\***********************/
+
/*
* Proccess the tx status descriptor on 5210/5211
*/
@@ -476,9 +482,10 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
return 0;
}
-/*
- * RX Descriptors
- */
+
+/****************\
+* RX Descriptors *
+\****************/
/*
* Initialize an rx control descriptor
@@ -666,6 +673,11 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
return 0;
}
+
+/********\
+* Attach *
+\********/
+
/*
* Init function pointers inside ath5k_hw struct
*/
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h
index b2adb2a281c2..2509d0bf037d 100644
--- a/drivers/net/wireless/ath/ath5k/desc.h
+++ b/drivers/net/wireless/ath/ath5k/desc.h
@@ -26,7 +26,7 @@
struct ath5k_hw_rx_ctl {
u32 rx_control_0; /* RX control word 0 */
u32 rx_control_1; /* RX control word 1 */
-} __packed;
+} __packed __aligned(4);
/* RX control word 1 fields/flags */
#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */
@@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl {
struct ath5k_hw_rx_status {
u32 rx_status_0; /* RX status word 0 */
u32 rx_status_1; /* RX status word 1 */
-} __packed;
+} __packed __aligned(4);
/* 5210/5211 */
/* RX status word 0 fields/flags */
@@ -129,7 +129,7 @@ enum ath5k_phy_error_code {
struct ath5k_hw_2w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */
u32 tx_control_1; /* TX control word 1 */
-} __packed;
+} __packed __aligned(4);
/* TX control word 0 fields/flags */
#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */
@@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl {
u32 tx_control_1; /* TX control word 1 */
u32 tx_control_2; /* TX control word 2 */
u32 tx_control_3; /* TX control word 3 */
-} __packed;
+} __packed __aligned(4);
/* TX control word 0 fields/flags */
#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */
@@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl {
struct ath5k_hw_tx_status {
u32 tx_status_0; /* TX status word 0 */
u32 tx_status_1; /* TX status word 1 */
-} __packed;
+} __packed __aligned(4);
/* TX status word 0 fields/flags */
#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */
@@ -282,7 +282,7 @@ struct ath5k_hw_tx_status {
struct ath5k_hw_5210_tx_desc {
struct ath5k_hw_2w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat;
-} __packed;
+} __packed __aligned(4);
/*
* 5212 hardware TX descriptor
@@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc {
struct ath5k_hw_5212_tx_desc {
struct ath5k_hw_4w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat;
-} __packed;
+} __packed __aligned(4);
/*
* Common hardware RX descriptor
@@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc {
struct ath5k_hw_all_rx_desc {
struct ath5k_hw_rx_ctl rx_ctl;
struct ath5k_hw_rx_status rx_stat;
-} __packed;
+} __packed __aligned(4);
/*
* Atheros hardware DMA descriptor
@@ -313,7 +313,7 @@ struct ath5k_desc {
struct ath5k_hw_5212_tx_desc ds_tx5212;
struct ath5k_hw_all_rx_desc ds_rx;
} ud;
-} __packed;
+} __packed __aligned(4);
#define AR5K_RXDESC_INTREQ 0x0020
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 923c9ca5c4f0..82541fec9f0e 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -37,6 +37,7 @@
#include "debug.h"
#include "base.h"
+
/*********\
* Receive *
\*********/
@@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
*
* @ah: The &struct ath5k_hw
*/
-int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
{
unsigned int i;
@@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
for (i = 1000; i > 0 &&
(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
i--)
- udelay(10);
+ udelay(100);
+
+ if (i)
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "failed to stop RX DMA !\n");
return i ? 0 : -EBUSY;
}
@@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
* @ah: The &struct ath5k_hw
* @phys_addr: RX descriptor address
*
- * XXX: Should we check if rx is enabled before setting rxdp ?
+ * Returns -EIO if rx is active
*/
-void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
+int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
{
+ if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "tried to set RXDP while rx was active !\n");
+ return -EIO;
+ }
+
ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+ return 0;
}
@@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Return if queue is declared inactive */
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return -EIO;
+ return -EINVAL;
if (ah->ah_version == AR5K_AR5210) {
tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
*
* Stop DMA transmit on a specific hw queue and drain queue so we don't
* have any pending frames. Returns -EBUSY if we still have pending frames,
- * -EINVAL if queue number is out of range.
+ * -EINVAL if queue number is out of range or inactive.
*
*/
-int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
{
unsigned int i = 40;
u32 tx_queue, pending;
@@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
/* Return if queue is declared inactive */
if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return -EIO;
+ return -EINVAL;
if (ah->ah_version == AR5K_AR5210) {
tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
@@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
ath5k_hw_reg_read(ah, AR5K_CR);
} else {
+
+ /*
+ * Enable DCU early termination to quickly
+ * flush any pending frames from QCU
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_DCU_EARLY);
+
/*
* Schedule TX disable and wait until queue is empty
*/
AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
- /*Check for pending frames*/
+ /* Wait for queue to stop */
+ for (i = 1000; i > 0 &&
+ (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0);
+ i--)
+ udelay(100);
+
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "queue %i didn't stop !\n", queue);
+
+ /* Check for pending frames */
+ i = 1000;
do {
pending = ath5k_hw_reg_read(ah,
AR5K_QUEUE_STATUS(queue)) &
@@ -247,12 +278,12 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
/* Wait a while and disable mechanism */
- udelay(200);
+ udelay(400);
AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
AR5K_QUIET_CTL1_QT_EN);
/* Re-check for pending frames */
- i = 40;
+ i = 100;
do {
pending = ath5k_hw_reg_read(ah,
AR5K_QUEUE_STATUS(queue)) &
@@ -262,12 +293,27 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
AR5K_DIAG_SW_CHANNEL_IDLE_HIGH);
+
+ if (pending)
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "quiet mechanism didn't work q:%i !\n",
+ queue);
}
+ /*
+ * Disable DCU early termination
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_DCU_EARLY);
+
/* Clear register */
ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
- if (pending)
+ if (pending) {
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "tx dma didn't stop (q:%i, frm:%i) !\n",
+ queue, pending);
return -EBUSY;
+ }
}
/* TODO: Check for success on 5210 else return error */
@@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
}
/**
+ * ath5k_hw_stop_beacon_queue - Stop beacon queue
+ *
+ * @ah The &struct ath5k_hw
+ * @queue The queue number
+ *
+ * Returns -EIO if queue didn't stop
+ */
+int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ int ret;
+ ret = ath5k_hw_stop_tx_dma(ah, queue);
+ if (ret) {
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA,
+ "beacon queue didn't stop !\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+/**
* ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
*
* @ah: The &struct ath5k_hw
@@ -427,6 +493,7 @@ done:
return ret;
}
+
/*******************\
* Interrupt masking *
\*******************/
@@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
return old_mask;
}
+
+/********************\
+ Init/Stop functions
+\********************/
+
+/**
+ * ath5k_hw_dma_init - Initialize DMA unit
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Set DMA size and pre-enable interrupts
+ * (driver handles tx/rx buffer setup and
+ * dma start/stop)
+ *
+ * XXX: Save/restore RXDP/TXDP registers ?
+ */
+void ath5k_hw_dma_init(struct ath5k_hw *ah)
+{
+ /*
+ * Set Rx/Tx DMA Configuration
+ *
+ * Set standard DMA size (128). Note that
+ * a DMA size of 512 causes rx overruns and tx errors
+ * on pci-e cards (tested on 5424 but since rx overruns
+ * also occur on 5416/5418 with madwifi we set 128
+ * for all PCI-E cards to be safe).
+ *
+ * XXX: need to check 5210 for this
+ * TODO: Check out tx triger level, it's always 64 on dumps but I
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_set_imr(ah, ah->ah_imr);
+
+}
+
+/**
+ * ath5k_hw_dma_stop - stop DMA unit
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stop tx/rx DMA and interrupts. Returns
+ * -EBUSY if tx or rx dma failed to stop.
+ *
+ * XXX: Sometimes DMA unit hangs and we have
+ * stuck frames on tx queues, only a reset
+ * can fix that.
+ */
+int ath5k_hw_dma_stop(struct ath5k_hw *ah)
+{
+ int i, qmax, err;
+ err = 0;
+
+ /* Disable interrupts */
+ ath5k_hw_set_imr(ah, 0);
+
+ /* Stop rx dma */
+ err = ath5k_hw_stop_rx_dma(ah);
+ if (err)
+ return err;
+
+ /* Clear any pending interrupts
+ * and disable tx dma */
+ if (ah->ah_version != AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+ qmax = AR5K_NUM_TX_QUEUES;
+ } else {
+ /* PISR/SISR Not available on 5210 */
+ ath5k_hw_reg_read(ah, AR5K_ISR);
+ qmax = AR5K_NUM_TX_QUEUES_NOQCU;
+ }
+
+ for (i = 0; i < qmax; i++) {
+ err = ath5k_hw_stop_tx_dma(ah, i);
+ /* -EINVAL -> queue inactive */
+ if (err != -EINVAL)
+ return err;
+ }
+
+ return err;
+}
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 39722dd73e43..97eaa9a4415e 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -28,45 +28,16 @@
#include "debug.h"
#include "base.h"
-/*
- * Read from eeprom
- */
-static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
-{
- u32 status, timeout;
-
- /*
- * Initialize EEPROM access
- */
- if (ah->ah_version == AR5K_AR5210) {
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
- (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
- } else {
- ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
- AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
- AR5K_EEPROM_CMD_READ);
- }
- for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
- status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
- if (status & AR5K_EEPROM_STAT_RDDONE) {
- if (status & AR5K_EEPROM_STAT_RDERR)
- return -EIO;
- *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
- 0xffff);
- return 0;
- }
- udelay(15);
- }
-
- return -ETIMEDOUT;
-}
+/******************\
+* Helper functions *
+\******************/
/*
* Translate binary channel representation in EEPROM to frequency
*/
static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
- unsigned int mode)
+ unsigned int mode)
{
u16 val;
@@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
return val;
}
+
+/*********\
+* Parsers *
+\*********/
+
/*
* Initialize eeprom & capabilities structs
*/
@@ -198,7 +174,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
*
* XXX: Serdes values seem to be fixed so
* no need to read them here, we write them
- * during ath5k_hw_attach */
+ * during ath5k_hw_init */
AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val);
ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ?
true : false;
@@ -647,6 +623,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
return 0;
}
+
/*
* Read power calibration for RF5111 chips
*
@@ -1514,6 +1491,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
return 0;
}
+
/*
* Read per channel calibration info from EEPROM
*
@@ -1607,15 +1585,6 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
return 0;
}
-void
-ath5k_eeprom_detach(struct ath5k_hw *ah)
-{
- u8 mode;
-
- for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
- ath5k_eeprom_free_pcal_info(ah, mode);
-}
-
/* Read conformance test limits used for regulatory control */
static int
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
@@ -1757,6 +1726,44 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah)
}
/*
+ * Read the MAC address from eeprom
+ */
+int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN] = {};
+ u32 total, offset;
+ u16 data;
+ int octet, ret;
+
+ ret = ath5k_hw_nvram_read(ah, 0x20, &data);
+ if (ret)
+ return ret;
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ ret = ath5k_hw_nvram_read(ah, offset, &data);
+ if (ret)
+ return ret;
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ return 0;
+}
+
+
+/***********************\
+* Init/Detach functions *
+\***********************/
+
+/*
* Initialize eeprom data structure
*/
int
@@ -1787,35 +1794,11 @@ ath5k_eeprom_init(struct ath5k_hw *ah)
return 0;
}
-/*
- * Read the MAC address from eeprom
- */
-int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+void
+ath5k_eeprom_detach(struct ath5k_hw *ah)
{
- u8 mac_d[ETH_ALEN] = {};
- u32 total, offset;
- u16 data;
- int octet, ret;
-
- ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
- if (ret)
- return ret;
-
- for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
- ret = ath5k_hw_eeprom_read(ah, offset, &data);
- if (ret)
- return ret;
-
- total += data;
- mac_d[octet + 1] = data & 0xff;
- mac_d[octet] = data >> 8;
- octet += 2;
- }
-
- if (!total || total == 3 * 0xffff)
- return -EINVAL;
-
- memcpy(mac, mac_d, ETH_ALEN);
+ u8 mode;
- return 0;
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
+ ath5k_eeprom_free_pcal_info(ah, mode);
}
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index c4a6d5f26af4..0017006be841 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -241,7 +241,7 @@ enum ath5k_eeprom_freq_bands{
#define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250
#define AR5K_EEPROM_READ(_o, _v) do { \
- ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \
+ ret = ath5k_hw_nvram_read(ah, (_o), &(_v)); \
if (ret) \
return ret; \
} while (0)
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index 8fa439308828..e49340d18df4 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -44,7 +44,7 @@ struct ath5k_ini {
struct ath5k_ini_mode {
u16 mode_register;
- u32 mode_value[5];
+ u32 mode_value[3];
};
/* Initial register settings for AR5210 */
@@ -391,76 +391,74 @@ static const struct ath5k_ini ar5211_ini[] = {
*/
static const struct ath5k_ini_mode ar5211_ini_mode[] = {
{ AR5K_TXCFG,
- /* a aTurbo b g (OFDM) */
- { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } },
+ /* A/XR B G */
+ { 0x00000015, 0x0000001d, 0x00000015 } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_DCU_GBL_IFS_SLOT,
- { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } },
+ { 0x00000168, 0x000001b8, 0x00000168 } },
{ AR5K_DCU_GBL_IFS_SIFS,
- { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } },
+ { 0x00000230, 0x000000b0, 0x00000230 } },
{ AR5K_DCU_GBL_IFS_EIFS,
- { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } },
+ { 0x00000d98, 0x00001f48, 0x00000d98 } },
{ AR5K_DCU_GBL_IFS_MISC,
- { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } },
+ { 0x0000a0e0, 0x00005880, 0x0000a0e0 } },
{ AR5K_TIME_OUT,
- { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } },
+ { 0x04000400, 0x20003000, 0x04000400 } },
{ AR5K_USEC_5211,
- { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } },
- { AR5K_PHY_TURBO,
- { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } },
+ { 0x0e8d8fa7, 0x01608f95, 0x0e8d8fa7 } },
{ AR5K_PHY(8),
- { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } },
- { AR5K_PHY(9),
- { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } },
- { AR5K_PHY(10),
- { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } },
- { AR5K_PHY(13),
- { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
- { AR5K_PHY(14),
- { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } },
- { AR5K_PHY(17),
- { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } },
- { AR5K_PHY(18),
- { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
- { AR5K_PHY(20),
- { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+ { 0x02020200, 0x02010200, 0x02020200 } },
+ { AR5K_PHY_RF_CTL2,
+ { 0x00000e0e, 0x00000707, 0x00000e0e } },
+ { AR5K_PHY_RF_CTL3,
+ { 0x0a020001, 0x05010000, 0x0a020001 } },
+ { AR5K_PHY_RF_CTL4,
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY_PA_CTL,
+ { 0x00000007, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY_SETTLING,
+ { 0x1372169c, 0x137216a8, 0x1372169c } },
+ { AR5K_PHY_GAIN,
+ { 0x0018ba67, 0x0018ba69, 0x0018ba69 } },
+ { AR5K_PHY_DESIRED_SIZE,
+ { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
+ { 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
+ { 0x31375d5e, 0x313a5d5e, 0x31375d5e } },
{ AR5K_PHY_AGCCTL,
- { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
+ { 0x0000bd10, 0x0000bd38, 0x0000bd10 } },
{ AR5K_PHY_NF,
- { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
{ AR5K_PHY_RX_DELAY,
- { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } },
+ { 0x00002710, 0x0000157c, 0x00002710 } },
{ AR5K_PHY(70),
- { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } },
+ { 0x00000190, 0x00000084, 0x00000190 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
+ { 0x6fe01020, 0x6fe00920, 0x6fe01020 } },
{ AR5K_PHY_PCDAC_TXPOWER_BASE,
- { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
+ { 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } },
{ AR5K_RF_BUFFER_CONTROL_4,
- { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } },
+ { 0x00000010, 0x00000010, 0x00000010 } },
};
/* Initial register settings for AR5212 */
@@ -677,89 +675,87 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
{ AR5K_QUEUE_DFS_LOCAL_IFS(0),
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ /* A/XR B G */
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(1),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(2),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(3),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(4),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(5),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(6),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(7),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(8),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(9),
- { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
{ AR5K_DCU_GBL_IFS_SIFS,
- { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+ { 0x00000230, 0x000000b0, 0x00000160 } },
{ AR5K_DCU_GBL_IFS_SLOT,
- { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+ { 0x00000168, 0x000001b8, 0x0000018c } },
{ AR5K_DCU_GBL_IFS_EIFS,
- { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+ { 0x00000e60, 0x00001f1c, 0x00003e38 } },
{ AR5K_DCU_GBL_IFS_MISC,
- { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+ { 0x0000a0e0, 0x00005880, 0x0000b0e0 } },
{ AR5K_TIME_OUT,
- { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
- { AR5K_PHY_TURBO,
- { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+ { 0x03e803e8, 0x04200420, 0x08400840 } },
{ AR5K_PHY(8),
- { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+ { 0x02020200, 0x02010200, 0x02020200 } },
{ AR5K_PHY_RF_CTL2,
- { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+ { 0x00000e0e, 0x00000707, 0x00000e0e } },
{ AR5K_PHY_SETTLING,
- { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+ { 0x1372161c, 0x13721722, 0x137216a2 } },
{ AR5K_PHY_AGCCTL,
- { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
+ { 0x00009d10, 0x00009d18, 0x00009d18 } },
{ AR5K_PHY_NF,
- { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
- { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+ { 0x409a4190, 0x409a4190, 0x409a4190 } },
{ AR5K_PHY(70),
- { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+ { 0x000001b8, 0x00000084, 0x00000108 } },
{ AR5K_PHY_OFDM_SELFCORR,
- { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+ { 0x10058a05, 0x10058a05, 0x10058a05 } },
{ 0xa230,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+ { 0x00000000, 0x00000000, 0x00000108 } },
};
/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
{ AR5K_TXCFG,
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ /* A/XR B G */
+ { 0x00008015, 0x00008015, 0x00008015 } },
{ AR5K_USEC_5211,
- { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+ { 0x128d8fa7, 0x04e00f95, 0x12e00fab } },
{ AR5K_PHY_RF_CTL3,
- { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+ { 0x0a020001, 0x05010100, 0x0a020001 } },
{ AR5K_PHY_RF_CTL4,
- { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
{ AR5K_PHY_PA_CTL,
- { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { 0x00000007, 0x0000000b, 0x0000000b } },
{ AR5K_PHY_GAIN,
- { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+ { 0x0018da5a, 0x0018ca69, 0x0018ca69 } },
{ AR5K_PHY_DESIRED_SIZE,
- { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+ { 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+ { 0x3137665e, 0x3137665e, 0x3137665e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
- { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+ { 0x050cb081, 0x050cb081, 0x050cb080 } },
{ AR5K_PHY_RX_DELAY,
- { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+ { 0x00002710, 0x0000157c, 0x00002af8 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+ { 0xf7b81020, 0xf7b80d20, 0xf7b81020 } },
{ AR5K_PHY_GAIN_2GHZ,
- { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+ { 0x642c416a, 0x6440416a, 0x6440416a } },
{ AR5K_PHY_CCK_RX_CTL_4,
- { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+ { 0x1883800a, 0x1873800a, 0x1883800a } },
};
static const struct ath5k_ini rf5111_ini_common_end[] = {
@@ -782,38 +778,38 @@ static const struct ath5k_ini rf5111_ini_common_end[] = {
/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
{ AR5K_TXCFG,
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ /* A/XR B G */
+ { 0x00008015, 0x00008015, 0x00008015 } },
{ AR5K_USEC_5211,
- { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { 0x128d93a7, 0x04e01395, 0x12e013ab } },
{ AR5K_PHY_RF_CTL3,
- { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { 0x0a020001, 0x05020100, 0x0a020001 } },
{ AR5K_PHY_RF_CTL4,
- { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
{ AR5K_PHY_PA_CTL,
- { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { 0x00000007, 0x0000000b, 0x0000000b } },
{ AR5K_PHY_GAIN,
- { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+ { 0x0018da6d, 0x0018ca75, 0x0018ca75 } },
{ AR5K_PHY_DESIRED_SIZE,
- { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
+ { 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+ { 0x3137665e, 0x3137665e, 0x3137665e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
- { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { 0x050cb081, 0x050cb081, 0x050cb081 } },
{ AR5K_PHY_RX_DELAY,
- { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { 0x000007d0, 0x0000044c, 0x00000898 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+ { 0xf7b81020, 0xf7b80d10, 0xf7b81010 } },
{ AR5K_PHY_CCKTXCTL,
- { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+ { 0x00000000, 0x00000008, 0x00000008 } },
{ AR5K_PHY_CCK_CROSSCORR,
- { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
{ AR5K_PHY_GAIN_2GHZ,
- { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+ { 0x642c0140, 0x6442c160, 0x6442c160 } },
{ AR5K_PHY_CCK_RX_CTL_4,
- { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+ { 0x1883800a, 0x1873800a, 0x1883800a } },
};
static const struct ath5k_ini rf5112_ini_common_end[] = {
@@ -833,66 +829,66 @@ static const struct ath5k_ini rf5112_ini_common_end[] = {
/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
{ AR5K_TXCFG,
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ /* A/XR B G */
+ { 0x00000015, 0x00000015, 0x00000015 } },
{ AR5K_USEC_5211,
- { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { 0x128d93a7, 0x04e01395, 0x12e013ab } },
{ AR5K_PHY_RF_CTL3,
- { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { 0x0a020001, 0x05020100, 0x0a020001 } },
{ AR5K_PHY_RF_CTL4,
- { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
{ AR5K_PHY_PA_CTL,
- { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { 0x00000007, 0x0000000b, 0x0000000b } },
{ AR5K_PHY_GAIN,
- { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+ { 0x0018fa61, 0x001a1a63, 0x001a1a63 } },
{ AR5K_PHY_DESIRED_SIZE,
- { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } },
{ AR5K_PHY_SIG,
- { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { 0x3139605e, 0x3139605e, 0x3139605e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
- { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { 0x050cb081, 0x050cb081, 0x050cb081 } },
{ AR5K_PHY_RX_DELAY,
- { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { 0x000007d0, 0x0000044c, 0x00000898 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
{ AR5K_PHY_CCKTXCTL,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY_CCK_CROSSCORR,
- { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
{ AR5K_PHY_GAIN_2GHZ,
- { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+ { 0x002ec1e0, 0x002ac120, 0x002ac120 } },
{ AR5K_PHY_CCK_RX_CTL_4,
- { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0x1883800a, 0x1863800a, 0x1883800a } },
{ 0xa300,
- { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+ { 0x18010000, 0x18010000, 0x18010000 } },
{ 0xa304,
- { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+ { 0x30032602, 0x30032602, 0x30032602 } },
{ 0xa308,
- { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+ { 0x48073e06, 0x48073e06, 0x48073e06 } },
{ 0xa30c,
- { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
{ 0xa310,
- { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+ { 0x641a600f, 0x641a600f, 0x641a600f } },
{ 0xa314,
- { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
{ 0xa318,
- { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
{ 0xa31c,
- { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+ { 0x90cf865b, 0x8ecf865b, 0x8ecf865b } },
{ 0xa320,
- { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+ { 0x9d4f970f, 0x9b4f970f, 0x9b4f970f } },
{ 0xa324,
- { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+ { 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f } },
{ 0xa328,
- { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+ { 0xb55faf1f, 0xb35faf1f, 0xb35faf1f } },
{ 0xa32c,
- { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+ { 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f } },
{ 0xa330,
- { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+ { 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f } },
{ 0xa334,
- { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+ { 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
};
static const struct ath5k_ini rf5413_ini_common_end[] = {
@@ -972,38 +968,38 @@ static const struct ath5k_ini rf5413_ini_common_end[] = {
/* XXX: a mode ? */
static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
{ AR5K_TXCFG,
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ /* A/XR B G */
+ { 0x00000015, 0x00000015, 0x00000015 } },
{ AR5K_USEC_5211,
- { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { 0x128d93a7, 0x04e01395, 0x12e013ab } },
{ AR5K_PHY_RF_CTL3,
- { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } },
+ { 0x0a020001, 0x05020000, 0x0a020001 } },
{ AR5K_PHY_RF_CTL4,
- { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } },
+ { 0x00000e00, 0x00000e00, 0x00000e00 } },
{ AR5K_PHY_PA_CTL,
- { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } },
+ { 0x00000002, 0x0000000a, 0x0000000a } },
{ AR5K_PHY_GAIN,
- { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
+ { 0x0018da6d, 0x001a6a64, 0x001a6a64 } },
{ AR5K_PHY_DESIRED_SIZE,
- { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } },
+ { 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da } },
{ AR5K_PHY_SIG,
- { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } },
+ { 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } },
+ { 0x3137665e, 0x3137665e, 0x3139605e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
- { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { 0x050cb081, 0x050cb081, 0x050cb081 } },
{ AR5K_PHY_RX_DELAY,
- { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { 0x000007d0, 0x0000044c, 0x00000898 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
{ AR5K_PHY_CCKTXCTL,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY_CCK_CROSSCORR,
- { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
{ AR5K_PHY_GAIN_2GHZ,
- { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } },
+ { 0x002c0140, 0x0042c140, 0x0042c140 } },
{ AR5K_PHY_CCK_RX_CTL_4,
- { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0x1883800a, 0x1863800a, 0x1883800a } },
};
static const struct ath5k_ini rf2413_ini_common_end[] = {
@@ -1094,52 +1090,50 @@ static const struct ath5k_ini rf2413_ini_common_end[] = {
/* XXX: a mode ? */
static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
{ AR5K_TXCFG,
- /* a/XR aTurbo b g (DYN) gTurbo */
- { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ /* A/XR B G */
+ { 0x00000015, 0x00000015, 0x00000015 } },
{ AR5K_USEC_5211,
- { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
- { AR5K_PHY_TURBO,
- { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } },
+ { 0x128d93a7, 0x04e01395, 0x12e013ab } },
{ AR5K_PHY_RF_CTL3,
- { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { 0x0a020001, 0x05020100, 0x0a020001 } },
{ AR5K_PHY_RF_CTL4,
- { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
{ AR5K_PHY_PA_CTL,
- { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { 0x00000003, 0x0000000b, 0x0000000b } },
{ AR5K_PHY_SETTLING,
- { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } },
+ { 0x1372161c, 0x13721722, 0x13721422 } },
{ AR5K_PHY_GAIN,
- { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } },
+ { 0x0018fa61, 0x00199a65, 0x00199a65 } },
{ AR5K_PHY_DESIRED_SIZE,
- { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } },
{ AR5K_PHY_SIG,
- { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
{ AR5K_PHY_AGCCOARSE,
- { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { 0x3139605e, 0x3139605e, 0x3139605e } },
{ AR5K_PHY_WEAK_OFDM_LOW_THR,
- { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { 0x050cb081, 0x050cb081, 0x050cb081 } },
{ AR5K_PHY_RX_DELAY,
- { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { 0x000007d0, 0x0000044c, 0x00000898 } },
{ AR5K_PHY_FRAME_CTL_5211,
- { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } },
{ AR5K_PHY_CCKTXCTL,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY_CCK_CROSSCORR,
- { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { 0xd6be6788, 0xd03e6788, 0xd03e6788 } },
{ AR5K_PHY_GAIN_2GHZ,
- { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } },
+ { 0x00000140, 0x0052c140, 0x0052c140 } },
{ AR5K_PHY_CCK_RX_CTL_4,
- { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0x1883800a, 0x1863800a, 0x1883800a } },
{ 0xa324,
- { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
{ 0xa328,
- { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
{ 0xa32c,
- { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
{ 0xa330,
- { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
{ 0xa334,
- { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
+ { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } },
};
static const struct ath5k_ini rf2425_ini_common_end[] = {
@@ -1368,15 +1362,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = {
* Write initial register dump
*/
static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
- const struct ath5k_ini *ini_regs, bool change_channel)
+ const struct ath5k_ini *ini_regs, bool skip_pcu)
{
unsigned int i;
/* Write initial registers */
for (i = 0; i < size; i++) {
- /* On channel change there is
- * no need to mess with PCU */
- if (change_channel &&
+ /* Skip PCU registers if
+ * requested */
+ if (skip_pcu &&
ini_regs[i].ini_register >= AR5K_PCU_MIN &&
ini_regs[i].ini_register <= AR5K_PCU_MAX)
continue;
@@ -1409,7 +1403,7 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
}
-int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
{
/*
* Write initial register settings
@@ -1427,7 +1421,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
* Write initial settings common for all modes
*/
ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start),
- ar5212_ini_common_start, change_channel);
+ ar5212_ini_common_start, skip_pcu);
/* Second set of mode-specific settings */
switch (ah->ah_radio) {
@@ -1439,12 +1433,12 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5111_ini_common_end),
- rf5111_ini_common_end, change_channel);
+ rf5111_ini_common_end, skip_pcu);
/* Baseband gain table */
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5111_ini_bbgain),
- rf5111_ini_bbgain, change_channel);
+ rf5111_ini_bbgain, skip_pcu);
break;
case AR5K_RF5112:
@@ -1455,11 +1449,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_common_end),
- rf5112_ini_common_end, change_channel);
+ rf5112_ini_common_end, skip_pcu);
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
+ rf5112_ini_bbgain, skip_pcu);
break;
case AR5K_RF5413:
@@ -1470,11 +1464,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5413_ini_common_end),
- rf5413_ini_common_end, change_channel);
+ rf5413_ini_common_end, skip_pcu);
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
+ rf5112_ini_bbgain, skip_pcu);
break;
case AR5K_RF2316:
@@ -1486,7 +1480,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf2413_ini_common_end),
- rf2413_ini_common_end, change_channel);
+ rf2413_ini_common_end, skip_pcu);
/* Override settings from rf2413_ini_common_end */
if (ah->ah_radio == AR5K_RF2316) {
@@ -1498,9 +1492,32 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
+ rf5112_ini_bbgain, skip_pcu);
break;
case AR5K_RF2317:
+
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf2413_ini_mode_end),
+ rf2413_ini_mode_end, mode);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf2425_ini_common_end),
+ rf2425_ini_common_end, skip_pcu);
+
+ /* Override settings from rf2413_ini_mode_end */
+ ath5k_hw_reg_write(ah, 0x00180a65, AR5K_PHY_GAIN);
+
+ /* Override settings from rf2413_ini_common_end */
+ ath5k_hw_reg_write(ah, 0x00004000, AR5K_PHY_AGC);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TPC_RG5,
+ AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, 0xa);
+ ath5k_hw_reg_write(ah, 0x800000a8, 0x8140);
+ ath5k_hw_reg_write(ah, 0x000000ff, 0x9958);
+
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, skip_pcu);
+ break;
case AR5K_RF2425:
ath5k_hw_ini_mode_registers(ah,
@@ -1509,11 +1526,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf2425_ini_common_end),
- rf2425_ini_common_end, change_channel);
+ rf2425_ini_common_end, skip_pcu);
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
+ rf5112_ini_bbgain, skip_pcu);
break;
default:
return -EINVAL;
@@ -1538,17 +1555,17 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
* Write initial settings common for all modes
*/
ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
- ar5211_ini, change_channel);
+ ar5211_ini, skip_pcu);
/* AR5211 only comes with 5111 */
/* Baseband gain table */
ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
- rf5111_ini_bbgain, change_channel);
+ rf5111_ini_bbgain, skip_pcu);
/* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
} else if (ah->ah_version == AR5K_AR5210) {
ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
- ar5210_ini, change_channel);
+ ar5210_ini, skip_pcu);
}
return 0;
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 67aa52e9bf94..576edf2965dc 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -133,7 +133,7 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
led->led_dev.default_trigger = trigger;
led->led_dev.brightness_set = ath5k_led_brightness_set;
- err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
+ err = led_classdev_register(sc->dev, &led->led_dev);
if (err) {
ATH5K_WARN(sc, "could not register LED %s\n", name);
led->sc = NULL;
@@ -161,11 +161,20 @@ int ath5k_init_leds(struct ath5k_softc *sc)
{
int ret = 0;
struct ieee80211_hw *hw = sc->hw;
+#ifndef CONFIG_ATHEROS_AR231X
struct pci_dev *pdev = sc->pdev;
+#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match;
+ if (!sc->pdev)
+ return 0;
+
+#ifdef CONFIG_ATHEROS_AR231X
+ match = NULL;
+#else
match = pci_match_id(&ath5k_led_devices[0], pdev);
+#endif
if (match) {
__set_bit(ATH_STAT_LEDSOFT, sc->status);
sc->led_pin = ATH_PIN(match->driver_data);
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
new file mode 100644
index 000000000000..39f033128c5a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/nl80211.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include "../ath.h"
+#include "ath5k.h"
+#include "debug.h"
+#include "base.h"
+#include "reg.h"
+
+/* Known PCI ids */
+static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {
+ { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */
+ { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */
+ { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/
+ { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */
+ { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */
+ { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */
+ { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */
+ { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */
+ { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */
+ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+ { 0 }
+};
+
+/* return bus cachesize in 4B word units */
+static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
+{
+ struct ath5k_softc *sc = (struct ath5k_softc *) common->priv;
+ u8 u8tmp;
+
+ pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp);
+ *csz = (int)u8tmp;
+
+ /*
+ * This check was put in to avoid "unplesant" consequences if
+ * the bootrom has not fully initialized all PCI devices.
+ * Sometimes the cache line size register is not set
+ */
+
+ if (*csz == 0)
+ *csz = L1_CACHE_BYTES >> 2; /* Use the default size */
+}
+
+/*
+ * Read from eeprom
+ */
+bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+{
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
+ u32 status, timeout;
+
+ /*
+ * Initialize EEPROM access
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_READ);
+ }
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
+ if (status & AR5K_EEPROM_STAT_RDERR)
+ return -EIO;
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+ 0xffff);
+ return 0;
+ }
+ udelay(15);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int ath5k_hw_read_srev(struct ath5k_hw *ah)
+{
+ ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ return 0;
+}
+
+/* Common ath_bus_opts structure */
+static const struct ath_bus_ops ath_pci_bus_ops = {
+ .ath_bus_type = ATH_PCI,
+ .read_cachesize = ath5k_pci_read_cachesize,
+ .eeprom_read = ath5k_pci_eeprom_read,
+};
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void __iomem *mem;
+ struct ath5k_softc *sc;
+ struct ieee80211_hw *hw;
+ int ret;
+ u8 csz;
+
+ /*
+ * L0s needs to be disabled on all ath5k cards.
+ *
+ * For distributions shipping with CONFIG_PCIEASPM (this will be enabled
+ * by default in the future in 2.6.36) this will also mean both L1 and
+ * L0s will be disabled when a pre 1.1 PCIe device is detected. We do
+ * know L1 works correctly even for all ath5k pre 1.1 PCIe devices
+ * though but cannot currently undue the effect of a blacklist, for
+ * details you can read pcie_aspm_sanity_check() and see how it adjusts
+ * the device link capability.
+ *
+ * It may be possible in the future to implement some PCI API to allow
+ * drivers to override blacklists for pre 1.1 PCIe but for now it is
+ * best to accept that both L0s and L1 will be disabled completely for
+ * distributions shipping with CONFIG_PCIEASPM rather than having this
+ * issue present. Motivation for adding this new API will be to help
+ * with power consumption for some of these devices.
+ */
+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "can't enable device\n");
+ goto err;
+ }
+
+ /* XXX 32-bit addressing only */
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(&pdev->dev, "32-bit DMA not available\n");
+ goto err_dis;
+ }
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * Linux 2.4.18 (at least) writes the cache line size
+ * register as a 16-bit wide register which is wrong.
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz = L1_CACHE_BYTES >> 2;
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /* Enable bus mastering */
+ pci_set_master(pdev);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ret = pci_request_region(pdev, 0, "ath5k");
+ if (ret) {
+ dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+ goto err_dis;
+ }
+
+ mem = pci_iomap(pdev, 0, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+ ret = -EIO;
+ goto err_reg;
+ }
+
+ /*
+ * Allocate hw (mac80211 main struct)
+ * and hw->priv (driver private data)
+ */
+ hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+ if (hw == NULL) {
+ dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+ ret = -ENOMEM;
+ goto err_map;
+ }
+
+ dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+ sc = hw->priv;
+ sc->hw = hw;
+ sc->pdev = pdev;
+ sc->dev = &pdev->dev;
+ sc->irq = pdev->irq;
+ sc->devid = id->device;
+ sc->iobase = mem; /* So we can unmap it on detach */
+
+ /* Initialize */
+ ret = ath5k_init_softc(sc, &ath_pci_bus_ops);
+ if (ret)
+ goto err_free;
+
+ /* Set private data */
+ pci_set_drvdata(pdev, hw);
+
+ return 0;
+err_free:
+ ieee80211_free_hw(hw);
+err_map:
+ pci_iounmap(pdev, mem);
+err_reg:
+ pci_release_region(pdev, 0);
+err_dis:
+ pci_disable_device(pdev);
+err:
+ return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = hw->priv;
+
+ ath5k_deinit_softc(sc);
+ pci_iounmap(pdev, sc->iobase);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ ieee80211_free_hw(hw);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int ath5k_pci_suspend(struct device *dev)
+{
+ struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
+
+ ath5k_led_off(sc);
+ return 0;
+}
+
+static int ath5k_pci_resume(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct ath5k_softc *sc = pci_get_drvdata(pdev);
+
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ath5k_led_enable(sc);
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume);
+#define ATH5K_PM_OPS (&ath5k_pm_ops)
+#else
+#define ATH5K_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static struct pci_driver ath5k_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = ath5k_pci_id_table,
+ .probe = ath5k_pci_probe,
+ .remove = __devexit_p(ath5k_pci_remove),
+ .driver.pm = ATH5K_PM_OPS,
+};
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&ath5k_pci_driver);
+ if (ret) {
+ printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+ pci_unregister_driver(&ath5k_pci_driver);
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 074b4c644399..e5f2b96a4c63 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -31,87 +31,163 @@
#include "debug.h"
#include "base.h"
+/*
+ * AR5212+ can use higher rates for ack transmition
+ * based on current tx rate instead of the base rate.
+ * It does this to better utilize channel usage.
+ * This is a mapping between G rates (that cover both
+ * CCK and OFDM) and ack rates that we use when setting
+ * rate -> duration table. This mapping is hw-based so
+ * don't change anything.
+ *
+ * To enable this functionality we must set
+ * ah->ah_ack_bitrate_high to true else base rate is
+ * used (1Mb for CCK, 6Mb for OFDM).
+ */
+static const unsigned int ack_rates_high[] =
+/* Tx -> ACK */
+/* 1Mb -> 1Mb */ { 0,
+/* 2MB -> 2Mb */ 1,
+/* 5.5Mb -> 2Mb */ 1,
+/* 11Mb -> 2Mb */ 1,
+/* 6Mb -> 6Mb */ 4,
+/* 9Mb -> 6Mb */ 4,
+/* 12Mb -> 12Mb */ 6,
+/* 18Mb -> 12Mb */ 6,
+/* 24Mb -> 24Mb */ 8,
+/* 36Mb -> 24Mb */ 8,
+/* 48Mb -> 24Mb */ 8,
+/* 54Mb -> 24Mb */ 8 };
+
/*******************\
-* Generic functions *
+* Helper functions *
\*******************/
/**
- * ath5k_hw_set_opmode - Set PCU operating mode
+ * ath5k_hw_get_frame_duration - Get tx time of a frame
*
* @ah: The &struct ath5k_hw
- * @op_mode: &enum nl80211_iftype operating mode
+ * @len: Frame's length in bytes
+ * @rate: The @struct ieee80211_rate
*
- * Initialize PCU for the various operating modes (AP/STA etc)
+ * Calculate tx duration of a frame given it's rate and length
+ * It extends ieee80211_generic_frame_duration for non standard
+ * bwmodes.
*/
-int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
+int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
+ int len, struct ieee80211_rate *rate)
{
- struct ath_common *common = ath5k_hw_common(ah);
- u32 pcu_reg, beacon_reg, low_id, high_id;
+ struct ath5k_softc *sc = ah->ah_sc;
+ int sifs, preamble, plcp_bits, sym_time;
+ int bitrate, bits, symbols, symbol_bits;
+ int dur;
+
+ /* Fallback */
+ if (!ah->ah_bwmode) {
+ dur = ieee80211_generic_frame_duration(sc->hw,
+ NULL, len, rate);
+ return dur;
+ }
- ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+ bitrate = rate->bitrate;
+ preamble = AR5K_INIT_OFDM_PREAMPLE_TIME;
+ plcp_bits = AR5K_INIT_OFDM_PLCP_BITS;
+ sym_time = AR5K_INIT_OFDM_SYMBOL_TIME;
- /* Preserve rest settings */
- pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
- pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
- | AR5K_STA_ID1_KEYSRCH_MODE
- | (ah->ah_version == AR5K_AR5210 ?
- (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
+ sifs = AR5K_INIT_SIFS_TURBO;
+ preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN;
+ break;
+ case AR5K_BWMODE_10MHZ:
+ sifs = AR5K_INIT_SIFS_HALF_RATE;
+ preamble *= 2;
+ sym_time *= 2;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ sifs = AR5K_INIT_SIFS_QUARTER_RATE;
+ preamble *= 4;
+ sym_time *= 4;
+ break;
+ default:
+ sifs = AR5K_INIT_SIFS_DEFAULT_BG;
+ break;
+ }
- beacon_reg = 0;
+ bits = plcp_bits + (len << 3);
+ /* Bit rate is in 100Kbits */
+ symbol_bits = bitrate * sym_time;
+ symbols = DIV_ROUND_UP(bits * 10, symbol_bits);
- switch (op_mode) {
- case NL80211_IFTYPE_ADHOC:
- pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
- beacon_reg |= AR5K_BCR_ADHOC;
- if (ah->ah_version == AR5K_AR5210)
- pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
- else
- AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
- break;
+ dur = sifs + preamble + (sym_time * symbols);
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_MESH_POINT:
- pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
- beacon_reg |= AR5K_BCR_AP;
- if (ah->ah_version == AR5K_AR5210)
- pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
- break;
+ return dur;
+}
- case NL80211_IFTYPE_STATION:
- pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
- | (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_PWR_SV : 0);
- case NL80211_IFTYPE_MONITOR:
- pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
- | (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
- break;
+/**
+ * ath5k_hw_get_default_slottime - Get the default slot time for current mode
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
+{
+ struct ieee80211_channel *channel = ah->ah_current_channel;
+ unsigned int slot_time;
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
+ slot_time = AR5K_INIT_SLOT_TIME_TURBO;
+ break;
+ case AR5K_BWMODE_10MHZ:
+ slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE;
+ break;
+ case AR5K_BWMODE_DEFAULT:
+ slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
default:
- return -EINVAL;
+ if (channel->hw_value & CHANNEL_CCK)
+ slot_time = AR5K_INIT_SLOT_TIME_B;
+ break;
}
- /*
- * Set PCU registers
- */
- low_id = get_unaligned_le32(common->macaddr);
- high_id = get_unaligned_le16(common->macaddr + 4);
- ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
- ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+ return slot_time;
+}
- /*
- * Set Beacon Control Register on 5210
- */
- if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+/**
+ * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
+ *
+ * @ah: The &struct ath5k_hw
+ */
+unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
+{
+ struct ieee80211_channel *channel = ah->ah_current_channel;
+ unsigned int sifs;
- return 0;
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
+ sifs = AR5K_INIT_SIFS_TURBO;
+ break;
+ case AR5K_BWMODE_10MHZ:
+ sifs = AR5K_INIT_SIFS_HALF_RATE;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ sifs = AR5K_INIT_SIFS_QUARTER_RATE;
+ break;
+ case AR5K_BWMODE_DEFAULT:
+ sifs = AR5K_INIT_SIFS_DEFAULT_BG;
+ default:
+ if (channel->hw_value & CHANNEL_5GHZ)
+ sifs = AR5K_INIT_SIFS_DEFAULT_A;
+ break;
+ }
+
+ return sifs;
}
/**
- * ath5k_hw_update - Update MIB counters (mac layer statistics)
+ * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics)
*
* @ah: The &struct ath5k_hw
*
@@ -133,36 +209,88 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
}
+
+/******************\
+* ACK/CTS Timeouts *
+\******************/
+
/**
- * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ * ath5k_hw_write_rate_duration - fill rate code to duration table
*
- * @ah: The &struct ath5k_hw
- * @high: Flag to determine if we want to use high transmission rate
- * for ACKs or not
+ * @ah: the &struct ath5k_hw
+ * @mode: one of enum ath5k_driver_mode
+ *
+ * Write the rate code to duration table upon hw reset. This is a helper for
+ * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
+ * the hardware, based on current mode, for each rate. The rates which are
+ * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
+ * different rate code so we write their value twice (one for long preamble
+ * and one for short).
+ *
+ * Note: Band doesn't matter here, if we set the values for OFDM it works
+ * on both a and g modes. So all we have to do is set values for all g rates
+ * that include all OFDM and CCK rates.
*
- * If high flag is set, we tell hw to use a set of control rates based on
- * the current transmission rate (check out control_rates array inside reset.c).
- * If not hw just uses the lowest rate available for the current modulation
- * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
*/
-void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
{
- if (ah->ah_version != AR5K_AR5212)
- return;
- else {
- u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
- if (high)
- AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct ieee80211_rate *rate;
+ unsigned int i;
+ /* 802.11g covers both OFDM and CCK */
+ u8 band = IEEE80211_BAND_2GHZ;
+
+ /* Write rate duration table */
+ for (i = 0; i < sc->sbands[band].n_bitrates; i++) {
+ u32 reg;
+ u16 tx_time;
+
+ if (ah->ah_ack_bitrate_high)
+ rate = &sc->sbands[band].bitrates[ack_rates_high[i]];
+ /* CCK -> 1Mb */
+ else if (i < 4)
+ rate = &sc->sbands[band].bitrates[0];
+ /* OFDM -> 6Mb */
else
- AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ rate = &sc->sbands[band].bitrates[4];
+
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(rate->hw_value);
+
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * which ieee80211_generic_frame_duration() adds,
+ * its 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+ tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+
+ tx_time = le16_to_cpu(tx_time);
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+ if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
+ continue;
+
+ /*
+ * We're not distinguishing short preamble here,
+ * This is true, all we'll get is a longer value here
+ * which is not necessarilly bad. We could use
+ * export ieee80211_frame_duration() but that needs to be
+ * fixed first to be properly used by mac802111 drivers:
+ *
+ * - remove erp stuff and let the routine figure ofdm
+ * erp rates
+ * - remove passing argument ieee80211_local as
+ * drivers don't have access to it
+ * - move drivers using ieee80211_generic_frame_duration()
+ * to this
+ */
+ ath5k_hw_reg_write(ah, tx_time,
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
}
}
-
-/******************\
-* ACK/CTS Timeouts *
-\******************/
-
/**
* ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
*
@@ -199,88 +327,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
return 0;
}
-/**
- * ath5k_hw_htoclock - Translate usec to hw clock units
- *
- * @ah: The &struct ath5k_hw
- * @usec: value in microseconds
- */
-unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
-{
- struct ath_common *common = ath5k_hw_common(ah);
- return usec * common->clockrate;
-}
-
-/**
- * ath5k_hw_clocktoh - Translate hw clock units to usec
- * @clock: value in hw clock units
- */
-unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
-{
- struct ath_common *common = ath5k_hw_common(ah);
- return clock / common->clockrate;
-}
-
-/**
- * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
- *
- * @ah: The &struct ath5k_hw
- */
-void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
- struct ath_common *common = ath5k_hw_common(ah);
- int clock;
-
- if (channel->hw_value & CHANNEL_5GHZ)
- clock = 40; /* 802.11a */
- else if (channel->hw_value & CHANNEL_CCK)
- clock = 22; /* 802.11b */
- else
- clock = 44; /* 802.11g */
-
- /* Clock rate in turbo modes is twice the normal rate */
- if (channel->hw_value & CHANNEL_TURBO)
- clock *= 2;
-
- common->clockrate = clock;
-}
-
-/**
- * ath5k_hw_get_default_slottime - Get the default slot time for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
-
- if (channel->hw_value & CHANNEL_TURBO)
- return 6; /* both turbo modes */
-
- if (channel->hw_value & CHANNEL_CCK)
- return 20; /* 802.11b */
-
- return 9; /* 802.11 a/g */
-}
-
-/**
- * ath5k_hw_get_default_sifs - Get the default SIFS for current mode
- *
- * @ah: The &struct ath5k_hw
- */
-static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
-{
- struct ieee80211_channel *channel = ah->ah_current_channel;
-
- if (channel->hw_value & CHANNEL_TURBO)
- return 8; /* both turbo modes */
- if (channel->hw_value & CHANNEL_5GHZ)
- return 16; /* 802.11a */
-
- return 10; /* 802.11 b/g */
-}
+/*******************\
+* RX filter Control *
+\*******************/
/**
* ath5k_hw_set_lladdr - Set station id
@@ -362,39 +412,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
ath_hw_setbssidmask(common);
}
-/************\
-* RX Control *
-\************/
-
-/**
- * ath5k_hw_start_rx_pcu - Start RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Starts RX engine on PCU so that hw can process RXed frames
- * (ACK etc).
- *
- * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
- */
-void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
-{
- AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
-/**
- * at5k_hw_stop_rx_pcu - Stop RX engine
- *
- * @ah: The &struct ath5k_hw
- *
- * Stops RX engine on PCU
- *
- * TODO: Detach ANI here
- */
-void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
-{
- AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-}
-
/*
* Set multicast filter
*/
@@ -746,7 +763,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
* @ah: The &struct ath5k_hw
* @coverage_class: IEEE 802.11 coverage class number
*
- * Sets slot time, ACK timeout and CTS timeout for given coverage class.
+ * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
*/
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
{
@@ -755,9 +772,175 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time;
int cts_timeout = ack_timeout;
- ath5k_hw_set_slot_time(ah, slot_time);
+ ath5k_hw_set_ifs_intervals(ah, slot_time);
ath5k_hw_set_ack_timeout(ah, ack_timeout);
ath5k_hw_set_cts_timeout(ah, cts_timeout);
ah->ah_coverage_class = coverage_class;
}
+
+/***************************\
+* Init/Start/Stop functions *
+\***************************/
+
+/**
+ * ath5k_hw_start_rx_pcu - Start RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Starts RX engine on PCU so that hw can process RXed frames
+ * (ACK etc).
+ *
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * at5k_hw_stop_rx_pcu - Stop RX engine
+ *
+ * @ah: The &struct ath5k_hw
+ *
+ * Stops RX engine on PCU
+ */
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
+{
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/**
+ * ath5k_hw_set_opmode - Set PCU operating mode
+ *
+ * @ah: The &struct ath5k_hw
+ * @op_mode: &enum nl80211_iftype operating mode
+ *
+ * Configure PCU for the various operating modes (AP/STA etc)
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
+{
+ struct ath_common *common = ath5k_hw_common(ah);
+ u32 pcu_reg, beacon_reg, low_id, high_id;
+
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode);
+
+ /* Preserve rest settings */
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+ pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+ | AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
+ beacon_reg = 0;
+
+ switch (op_mode) {
+ case NL80211_IFTYPE_ADHOC:
+ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
+ beacon_reg |= AR5K_BCR_ADHOC;
+ if (ah->ah_version == AR5K_AR5210)
+ pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+ break;
+
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
+ beacon_reg |= AR5K_BCR_AP;
+ if (ah->ah_version == AR5K_AR5210)
+ pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
+ break;
+
+ case NL80211_IFTYPE_STATION:
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_PWR_SV : 0);
+ case NL80211_IFTYPE_MONITOR:
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * Set PCU registers
+ */
+ low_id = get_unaligned_le32(common->macaddr);
+ high_id = get_unaligned_le16(common->macaddr + 4);
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ /*
+ * Set Beacon Control Register on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+ return 0;
+}
+
+void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ u8 mode)
+{
+ /* Set bssid and bssid mask */
+ ath5k_hw_set_bssid(ah);
+
+ /* Set PCU config */
+ ath5k_hw_set_opmode(ah, op_mode);
+
+ /* Write rate duration table only on AR5212 and if
+ * virtual interface has already been brought up
+ * XXX: rethink this after new mode changes to
+ * mac80211 are integrated */
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_sc->nvifs)
+ ath5k_hw_write_rate_duration(ah);
+
+ /* Set RSSI/BRSSI thresholds
+ *
+ * Note: If we decide to set this value
+ * dynamicaly, have in mind that when AR5K_RSSI_THR
+ * register is read it might return 0x40 if we haven't
+ * wrote anything to it plus BMISS RSSI threshold is zeroed.
+ * So doing a save/restore procedure here isn't the right
+ * choice. Instead store it on ath5k_hw */
+ ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES <<
+ AR5K_RSSI_THR_BMISS_S),
+ AR5K_RSSI_THR);
+
+ /* MIC QoS support */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
+ ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
+ ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
+ }
+
+ /* QoS NOACK Policy */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
+ AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
+ AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
+ AR5K_QOS_NOACK);
+ }
+
+ /* Restore slot time and ACK timeouts */
+ if (ah->ah_coverage_class > 0)
+ ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
+
+ /* Set ACK bitrate mode (see ack_rates_high) */
+ if (ah->ah_version == AR5K_AR5212) {
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+ if (ah->ah_ack_bitrate_high)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ }
+ return;
+}
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 219367884e64..df5cd0fd69d6 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -29,6 +29,95 @@
#include "rfbuffer.h"
#include "rfgain.h"
+
+/******************\
+* Helper functions *
+\******************/
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+ unsigned int i;
+ u32 srev;
+ u16 ret;
+
+ /*
+ * Set the radio chip access register
+ */
+ switch (chan) {
+ case CHANNEL_2GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+ break;
+ case CHANNEL_5GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ break;
+ default:
+ return 0;
+ }
+
+ mdelay(2);
+
+ /* ...wait until PHY is ready and read the selected radio revision */
+ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+ for (i = 0; i < 8; i++)
+ ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+ if (ah->ah_version == AR5K_AR5210) {
+ srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+ ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+ } else {
+ srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+ ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+ ((srev & 0x0f) << 4), 8);
+ }
+
+ /* Reset to the 5GHz mode */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ return ret;
+}
+
+/*
+ * Check if a channel is supported
+ */
+bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+ /* Check if the channel is in our supported range */
+ if (flags & CHANNEL_2GHZ) {
+ if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+ return true;
+ } else if (flags & CHANNEL_5GHZ)
+ if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+ return true;
+
+ return false;
+}
+
+bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u8 refclk_freq;
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ refclk_freq = 40;
+ else
+ refclk_freq = 32;
+
+ if ((channel->center_freq % refclk_freq != 0) &&
+ ((channel->center_freq % refclk_freq < 10) ||
+ (channel->center_freq % refclk_freq > 22)))
+ return true;
+ else
+ return false;
+}
+
/*
* Used to modify RF Banks before writing them to AR5K_RF_BUFFER
*/
@@ -110,6 +199,90 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,
return data;
}
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
+ * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init.
+ *
+ * Since delta slope is floating point we split it on its exponent and
+ * mantissa and provide these values on hw.
+ *
+ * For more infos i think this patent is related
+ * http://www.freepatentsonline.com/7184495.html
+ */
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ /* Get exponent and mantissa and set it */
+ u32 coef_scaled, coef_exp, coef_man,
+ ds_coef_exp, ds_coef_man, clock;
+
+ BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
+ !(channel->hw_value & CHANNEL_OFDM));
+
+ /* Get coefficient
+ * ALGO: coef = (5 * clock / carrier_freq) / 2
+ * we scale coef by shifting clock value by 24 for
+ * better precision since we use integers */
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
+ clock = 40 * 2;
+ break;
+ case AR5K_BWMODE_10MHZ:
+ clock = 40 / 2;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ clock = 40 / 4;
+ break;
+ default:
+ clock = 40;
+ break;
+ }
+ coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
+
+ /* Get exponent
+ * ALGO: coef_exp = 14 - highest set bit position */
+ coef_exp = ilog2(coef_scaled);
+
+ /* Doesn't make sense if it's zero*/
+ if (!coef_scaled || !coef_exp)
+ return -EINVAL;
+
+ /* Note: we've shifted coef_scaled by 24 */
+ coef_exp = 14 - (coef_exp - 24);
+
+
+ /* Get mantissa (significant digits)
+ * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
+ coef_man = coef_scaled +
+ (1 << (24 - coef_exp - 1));
+
+ /* Calculate delta slope coefficient exponent
+ * and mantissa (remove scaling) and set them on hw */
+ ds_coef_man = coef_man >> (24 - coef_exp);
+ ds_coef_exp = coef_exp - 16;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+ return 0;
+}
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+ /*Just a try M.F.*/
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+ return 0;
+}
+
+
/**********************\
* RF Gain optimization *
\**********************/
@@ -436,7 +609,7 @@ done:
/* Write initial RF gain table to set the RF sensitivity
* this one works on all RF chips and has nothing to do
* with gain_F calibration */
-int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
+static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
{
const struct ath5k_ini_rfgain *ath5k_rfg;
unsigned int i, size;
@@ -494,12 +667,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq)
* RF Registers setup *
\********************/
-
/*
* Setup RF registers by writing RF buffer on hw
*/
-int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
- unsigned int mode)
+static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, unsigned int mode)
{
const struct ath5k_rf_reg *rf_regs;
const struct ath5k_ini_rfbuffer *ini_rfb;
@@ -652,6 +824,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
g_step = &go->go_step[ah->ah_gain.g_step_idx];
+ /* Set turbo mode (N/A on RF5413) */
+ if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
+ (ah->ah_radio != AR5K_RF5413))
+ ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false);
+
/* Bank Modifications (chip-specific) */
if (ah->ah_radio == AR5K_RF5111) {
@@ -691,7 +868,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
AR5K_RF_PLO_SEL, true);
- /* TODO: Half/quarter channel support */
+ /* Tweak power detectors for half/quarter rate support */
+ if (ah->ah_bwmode == AR5K_BWMODE_5MHZ ||
+ ah->ah_bwmode == AR5K_BWMODE_10MHZ) {
+ u8 wait_i;
+
+ ath5k_hw_rfb_op(ah, rf_regs, 0x1f,
+ AR5K_RF_WAIT_S, true);
+
+ wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ?
+ 0x1f : 0x10;
+
+ ath5k_hw_rfb_op(ah, rf_regs, wait_i,
+ AR5K_RF_WAIT_I, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 3,
+ AR5K_RF_MAX_TIME, true);
+
+ }
}
if (ah->ah_radio == AR5K_RF5112) {
@@ -789,8 +982,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
AR5K_RF_GAIN_I, true);
- /* TODO: Half/quarter channel support */
+ /* Tweak power detector for half/quarter rates */
+ if (ah->ah_bwmode == AR5K_BWMODE_5MHZ ||
+ ah->ah_bwmode == AR5K_BWMODE_10MHZ) {
+ u8 pd_delay;
+
+ pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ?
+ 0xf : 0x8;
+
+ ath5k_hw_rfb_op(ah, rf_regs, pd_delay,
+ AR5K_RF_PD_PERIOD_A, true);
+ ath5k_hw_rfb_op(ah, rf_regs, 0xf,
+ AR5K_RF_PD_DELAY_A, true);
+ }
}
if (ah->ah_radio == AR5K_RF5413 &&
@@ -822,24 +1027,6 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
\**************************/
/*
- * Check if a channel is supported
- */
-bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
-{
- /* Check if the channel is in our supported range */
- if (flags & CHANNEL_2GHZ) {
- if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
- (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
- return true;
- } else if (flags & CHANNEL_5GHZ)
- if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
- (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
- return true;
-
- return false;
-}
-
-/*
* Convertion needed for RF5110
*/
static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
@@ -1045,7 +1232,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
/*
* Set a channel on the radio chip
*/
-int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+static int ath5k_hw_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
{
int ret;
/*
@@ -1092,8 +1280,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
}
ah->ah_current_channel = channel;
- ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
- ath5k_hw_set_clockrate(ah);
return 0;
}
@@ -1102,18 +1288,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
PHY calibration
\*****************/
-static int sign_extend(int val, const int nbits)
-{
- int order = BIT(nbits-1);
- return (val ^ order) - order;
-}
-
static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
{
s32 val;
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
- return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
+ return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8);
}
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
@@ -1183,12 +1363,10 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
- case CHANNEL_T:
case CHANNEL_XR:
ee_mode = AR5K_EEPROM_MODE_11A;
break;
case CHANNEL_G:
- case CHANNEL_TG:
ee_mode = AR5K_EEPROM_MODE_11G;
break;
default:
@@ -1425,31 +1603,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
return ret;
}
+
/***************************\
* Spur mitigation functions *
\***************************/
-bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
- struct ieee80211_channel *channel)
-{
- u8 refclk_freq;
-
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
- refclk_freq = 40;
- else
- refclk_freq = 32;
-
- if ((channel->center_freq % refclk_freq != 0) &&
- ((channel->center_freq % refclk_freq < 10) ||
- (channel->center_freq % refclk_freq > 22)))
- return true;
- else
- return false;
-}
-
-void
+static void
ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
struct ieee80211_channel *channel)
{
@@ -1478,7 +1637,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
spur_chan_fbin = AR5K_EEPROM_NO_SPUR;
spur_detection_window = AR5K_SPUR_CHAN_WIDTH;
/* XXX: Half/Quarter channels ?*/
- if (channel->hw_value & CHANNEL_TURBO)
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
spur_detection_window *= 2;
for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) {
@@ -1507,32 +1666,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
* Calculate deltas:
* spur_freq_sigma_delta -> spur_offset / sample_freq << 21
* spur_delta_phase -> spur_offset / chip_freq << 11
- * Note: Both values have 100KHz resolution
+ * Note: Both values have 100Hz resolution
*/
- /* XXX: Half/Quarter rate channels ? */
- switch (channel->hw_value) {
- case CHANNEL_A:
- /* Both sample_freq and chip_freq are 40MHz */
- spur_delta_phase = (spur_offset << 17) / 25;
- spur_freq_sigma_delta = (spur_delta_phase >> 10);
- symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
- break;
- case CHANNEL_G:
- /* sample_freq -> 40MHz chip_freq -> 44MHz
- * (for b compatibility) */
- spur_freq_sigma_delta = (spur_offset << 8) / 55;
- spur_delta_phase = (spur_offset << 17) / 25;
- symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
- break;
- case CHANNEL_T:
- case CHANNEL_TG:
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
/* Both sample_freq and chip_freq are 80MHz */
spur_delta_phase = (spur_offset << 16) / 25;
spur_freq_sigma_delta = (spur_delta_phase >> 10);
- symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz;
+ symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2;
break;
+ case AR5K_BWMODE_10MHZ:
+ /* Both sample_freq and chip_freq are 20MHz (?) */
+ spur_delta_phase = (spur_offset << 18) / 25;
+ spur_freq_sigma_delta = (spur_delta_phase >> 10);
+ symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2;
+ case AR5K_BWMODE_5MHZ:
+ /* Both sample_freq and chip_freq are 10MHz (?) */
+ spur_delta_phase = (spur_offset << 19) / 25;
+ spur_freq_sigma_delta = (spur_delta_phase >> 10);
+ symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
default:
- return;
+ if (channel->hw_value == CHANNEL_A) {
+ /* Both sample_freq and chip_freq are 40MHz */
+ spur_delta_phase = (spur_offset << 17) / 25;
+ spur_freq_sigma_delta =
+ (spur_delta_phase >> 10);
+ symbol_width =
+ AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+ } else {
+ /* sample_freq -> 40MHz chip_freq -> 44MHz
+ * (for b compatibility) */
+ spur_delta_phase = (spur_offset << 17) / 25;
+ spur_freq_sigma_delta =
+ (spur_offset << 8) / 55;
+ symbol_width =
+ AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz;
+ }
+ break;
}
/* Calculate pilot and magnitude masks */
@@ -1672,63 +1842,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
}
}
-/********************\
- Misc PHY functions
-\********************/
-
-int ath5k_hw_phy_disable(struct ath5k_hw *ah)
-{
- /*Just a try M.F.*/
- ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
-
- return 0;
-}
-
-/*
- * Get the PHY Chip revision
- */
-u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
-{
- unsigned int i;
- u32 srev;
- u16 ret;
-
- /*
- * Set the radio chip access register
- */
- switch (chan) {
- case CHANNEL_2GHZ:
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
- break;
- case CHANNEL_5GHZ:
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
- break;
- default:
- return 0;
- }
-
- mdelay(2);
-
- /* ...wait until PHY is ready and read the selected radio revision */
- ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
-
- for (i = 0; i < 8; i++)
- ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
-
- if (ah->ah_version == AR5K_AR5210) {
- srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
- ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
- } else {
- srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
- ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
- ((srev & 0x0f) << 4), 8);
- }
-
- /* Reset to the 5GHz mode */
- ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
-
- return ret;
-}
/*****************\
* Antenna control *
@@ -1836,12 +1949,10 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
- case CHANNEL_T:
case CHANNEL_XR:
ee_mode = AR5K_EEPROM_MODE_11A;
break;
case CHANNEL_G:
- case CHANNEL_TG:
ee_mode = AR5K_EEPROM_MODE_11G;
break;
case CHANNEL_B:
@@ -2275,20 +2386,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
- ctl_mode |= AR5K_CTL_11A;
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+ ctl_mode |= AR5K_CTL_TURBO;
+ else
+ ctl_mode |= AR5K_CTL_11A;
break;
case CHANNEL_G:
- ctl_mode |= AR5K_CTL_11G;
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+ ctl_mode |= AR5K_CTL_TURBOG;
+ else
+ ctl_mode |= AR5K_CTL_11G;
break;
case CHANNEL_B:
ctl_mode |= AR5K_CTL_11B;
break;
- case CHANNEL_T:
- ctl_mode |= AR5K_CTL_TURBO;
- break;
- case CHANNEL_TG:
- ctl_mode |= AR5K_CTL_TURBOG;
- break;
case CHANNEL_XR:
/* Fall through */
default:
@@ -2990,9 +3101,9 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr,
/*
* Set transmission power
*/
-int
+static int
ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
- u8 ee_mode, u8 txpower)
+ u8 ee_mode, u8 txpower, bool fast)
{
struct ath5k_rate_pcal_info rate_info;
u8 type;
@@ -3011,6 +3122,9 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
/* Initialize TX power table */
switch (ah->ah_radio) {
+ case AR5K_RF5110:
+ /* TODO */
+ return 0;
case AR5K_RF5111:
type = AR5K_PWRTABLE_PWR_TO_PCDAC;
break;
@@ -3028,10 +3142,15 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
return -EINVAL;
}
- /* FIXME: Only on channel/mode change */
- ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type);
- if (ret)
- return ret;
+ /* If fast is set it means we are on the same channel/mode
+ * so there is no need to recalculate the powertable, we 'll
+ * just use the cached one */
+ if (!fast) {
+ ret = ath5k_setup_channel_powertable(ah, channel,
+ ee_mode, type);
+ if (ret)
+ return ret;
+ }
/* Limit max power if we have a CTL available */
ath5k_get_max_ctl_power(ah, channel);
@@ -3092,12 +3211,10 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
switch (channel->hw_value & CHANNEL_MODES) {
case CHANNEL_A:
- case CHANNEL_T:
case CHANNEL_XR:
ee_mode = AR5K_EEPROM_MODE_11A;
break;
case CHANNEL_G:
- case CHANNEL_TG:
ee_mode = AR5K_EEPROM_MODE_11G;
break;
case CHANNEL_B:
@@ -3112,5 +3229,229 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower)
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
"changing txpower to %d\n", txpower);
- return ath5k_hw_txpower(ah, channel, ee_mode, txpower);
+ return ath5k_hw_txpower(ah, channel, ee_mode, txpower, true);
+}
+
+/*************\
+ Init function
+\*************/
+
+int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ u8 mode, u8 ee_mode, u8 freq, bool fast)
+{
+ struct ieee80211_channel *curr_channel;
+ int ret, i;
+ u32 phy_tst1;
+ bool fast_txp;
+ ret = 0;
+
+ /*
+ * Sanity check for fast flag
+ * Don't try fast channel change when changing modulation
+ * mode/band. We check for chip compatibility on
+ * ath5k_hw_reset.
+ */
+ curr_channel = ah->ah_current_channel;
+ if (fast && (channel->hw_value != curr_channel->hw_value))
+ return -EINVAL;
+
+ /*
+ * On fast channel change we only set the synth parameters
+ * while PHY is running, enable calibration and skip the rest.
+ */
+ if (fast) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
+ AR5K_PHY_RFBUS_REQ_REQUEST);
+ for (i = 0; i < 100; i++) {
+ if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT))
+ break;
+ udelay(5);
+ }
+ /* Failed */
+ if (i >= 100)
+ return -EIO;
+ }
+
+ /*
+ * If we don't change channel/mode skip
+ * tx powertable calculation and use the
+ * cached one.
+ */
+ if ((channel->hw_value == curr_channel->hw_value) &&
+ (channel->center_freq == curr_channel->center_freq))
+ fast_txp = true;
+ else
+ fast_txp = false;
+
+ /*
+ * Set TX power
+ *
+ * Note: We need to do that before we set
+ * RF buffer settings on 5211/5212+ so that we
+ * properly set curve indices.
+ */
+ ret = ath5k_hw_txpower(ah, channel, ee_mode,
+ ah->ah_txpower.txp_max_pwr / 2,
+ fast_txp);
+ if (ret)
+ return ret;
+
+ /*
+ * For 5210 we do all initialization using
+ * initvals, so we don't have to modify
+ * any settings (5210 also only supports
+ * a/aturbo modes)
+ */
+ if ((ah->ah_version != AR5K_AR5210) && !fast) {
+
+ /*
+ * Write initial RF gain settings
+ * This should work for both 5111/5112
+ */
+ ret = ath5k_hw_rfgain_init(ah, freq);
+ if (ret)
+ return ret;
+
+ mdelay(1);
+
+ /*
+ * Write RF buffer
+ */
+ ret = ath5k_hw_rfregs_init(ah, channel, mode);
+ if (ret)
+ return ret;
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+ channel->hw_value & CHANNEL_OFDM) {
+
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+
+ /* Spur info is available only from EEPROM versions
+ * greater than 5.3, but the EEPROM routines will use
+ * static values for older versions */
+ if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
+ ath5k_hw_set_spur_mitigation_filter(ah,
+ channel);
+ }
+
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+ if (mode == AR5K_MODE_11B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ }
+
+ } else if (ah->ah_version == AR5K_AR5210) {
+ mdelay(1);
+ /* Disable phy and wait */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+ mdelay(1);
+ }
+
+ /* Set channel on PHY */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable the PHY and wait until completion
+ * This includes BaseBand and Synthesizer
+ * activation.
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+ /*
+ * On 5211+ read activation -> rx delay
+ * and use it.
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ u32 delay;
+ delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+ delay = (channel->hw_value & CHANNEL_CCK) ?
+ ((delay << 2) / 22) : (delay / 10);
+ if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
+ delay = delay << 1;
+ if (ah->ah_bwmode == AR5K_BWMODE_5MHZ)
+ delay = delay << 2;
+ /* XXX: /2 on turbo ? Let's be safe
+ * for now */
+ udelay(100 + delay);
+ } else {
+ mdelay(1);
+ }
+
+ if (fast)
+ /*
+ * Release RF Bus grant
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ,
+ AR5K_PHY_RFBUS_REQ_REQUEST);
+ else {
+ /*
+ * Perform ADC test to see if baseband is ready
+ * Set tx hold and check adc test register
+ */
+ phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
+ ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
+ for (i = 0; i <= 20; i++) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
+ break;
+ udelay(200);
+ }
+ ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
+ }
+
+ /*
+ * Start automatic gain control calibration
+ *
+ * During AGC calibration RX path is re-routed to
+ * a power detector so we don't receive anything.
+ *
+ * This method is used to calibrate some static offsets
+ * used together with on-the fly I/Q calibration (the
+ * one performed via ath5k_hw_phy_calibrate), which doesn't
+ * interrupt rx path.
+ *
+ * While rx path is re-routed to the power detector we also
+ * start a noise floor calibration to measure the
+ * card's noise floor (the noise we measure when we are not
+ * transmitting or receiving anything).
+ *
+ * If we are in a noisy environment, AGC calibration may time
+ * out and/or noise floor calibration might timeout.
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
+
+ /* At the same time start I/Q calibration for QAM constellation
+ * -no need for CCK- */
+ ah->ah_calibration = false;
+ if (!(mode == AR5K_MODE_11B)) {
+ ah->ah_calibration = true;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_RUN);
+ }
+
+ /* Wait for gain calibration to finish (we check for I/Q calibration
+ * during ath5k_phy_calibrate) */
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, false)) {
+ ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
+ channel->center_freq);
+ }
+
+ /* Restore antenna mode */
+ ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
+
+ return ret;
}
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 84c717ded1c5..1849eee8235c 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -25,14 +25,52 @@ Queue Control Unit, DFS Control Unit Functions
#include "debug.h"
#include "base.h"
+
+/******************\
+* Helper functions *
+\******************/
+
/*
- * Get properties for a transmit queue
+ * Get number of pending frames
+ * for a specific queue [5211+]
*/
-int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
- struct ath5k_txq_info *queue_info)
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
{
- memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
- return 0;
+ u32 pending;
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return false;
+
+ /* XXX: How about AR5K_CFG_TXCNT ? */
+ if (ah->ah_version == AR5K_AR5210)
+ return false;
+
+ pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
+ pending &= AR5K_QCU_STS_FRMPENDCNT;
+
+ /* It's possible to have no frames pending even if TXE
+ * is set. To indicate that q has not stopped return
+ * true */
+ if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ return true;
+
+ return pending;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
+ return;
+
+ /* This queue will be skipped in further operations */
+ ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
+ /*For SIMR setup*/
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
}
/*
@@ -50,6 +88,16 @@ static u16 ath5k_cw_validate(u16 cw_req)
}
/*
+ * Get properties for a transmit queue
+ */
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
+ struct ath5k_txq_info *queue_info)
+{
+ memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
+ return 0;
+}
+
+/*
* Set properties for a transmit queue
*/
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
@@ -172,113 +220,18 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
return queue;
}
-/*
- * Get number of pending frames
- * for a specific queue [5211+]
- */
-u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
-{
- u32 pending;
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- /* Return if queue is declared inactive */
- if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return false;
-
- /* XXX: How about AR5K_CFG_TXCNT ? */
- if (ah->ah_version == AR5K_AR5210)
- return false;
-
- pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue));
- pending &= AR5K_QCU_STS_FRMPENDCNT;
-
- /* It's possible to have no frames pending even if TXE
- * is set. To indicate that q has not stopped return
- * true */
- if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
- return true;
-
- return pending;
-}
-
-/*
- * Set a transmit queue inactive
- */
-void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
-{
- if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
- return;
- /* This queue will be skipped in further operations */
- ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
- /*For SIMR setup*/
- AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
-}
+/*******************************\
+* Single QCU/DCU initialization *
+\*******************************/
/*
- * Set DFS properties for a transmit queue on DCU
+ * Set tx retry limits on DCU
*/
-int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+ unsigned int queue)
{
u32 retry_lg, retry_sh;
- struct ath5k_txq_info *tq = &ah->ah_txq[queue];
-
- AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
-
- tq = &ah->ah_txq[queue];
-
- if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
- return 0;
-
- if (ah->ah_version == AR5K_AR5210) {
- /* Only handle data queues, others will be ignored */
- if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
- return 0;
-
- /* Set Slot time */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
- AR5K_SLOT_TIME);
- /* Set ACK_CTS timeout */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
- AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
- /* Set Transmit Latency */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_TRANSMIT_LATENCY_TURBO :
- AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
-
- /* Set IFS0 */
- if (ah->ah_turbo) {
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
- tq->tqi_aifs * AR5K_INIT_SLOT_TIME_TURBO) <<
- AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
- AR5K_IFS0);
- } else {
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
- tq->tqi_aifs * AR5K_INIT_SLOT_TIME) <<
- AR5K_IFS0_DIFS_S) |
- AR5K_INIT_SIFS, AR5K_IFS0);
- }
-
- /* Set IFS1 */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
- AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
- /* Set AR5K_PHY_SETTLING */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
- | 0x38 :
- (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
- | 0x1C,
- AR5K_PHY_SETTLING);
- /* Set Frame Control Register */
- ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
- AR5K_PHY_TURBO_SHORT | 0x2020) :
- (AR5K_PHY_FRAME_CTL_INI | 0x1020),
- AR5K_PHY_FRAME_CTL_5210);
- }
/*
* Calculate and set retry limits
@@ -293,8 +246,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
retry_sh = AR5K_INIT_SH_RETRY;
}
- /*No QCU/DCU [5210]*/
+ /* Single data queue on AR5210 */
if (ah->ah_version == AR5K_AR5210) {
+ struct ath5k_txq_info *tq = &ah->ah_txq[queue];
+
+ if (queue > 0)
+ return;
+
ath5k_hw_reg_write(ah,
(tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
@@ -304,8 +262,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
AR5K_NODCU_RETRY_LMT);
+ /* DCU on AR5211+ */
} else {
- /*QCU/DCU [5211+]*/
ath5k_hw_reg_write(ah,
AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
AR5K_DCU_RETRY_LMT_SLG_RETRY) |
@@ -314,219 +272,393 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+ }
+ return;
+}
+
+/**
+ * ath5k_hw_reset_tx_queue - Initialize a single hw queue
+ *
+ * @ah The &struct ath5k_hw
+ * @queue The hw queue number
+ *
+ * Set DFS properties for the given transmit queue on DCU
+ * and configures all queue-specific parameters.
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ struct ath5k_txq_info *tq = &ah->ah_txq[queue];
- /*===Rest is also for QCU/DCU only [5211+]===*/
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
- /*
- * Set contention window (cw_min/cw_max)
- * and arbitrated interframe space (aifs)...
- */
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
- AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
- AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
- AR5K_QUEUE_DFS_LOCAL_IFS(queue));
-
- /*
- * Set misc registers
- */
- /* Enable DCU early termination for this queue */
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_DCU_EARLY);
+ tq = &ah->ah_txq[queue];
+
+ /* Skip if queue inactive or if we are on AR5210
+ * that doesn't have QCU/DCU */
+ if ((ah->ah_version == AR5K_AR5210) ||
+ (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE))
+ return 0;
+
+ /*
+ * Set contention window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set tx retry limits for this queue
+ */
+ ath5k_hw_set_tx_retry_limits(ah, queue);
+
+
+ /*
+ * Set misc registers
+ */
+
+ /* Enable DCU to wait for next fragment from QCU */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_DCU_MISC_FRAG_WAIT);
- /* Enable DCU to wait for next fragment from QCU */
+ /* On Maui and Spirit use the global seqnum on DCU */
+ if (ah->ah_mac_version < AR5K_SREV_AR5211)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- AR5K_DCU_MISC_FRAG_WAIT);
-
- /* On Maui and Spirit use the global seqnum on DCU */
- if (ah->ah_mac_version < AR5K_SREV_AR5211)
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- AR5K_DCU_MISC_SEQNUM_CTL);
-
- if (tq->tqi_cbr_period) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
- AR5K_QCU_CBRCFG_INTVAL) |
- AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
- AR5K_QCU_CBRCFG_ORN_THRES),
- AR5K_QUEUE_CBRCFG(queue));
+ AR5K_DCU_MISC_SEQNUM_CTL);
+
+ /* Constant bit rate period */
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+
+ if (tq->tqi_cbr_overflow_limit)
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_CBR);
- if (tq->tqi_cbr_overflow_limit)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_CBR_THRES_ENABLE);
- }
+ }
- if (tq->tqi_ready_time &&
- (tq->tqi_type != AR5K_TX_QUEUE_CAB))
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
- AR5K_QCU_RDYTIMECFG_INTVAL) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
-
- if (tq->tqi_burst_time) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
- AR5K_DCU_CHAN_TIME_DUR) |
- AR5K_DCU_CHAN_TIME_ENABLE,
- AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
-
- if (tq->tqi_flags
- & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
- AR5K_REG_ENABLE_BITS(ah,
- AR5K_QUEUE_MISC(queue),
+ /* Ready time interval */
+ if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB))
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_RDY_VEOL_POLICY);
- }
+ }
- if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
- AR5K_QUEUE_DFS_MISC(queue));
+ /* Enable/disable Post frame backoff */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));
- if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
- ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
- AR5K_QUEUE_DFS_MISC(queue));
+ /* Enable/disable fragmentation burst backoff */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));
- /*
- * Set registers by queue type
- */
- switch (tq->tqi_type) {
- case AR5K_TX_QUEUE_BEACON:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ /*
+ * Set registers by queue type
+ */
+ switch (tq->tqi_type) {
+ case AR5K_TX_QUEUE_BEACON:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
AR5K_QCU_MISC_FRSHED_DBA_GT |
AR5K_QCU_MISC_CBREXP_BCN_DIS |
AR5K_QCU_MISC_BCN_ENABLE);
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
AR5K_DCU_MISC_ARBLOCK_CTL_S) |
AR5K_DCU_MISC_ARBLOCK_IGNORE |
AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
AR5K_DCU_MISC_BCN_ENABLE);
- break;
+ break;
- case AR5K_TX_QUEUE_CAB:
- /* XXX: use BCN_SENT_GT, if we can figure out how */
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_FRSHED_DBA_GT |
- AR5K_QCU_MISC_CBREXP_DIS |
- AR5K_QCU_MISC_CBREXP_BCN_DIS);
+ case AR5K_TX_QUEUE_CAB:
+ /* XXX: use BCN_SENT_GT, if we can figure out how */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP_DIS |
+ AR5K_QCU_MISC_CBREXP_BCN_DIS);
- ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
- (AR5K_TUNE_SW_BEACON_RESP -
- AR5K_TUNE_DMA_BEACON_RESP) -
+ ath5k_hw_reg_write(ah, ((tq->tqi_ready_time -
+ (AR5K_TUNE_SW_BEACON_RESP -
+ AR5K_TUNE_DMA_BEACON_RESP) -
AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
- AR5K_QCU_RDYTIMECFG_ENABLE,
- AR5K_QUEUE_RDYTIMECFG(queue));
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
- (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
- AR5K_DCU_MISC_ARBLOCK_CTL_S));
- break;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S));
+ break;
- case AR5K_TX_QUEUE_UAPSD:
- AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
- AR5K_QCU_MISC_CBREXP_DIS);
- break;
+ case AR5K_TX_QUEUE_UAPSD:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBREXP_DIS);
+ break;
- case AR5K_TX_QUEUE_DATA:
- default:
+ case AR5K_TX_QUEUE_DATA:
+ default:
break;
- }
-
- /* TODO: Handle frame compression */
-
- /*
- * Enable interrupts for this tx queue
- * in the secondary interrupt mask registers
- */
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
-
- if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
- AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
-
- /* Update secondary interrupt mask registers */
-
- /* Filter out inactive queues */
- ah->ah_txq_imr_txok &= ah->ah_txq_status;
- ah->ah_txq_imr_txerr &= ah->ah_txq_status;
- ah->ah_txq_imr_txurn &= ah->ah_txq_status;
- ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
- ah->ah_txq_imr_txeol &= ah->ah_txq_status;
- ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
- ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
- ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
- ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
-
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
- AR5K_SIMR0_QCU_TXOK) |
- AR5K_REG_SM(ah->ah_txq_imr_txdesc,
- AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
- AR5K_SIMR1_QCU_TXERR) |
- AR5K_REG_SM(ah->ah_txq_imr_txeol,
- AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
- /* Update simr2 but don't overwrite rest simr2 settings */
- AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
- AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
- AR5K_REG_SM(ah->ah_txq_imr_txurn,
- AR5K_SIMR2_QCU_TXURN));
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
- AR5K_SIMR3_QCBRORN) |
- AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
- AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
- AR5K_SIMR4_QTRIG), AR5K_SIMR4);
- /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
- AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
- /* No queue has TXNOFRM enabled, disable the interrupt
- * by setting AR5K_TXNOFRM to zero */
- if (ah->ah_txq_imr_nofrm == 0)
- ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
-
- /* Set QCU mask for this DCU to save power */
- AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
}
+ /* TODO: Handle frame compression */
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
+
+ /* Update secondary interrupt mask registers */
+
+ /* Filter out inactive queues */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+ ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC),
+ AR5K_SIMR0);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL),
+ AR5K_SIMR1);
+
+ /* Update SIMR2 but don't overwrite rest simr2 settings */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+ AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN));
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+ AR5K_SIMR3_QCBRORN) |
+ AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+ AR5K_SIMR3_QCBRURN),
+ AR5K_SIMR3);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+ AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+
+ /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+ AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+
+ /* No queue has TXNOFRM enabled, disable the interrupt
+ * by setting AR5K_TXNOFRM to zero */
+ if (ah->ah_txq_imr_nofrm == 0)
+ ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
+
+ /* Set QCU mask for this DCU to save power */
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
+
return 0;
}
-/*
- * Set slot time on DCU
+
+/**************************\
+* Global QCU/DCU functions *
+\**************************/
+
+/**
+ * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU
+ *
+ * @ah The &struct ath5k_hw
+ * @slot_time Slot time in us
+ *
+ * Sets the global IFS intervals on DCU (also works on AR5210) for
+ * the given slot time and the current bwmode.
*/
-int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
{
+ struct ieee80211_channel *channel = ah->ah_current_channel;
+ struct ath5k_softc *sc = ah->ah_sc;
+ struct ieee80211_rate *rate;
+ u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock;
u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time);
if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX)
return -EINVAL;
- if (ah->ah_version == AR5K_AR5210)
- ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
+ sifs = ath5k_hw_get_default_sifs(ah);
+ sifs_clock = ath5k_hw_htoclock(ah, sifs);
+
+ /* EIFS
+ * Txtime of ack at lowest rate + SIFS + DIFS
+ * (DIFS = SIFS + 2 * Slot time)
+ *
+ * Note: HAL has some predefined values for EIFS
+ * Turbo: (37 + 2 * 6)
+ * Default: (74 + 2 * 9)
+ * Half: (149 + 2 * 13)
+ * Quarter: (298 + 2 * 21)
+ *
+ * (74 + 2 * 6) for AR5210 default and turbo !
+ *
+ * According to the formula we have
+ * ack_tx_time = 25 for turbo and
+ * ack_tx_time = 42.5 * clock multiplier
+ * for default/half/quarter.
+ *
+ * This can't be right, 42 is what we would get
+ * from ath5k_hw_get_frame_dur_for_bwmode or
+ * ieee80211_generic_frame_duration for zero frame
+ * length and without SIFS !
+ *
+ * Also we have different lowest rate for 802.11a
+ */
+ if (channel->hw_value & CHANNEL_5GHZ)
+ rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
else
- ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+ rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
+
+ ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate);
+
+ /* ack_tx_time includes an SIFS already */
+ eifs = ack_tx_time + sifs + 2 * slot_time;
+ eifs_clock = ath5k_hw_htoclock(ah, eifs);
+
+ /* Set IFS settings on AR5210 */
+ if (ah->ah_version == AR5K_AR5210) {
+ u32 pifs, pifs_clock, difs, difs_clock;
+
+ /* Set slot time */
+ ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME);
+
+ /* Set EIFS */
+ eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS);
+
+ /* PIFS = Slot time + SIFS */
+ pifs = slot_time + sifs;
+ pifs_clock = ath5k_hw_htoclock(ah, pifs);
+ pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS);
+
+ /* DIFS = SIFS + 2 * Slot time */
+ difs = sifs + 2 * slot_time;
+ difs_clock = ath5k_hw_htoclock(ah, difs);
+
+ /* Set SIFS/DIFS */
+ ath5k_hw_reg_write(ah, (difs_clock <<
+ AR5K_IFS0_DIFS_S) | sifs_clock,
+ AR5K_IFS0);
+
+ /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */
+ ath5k_hw_reg_write(ah, pifs_clock | eifs_clock |
+ (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S),
+ AR5K_IFS1);
+
+ return 0;
+ }
+
+ /* Set IFS slot time */
+ ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT);
+
+ /* Set EIFS interval */
+ ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS);
+
+ /* Set SIFS interval in usecs */
+ AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+ AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC,
+ sifs);
+
+ /* Set SIFS interval in clock cycles */
+ ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS);
return 0;
}
+
+int ath5k_hw_init_queues(struct ath5k_hw *ah)
+{
+ int i, ret;
+
+ /* TODO: HW Compression support for data queues */
+ /* TODO: Burst prefetch for data queues */
+
+ /*
+ * Reset queues and start beacon timers at the end of the reset routine
+ * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
+ * Note: If we want we can assign multiple qcus on one dcu.
+ */
+ if (ah->ah_version != AR5K_AR5210)
+ for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+ ret = ath5k_hw_reset_tx_queue(ah, i);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "failed to reset TX queue #%d\n", i);
+ return ret;
+ }
+ }
+ else
+ /* No QCU/DCU on AR5210, just set tx
+ * retry limits. We set IFS parameters
+ * on ath5k_hw_set_ifs_intervals */
+ ath5k_hw_set_tx_retry_limits(ah, 0);
+
+ /* Set the turbo flag when operating on 40MHz */
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+ AR5K_DCU_GBL_IFS_MISC_TURBO_MODE);
+
+ /* If we didn't set IFS timings through
+ * ath5k_hw_set_coverage_class make sure
+ * we set them here */
+ if (!ah->ah_coverage_class) {
+ unsigned int slot_time = ath5k_hw_get_default_slottime(ah);
+ ath5k_hw_set_ifs_intervals(ah, slot_time);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index ca79ecd832fd..7ad05d401ab5 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -787,6 +787,7 @@
#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */
#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */
#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S 4
#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */
#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10
#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */
@@ -1311,7 +1312,7 @@
#define AR5K_IFS1_EIFS 0x03fff000
#define AR5K_IFS1_EIFS_S 12
#define AR5K_IFS1_CS_EN 0x04000000
-
+#define AR5K_IFS1_CS_EN_S 26
/*
* CFP duration register
@@ -2058,6 +2059,7 @@
#define AR5K_PHY_SCAL 0x9878
#define AR5K_PHY_SCAL_32MHZ 0x0000000e
+#define AR5K_PHY_SCAL_32MHZ_5311 0x00000008
#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a
#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032
@@ -2244,6 +2246,8 @@
#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
/*---[5111+]---*/
+#define AR5K_PHY_FRAME_CTL_WIN_LEN 0x00000003 /* Force window length (?) */
+#define AR5K_PHY_FRAME_CTL_WIN_LEN_S 0
#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */
#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */
@@ -2558,3 +2562,28 @@
*/
#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280
#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * Platform registers for WiSoC
+ */
+#define AR5K_AR5312_RESET 0xbc003020
+#define AR5K_AR5312_RESET_BB0_COLD 0x00000004
+#define AR5K_AR5312_RESET_BB1_COLD 0x00000200
+#define AR5K_AR5312_RESET_WMAC0 0x00002000
+#define AR5K_AR5312_RESET_BB0_WARM 0x00004000
+#define AR5K_AR5312_RESET_WMAC1 0x00020000
+#define AR5K_AR5312_RESET_BB1_WARM 0x00040000
+
+#define AR5K_AR5312_ENABLE 0xbc003080
+#define AR5K_AR5312_ENABLE_WLAN0 0x00000001
+#define AR5K_AR5312_ENABLE_WLAN1 0x00000008
+
+#define AR5K_AR2315_RESET 0xb1000004
+#define AR5K_AR2315_RESET_WMAC 0x00000001
+#define AR5K_AR2315_RESET_BB_WARM 0x00000002
+
+#define AR5K_AR2315_AHB_ARB_CTL 0xb1000008
+#define AR5K_AR2315_AHB_ARB_CTL_WLAN 0x00000002
+
+#define AR5K_AR2315_BYTESWAP 0xb100000c
+#define AR5K_AR2315_BYTESWAP_WMAC 0x00000002
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 5b179d01f97d..bc84aaa31446 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -27,11 +27,17 @@
#include <linux/pci.h> /* To determine if a card is pci-e */
#include <linux/log2.h>
+#include <linux/platform_device.h>
#include "ath5k.h"
#include "reg.h"
#include "base.h"
#include "debug.h"
+
+/******************\
+* Helper functions *
+\******************/
+
/*
* Check if a register write has been completed
*/
@@ -53,146 +59,267 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
return (i <= 0) ? -EAGAIN : 0;
}
+
+/*************************\
+* Clock related functions *
+\*************************/
+
/**
- * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ * ath5k_hw_htoclock - Translate usec to hw clock units
*
- * @ah: the &struct ath5k_hw
- * @channel: the currently set channel upon reset
- *
- * Write the delta slope coefficient (used on pilot tracking ?) for OFDM
- * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset().
+ * @ah: The &struct ath5k_hw
+ * @usec: value in microseconds
+ */
+unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
+{
+ struct ath_common *common = ath5k_hw_common(ah);
+ return usec * common->clockrate;
+}
+
+/**
+ * ath5k_hw_clocktoh - Translate hw clock units to usec
+ * @clock: value in hw clock units
+ */
+unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
+{
+ struct ath_common *common = ath5k_hw_common(ah);
+ return clock / common->clockrate;
+}
+
+/**
+ * ath5k_hw_init_core_clock - Initialize core clock
*
- * Since delta slope is floating point we split it on its exponent and
- * mantissa and provide these values on hw.
+ * @ah The &struct ath5k_hw
*
- * For more infos i think this patent is related
- * http://www.freepatentsonline.com/7184495.html
+ * Initialize core clock parameters (usec, usec32, latencies etc).
*/
-static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
- struct ieee80211_channel *channel)
+static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
{
- /* Get exponent and mantissa and set it */
- u32 coef_scaled, coef_exp, coef_man,
- ds_coef_exp, ds_coef_man, clock;
-
- BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
- !(channel->hw_value & CHANNEL_OFDM));
-
- /* Get coefficient
- * ALGO: coef = (5 * clock / carrier_freq) / 2
- * we scale coef by shifting clock value by 24 for
- * better precision since we use integers */
- /* TODO: Half/quarter rate */
- clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40;
- coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq;
-
- /* Get exponent
- * ALGO: coef_exp = 14 - highest set bit position */
- coef_exp = ilog2(coef_scaled);
-
- /* Doesn't make sense if it's zero*/
- if (!coef_scaled || !coef_exp)
- return -EINVAL;
+ struct ieee80211_channel *channel = ah->ah_current_channel;
+ struct ath_common *common = ath5k_hw_common(ah);
+ u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs;
+
+ /*
+ * Set core clock frequency
+ */
+ if (channel->hw_value & CHANNEL_5GHZ)
+ clock = 40; /* 802.11a */
+ else if (channel->hw_value & CHANNEL_CCK)
+ clock = 22; /* 802.11b */
+ else
+ clock = 44; /* 802.11g */
+
+ /* Use clock multiplier for non-default
+ * bwmode */
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_40MHZ:
+ clock *= 2;
+ break;
+ case AR5K_BWMODE_10MHZ:
+ clock /= 2;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ clock /= 4;
+ break;
+ default:
+ break;
+ }
- /* Note: we've shifted coef_scaled by 24 */
- coef_exp = 14 - (coef_exp - 24);
+ common->clockrate = clock;
+ /*
+ * Set USEC parameters
+ */
+ /* Set USEC counter on PCU*/
+ usec = clock - 1;
+ usec = AR5K_REG_SM(usec, AR5K_USEC_1);
- /* Get mantissa (significant digits)
- * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */
- coef_man = coef_scaled +
- (1 << (24 - coef_exp - 1));
+ /* Set usec duration on DCU */
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC,
+ AR5K_DCU_GBL_IFS_MISC_USEC_DUR,
+ clock);
- /* Calculate delta slope coefficient exponent
- * and mantissa (remove scaling) and set them on hw */
- ds_coef_man = coef_man >> (24 - coef_exp);
- ds_coef_exp = coef_exp - 16;
+ /* Set 32MHz USEC counter */
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_radio == AR5K_RF2317))
+ /* Remain on 40MHz clock ? */
+ sclock = 40 - 1;
+ else
+ sclock = 32 - 1;
+ sclock = AR5K_REG_SM(sclock, AR5K_USEC_32);
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
- AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
- AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+ /*
+ * Set tx/rx latencies
+ */
+ usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
+ txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211);
+ rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211);
- return 0;
-}
+ /*
+ * 5210 initvals don't include usec settings
+ * so we need to use magic values here for
+ * tx/rx latencies
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ /* same for turbo */
+ txlat = AR5K_INIT_TX_LATENCY_5210;
+ rxlat = AR5K_INIT_RX_LATENCY_5210;
+ }
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ /* 5311 has different tx/rx latency masks
+ * from 5211, since we deal 5311 the same
+ * as 5211 when setting initvals, shift
+ * values here to their proper locations
+ *
+ * Note: Initvals indicate tx/rx/ latencies
+ * are the same for turbo mode */
+ txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210);
+ rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210);
+ } else
+ switch (ah->ah_bwmode) {
+ case AR5K_BWMODE_10MHZ:
+ txlat = AR5K_REG_SM(txlat * 2,
+ AR5K_USEC_TX_LATENCY_5211);
+ rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
+ AR5K_USEC_RX_LATENCY_5211);
+ txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ;
+ break;
+ case AR5K_BWMODE_5MHZ:
+ txlat = AR5K_REG_SM(txlat * 4,
+ AR5K_USEC_TX_LATENCY_5211);
+ rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX,
+ AR5K_USEC_RX_LATENCY_5211);
+ txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ;
+ break;
+ case AR5K_BWMODE_40MHZ:
+ txlat = AR5K_INIT_TX_LAT_MIN;
+ rxlat = AR5K_REG_SM(rxlat / 2,
+ AR5K_USEC_RX_LATENCY_5211);
+ txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT;
+ break;
+ default:
+ break;
+ }
-/*
- * index into rates for control rates, we can set it up like this because
- * this is only used for AR5212 and we know it supports G mode
- */
-static const unsigned int control_rates[] =
- { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 };
+ usec_reg = (usec | sclock | txlat | rxlat);
+ ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC);
-/**
- * ath5k_hw_write_rate_duration - fill rate code to duration table
- *
- * @ah: the &struct ath5k_hw
- * @mode: one of enum ath5k_driver_mode
- *
- * Write the rate code to duration table upon hw reset. This is a helper for
- * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on
- * the hardware, based on current mode, for each rate. The rates which are
- * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have
- * different rate code so we write their value twice (one for long preample
- * and one for short).
+ /* On 5112 set tx frane to tx data start delay */
+ if (ah->ah_radio == AR5K_RF5112) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,
+ AR5K_PHY_RF_CTL2_TXF2TXD_START,
+ txf2txs);
+ }
+}
+
+/*
+ * If there is an external 32KHz crystal available, use it
+ * as ref. clock instead of 32/40MHz clock and baseband clocks
+ * to save power during sleep or restore normal 32/40MHz
+ * operation.
*
- * Note: Band doesn't matter here, if we set the values for OFDM it works
- * on both a and g modes. So all we have to do is set values for all g rates
- * that include all OFDM and CCK rates. If we operate in turbo or xr/half/
- * quarter rate mode, we need to use another set of bitrates (that's why we
- * need the mode parameter) but we don't handle these proprietary modes yet.
+ * XXX: When operating on 32KHz certain PHY registers (27 - 31,
+ * 123 - 127) require delay on access.
*/
-static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
- unsigned int mode)
+static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
{
- struct ath5k_softc *sc = ah->ah_sc;
- struct ieee80211_rate *rate;
- unsigned int i;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 scal, spending;
- /* Write rate duration table */
- for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) {
- u32 reg;
- u16 tx_time;
+ /* Only set 32KHz settings if we have an external
+ * 32KHz crystal present */
+ if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
+ AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
+ enable) {
- rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]];
+ /* 1 usec/cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
+ /* Set up tsf increment on each cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
- /* Set ACK timeout */
- reg = AR5K_RATE_DUR(rate->hw_value);
+ /* Set baseband sleep control registers
+ * and sleep control rate */
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
- /* An ACK frame consists of 10 bytes. If you add the FCS,
- * which ieee80211_generic_frame_duration() adds,
- * its 14 bytes. Note we use the control rate and not the
- * actual rate for this rate. See mac80211 tx.c
- * 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,
- NULL, 10, rate));
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
- ath5k_hw_reg_write(ah, tx_time, reg);
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
+ } else {
+ ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
+ }
- if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE))
- continue;
+ /* Enable sleep clock operation */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
- /*
- * We're not distinguishing short preamble here,
- * This is true, all we'll get is a longer value here
- * which is not necessarilly bad. We could use
- * export ieee80211_frame_duration() but that needs to be
- * fixed first to be properly used by mac802111 drivers:
- *
- * - remove erp stuff and let the routine figure ofdm
- * erp rates
- * - remove passing argument ieee80211_local as
- * drivers don't have access to it
- * - move drivers using ieee80211_generic_frame_duration()
- * to this
- */
- ath5k_hw_reg_write(ah, tx_time,
- reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+ } else {
+
+ /* Disable sleep clock operation and
+ * restore default parameters */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_EN);
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
+
+ /* Set DAC/ADC delays */
+ ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+
+ if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
+ scal = AR5K_PHY_SCAL_32MHZ_2417;
+ else if (ee->ee_is_hb63)
+ scal = AR5K_PHY_SCAL_32MHZ_HB63;
+ else
+ scal = AR5K_PHY_SCAL_32MHZ;
+ ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
+
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+
+ if ((ah->ah_radio == AR5K_RF5112) ||
+ (ah->ah_radio == AR5K_RF5413) ||
+ (ah->ah_radio == AR5K_RF2316) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
+ spending = 0x14;
+ else
+ spending = 0x18;
+ ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
+
+ /* Set up tsf increment on each cycle */
+ AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
}
}
+
+/*********************\
+* Reset/Sleep control *
+\*********************/
+
/*
* Reset chipset
*/
@@ -236,6 +363,64 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
}
/*
+ * Reset AHB chipset
+ * AR5K_RESET_CTL_PCU flag resets WMAC
+ * AR5K_RESET_CTL_BASEBAND flag resets WBB
+ */
+static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
+{
+ u32 mask = flags ? flags : ~0U;
+ volatile u32 *reg;
+ u32 regval;
+ u32 val = 0;
+
+ /* ah->ah_mac_srev is not available at this point yet */
+ if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
+ reg = (u32 *) AR5K_AR2315_RESET;
+ if (mask & AR5K_RESET_CTL_PCU)
+ val |= AR5K_AR2315_RESET_WMAC;
+ if (mask & AR5K_RESET_CTL_BASEBAND)
+ val |= AR5K_AR2315_RESET_BB_WARM;
+ } else {
+ reg = (u32 *) AR5K_AR5312_RESET;
+ if (to_platform_device(ah->ah_sc->dev)->id == 0) {
+ if (mask & AR5K_RESET_CTL_PCU)
+ val |= AR5K_AR5312_RESET_WMAC0;
+ if (mask & AR5K_RESET_CTL_BASEBAND)
+ val |= AR5K_AR5312_RESET_BB0_COLD |
+ AR5K_AR5312_RESET_BB0_WARM;
+ } else {
+ if (mask & AR5K_RESET_CTL_PCU)
+ val |= AR5K_AR5312_RESET_WMAC1;
+ if (mask & AR5K_RESET_CTL_BASEBAND)
+ val |= AR5K_AR5312_RESET_BB1_COLD |
+ AR5K_AR5312_RESET_BB1_WARM;
+ }
+ }
+
+ /* Put BB/MAC into reset */
+ regval = __raw_readl(reg);
+ __raw_writel(regval | val, reg);
+ regval = __raw_readl(reg);
+ udelay(100);
+
+ /* Bring BB/MAC out of reset */
+ __raw_writel(regval & ~val, reg);
+ regval = __raw_readl(reg);
+
+ /*
+ * Reset configuration register (for hw byte-swap). Note that this
+ * is only set for big endian. We do the necessary magic in
+ * AR5K_INIT_CFG.
+ */
+ if ((flags & AR5K_RESET_CTL_PCU) == 0)
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+ return 0;
+}
+
+
+/*
* Sleep control
*/
static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
@@ -334,6 +519,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
u32 bus_flags;
int ret;
+ if (ath5k_get_bus_type(ah) == ATH_AHB)
+ return 0;
+
/* Make sure device is awake */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
if (ret) {
@@ -349,7 +537,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
* we ingore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+ bus_flags = (pdev && pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
if (ah->ah_version == AR5K_AR5210) {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
@@ -378,7 +566,6 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
/*
* Bring up MAC + PHY Chips and program PLL
- * TODO: Half/Quarter rate support
*/
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
{
@@ -390,11 +577,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
mode = 0;
clock = 0;
- /* Wakeup the device */
- ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
- return ret;
+ if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) {
+ /* Wakeup the device */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
}
/*
@@ -405,7 +594,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
* we ingore that flag for PCI-E cards. On PCI cards
* this flag gets cleared after 64 PCI clocks.
*/
- bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
+ bus_flags = (pdev && pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
if (ah->ah_version == AR5K_AR5210) {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
@@ -413,8 +602,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
mdelay(2);
} else {
- ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
- AR5K_RESET_CTL_BASEBAND | bus_flags);
+ if (ath5k_get_bus_type(ah) == ATH_AHB)
+ ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND);
+ else
+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
+ AR5K_RESET_CTL_BASEBAND | bus_flags);
}
if (ret) {
@@ -429,9 +622,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return ret;
}
- /* ...clear reset control register and pull device out of
- * warm reset */
- if (ath5k_hw_nic_reset(ah, 0)) {
+ /* ...reset configuration regiter on Wisoc ...
+ * ...clear reset control register and pull device out of
+ * warm reset on others */
+ if (ath5k_get_bus_type(ah) == ATH_AHB)
+ ret = ath5k_hw_wisoc_reset(ah, 0);
+ else
+ ret = ath5k_hw_nic_reset(ah, 0);
+
+ if (ret) {
ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
return -EIO;
}
@@ -466,7 +665,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
* CCK headers) operation. We need to test
* this, 5211 might support ofdm-only g after
* all, there are also initial register values
- * in the code for g mode (see initvals.c). */
+ * in the code for g mode (see initvals.c).
+ */
if (ah->ah_version == AR5K_AR5211)
mode |= AR5K_PHY_MODE_MOD_OFDM;
else
@@ -479,6 +679,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
} else if (flags & CHANNEL_5GHZ) {
mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+ /* Different PLL setting for 5413 */
if (ah->ah_radio == AR5K_RF5413)
clock = AR5K_PHY_PLL_40MHZ_5413;
else
@@ -496,12 +697,29 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return -EINVAL;
}
- if (flags & CHANNEL_TURBO)
- turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+ /*XXX: Can bwmode be used with dynamic mode ?
+ * (I don't think it supports 44MHz) */
+ /* On 2425 initvals TURBO_SHORT is not pressent */
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
+ turbo = AR5K_PHY_TURBO_MODE |
+ (ah->ah_radio == AR5K_RF2425) ? 0 :
+ AR5K_PHY_TURBO_SHORT;
+ } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) {
+ if (ah->ah_radio == AR5K_RF5413) {
+ mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
+ AR5K_PHY_MODE_HALF_RATE :
+ AR5K_PHY_MODE_QUARTER_RATE;
+ } else if (ah->ah_version == AR5K_AR5212) {
+ clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ?
+ AR5K_PHY_PLL_HALF_RATE :
+ AR5K_PHY_PLL_QUARTER_RATE;
+ }
+ }
+
} else { /* Reset the device */
/* ...enable Atheros turbo mode if requested */
- if (flags & CHANNEL_TURBO)
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
AR5K_PHY_TURBO);
}
@@ -522,107 +740,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
return 0;
}
-/*
- * If there is an external 32KHz crystal available, use it
- * as ref. clock instead of 32/40MHz clock and baseband clocks
- * to save power during sleep or restore normal 32/40MHz
- * operation.
- *
- * XXX: When operating on 32KHz certain PHY registers (27 - 31,
- * 123 - 127) require delay on access.
- */
-static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
-{
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- u32 scal, spending, usec32;
-
- /* Only set 32KHz settings if we have an external
- * 32KHz crystal present */
- if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) ||
- AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) &&
- enable) {
-
- /* 1 usec/cycle */
- AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1);
- /* Set up tsf increment on each cycle */
- AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61);
-
- /* Set baseband sleep control registers
- * and sleep control rate */
- ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
-
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
- spending = 0x14;
- else
- spending = 0x18;
- ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
- ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT);
- ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY);
- AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02);
- } else {
- ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT);
- ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY);
- AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03);
- }
-
- /* Enable sleep clock operation */
- AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_SLEEP_CLOCK_EN);
-
- } else {
-
- /* Disable sleep clock operation and
- * restore default parameters */
- AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_SLEEP_CLOCK_EN);
-
- AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG,
- AR5K_PCICFG_SLEEP_CLOCK_RATE, 0);
-
- ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR);
- ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
-
- if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
- scal = AR5K_PHY_SCAL_32MHZ_2417;
- else if (ee->ee_is_hb63)
- scal = AR5K_PHY_SCAL_32MHZ_HB63;
- else
- scal = AR5K_PHY_SCAL_32MHZ;
- ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
-
- ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
- spending = 0x14;
- else
- spending = 0x18;
- ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING);
-
- if ((ah->ah_radio == AR5K_RF5112) ||
- (ah->ah_radio == AR5K_RF5413))
- usec32 = 39;
- else
- usec32 = 31;
- AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32);
-
- AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
- }
-}
+/**************************************\
+* Post-initvals register modifications *
+\**************************************/
/* TODO: Half/Quarter rate */
static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
@@ -663,22 +784,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
AR5K_TXCFG_DCU_DBL_BUF_DIS);
- /* Set DAC/ADC delays */
- if (ah->ah_version == AR5K_AR5212) {
- u32 scal;
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))
- scal = AR5K_PHY_SCAL_32MHZ_2417;
- else if (ee->ee_is_hb63)
- scal = AR5K_PHY_SCAL_32MHZ_HB63;
- else
- scal = AR5K_PHY_SCAL_32MHZ;
- ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL);
- }
-
/* Set fast ADC */
if ((ah->ah_radio == AR5K_RF5413) ||
- (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
+ (ah->ah_radio == AR5K_RF2317) ||
+ (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) {
u32 fast_adc = true;
if (channel->center_freq == 2462 ||
@@ -706,26 +815,54 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
}
if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
- u32 usec_reg;
- /* 5311 has different tx/rx latency masks
- * from 5211, since we deal 5311 the same
- * as 5211 when setting initvals, shift
- * values here to their proper locations */
- usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211);
- ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 |
- AR5K_USEC_32 |
- AR5K_USEC_TX_LATENCY_5211 |
- AR5K_REG_SM(29,
- AR5K_USEC_RX_LATENCY_5210)),
- AR5K_USEC_5211);
/* Clear QCU/DCU clock gating register */
ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT);
/* Set DAC/ADC delays */
- ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311,
+ AR5K_PHY_SCAL);
/* Enable PCU FIFO corruption ECO */
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
AR5K_DIAG_SW_ECO_ENABLE);
}
+
+ if (ah->ah_bwmode) {
+ /* Increase PHY switch and AGC settling time
+ * on turbo mode (ath5k_hw_commit_eeprom_settings
+ * will override settling time if available) */
+ if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_AGC,
+ AR5K_AGC_SETTLING_TURBO);
+
+ /* XXX: Initvals indicate we only increase
+ * switch time on AR5212, 5211 and 5210
+ * only change agc time (bug?) */
+ if (ah->ah_version == AR5K_AR5212)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
+ AR5K_PHY_SETTLING_SWITCH,
+ AR5K_SWITCH_SETTLING_TURBO);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Set Frame Control Register */
+ ath5k_hw_reg_write(ah,
+ (AR5K_PHY_FRAME_CTL_INI |
+ AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
+ /* On 5413 PHY force window length for half/quarter rate*/
+ } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) &&
+ (ah->ah_mac_srev <= AR5K_SREV_AR5414)) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211,
+ AR5K_PHY_FRAME_CTL_WIN_LEN,
+ 3);
+ }
+ } else if (ah->ah_version == AR5K_AR5210) {
+ /* Set Frame Control Register for normal operation */
+ ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
}
static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
@@ -734,6 +871,10 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
s16 cck_ofdm_pwr_delta;
+ /* TODO: Add support for AR5210 EEPROM */
+ if (ah->ah_version == AR5K_AR5210)
+ return;
+
/* Adjust power delta for channel 14 */
if (channel->center_freq == 2484)
cck_ofdm_pwr_delta =
@@ -772,7 +913,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
AR5K_PHY_NFTHRES);
- if ((channel->hw_value & CHANNEL_TURBO) &&
+ if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) &&
(ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) {
/* Switch settling time (Turbo) */
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING,
@@ -870,143 +1011,183 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE);
}
-/*
- * Main reset function
- */
+
+/*********************\
+* Main reset function *
+\*********************/
+
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
- struct ieee80211_channel *channel, bool change_channel)
+ struct ieee80211_channel *channel, bool fast, bool skip_pcu)
{
- struct ath_common *common = ath5k_hw_common(ah);
- u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo;
- u32 phy_tst1;
+ u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
u8 mode, freq, ee_mode;
int i, ret;
ee_mode = 0;
- staid1_flags = 0;
tsf_up = 0;
tsf_lo = 0;
freq = 0;
mode = 0;
/*
- * Save some registers before a reset
+ * Sanity check for fast flag
+ * Fast channel change only available
+ * on AR2413/AR5413.
*/
- /*DCU/Antenna selection not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
+ if (fast && (ah->ah_radio != AR5K_RF2413) &&
+ (ah->ah_radio != AR5K_RF5413))
+ fast = 0;
- switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
- mode = AR5K_MODE_11A;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- case CHANNEL_G:
- mode = AR5K_MODE_11G;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
- break;
- case CHANNEL_B:
- mode = AR5K_MODE_11B;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11B;
- break;
- case CHANNEL_T:
- mode = AR5K_MODE_11A_TURBO;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- case CHANNEL_TG:
- if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
- "TurboG mode not available on 5211");
- return -EINVAL;
- }
- mode = AR5K_MODE_11G_TURBO;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
- break;
- case CHANNEL_XR:
- if (ah->ah_version == AR5K_AR5211) {
- ATH5K_ERR(ah->ah_sc,
- "XR mode not available on 5211");
- return -EINVAL;
- }
- mode = AR5K_MODE_XR;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
- break;
- default:
+ /* Disable sleep clock operation
+ * to avoid register access delay on certain
+ * PHY registers */
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_set_sleep_clock(ah, false);
+
+ /*
+ * Stop PCU
+ */
+ ath5k_hw_stop_rx_pcu(ah);
+
+ /*
+ * Stop DMA
+ *
+ * Note: If DMA didn't stop continue
+ * since only a reset will fix it.
+ */
+ ret = ath5k_hw_dma_stop(ah);
+
+ /* RF Bus grant won't work if we have pending
+ * frames */
+ if (ret && fast) {
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ "DMA didn't stop, falling back to normal reset\n");
+ fast = 0;
+ /* Non fatal, just continue with
+ * normal reset */
+ ret = 0;
+ }
+
+ switch (channel->hw_value & CHANNEL_MODES) {
+ case CHANNEL_A:
+ mode = AR5K_MODE_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ case CHANNEL_G:
+
+ if (ah->ah_version <= AR5K_AR5211) {
ATH5K_ERR(ah->ah_sc,
- "invalid channel: %d\n", channel->center_freq);
+ "G mode not available on 5210/5211");
return -EINVAL;
}
- if (change_channel) {
- /*
- * Save frame sequence count
- * For revs. after Oahu, only save
- * seq num for DCU 0 (Global seq num)
- */
- if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
-
- for (i = 0; i < 10; i++)
- s_seq[i] = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DCU_SEQNUM(i));
+ mode = AR5K_MODE_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ case CHANNEL_B:
- } else {
- s_seq[0] = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DCU_SEQNUM(0));
- }
+ if (ah->ah_version < AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "B mode not available on 5210");
+ return -EINVAL;
+ }
- /* TSF accelerates on AR5211 during reset
- * As a workaround save it here and restore
- * it later so that it's back in time after
- * reset. This way it'll get re-synced on the
- * next beacon without breaking ad-hoc.
- *
- * On AR5212 TSF is almost preserved across a
- * reset so it stays back in time anyway and
- * we don't have to save/restore it.
- *
- * XXX: Since this breaks power saving we have
- * to disable power saving until we receive the
- * next beacon, so we can resync beacon timers */
- if (ah->ah_version == AR5K_AR5211) {
- tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
- tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
- }
+ mode = AR5K_MODE_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "XR mode not available on 5211");
+ return -EINVAL;
}
+ mode = AR5K_MODE_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ ATH5K_ERR(ah->ah_sc,
+ "invalid channel: %d\n", channel->center_freq);
+ return -EINVAL;
+ }
- if (ah->ah_version == AR5K_AR5212) {
- /* Restore normal 32/40MHz clock operation
- * to avoid register access delay on certain
- * PHY registers */
- ath5k_hw_set_sleep_clock(ah, false);
+ /*
+ * If driver requested fast channel change and DMA has stopped
+ * go on. If it fails continue with a normal reset.
+ */
+ if (fast) {
+ ret = ath5k_hw_phy_init(ah, channel, mode,
+ ee_mode, freq, true);
+ if (ret) {
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
+ "fast chan change failed, falling back to normal reset\n");
+ /* Non fatal, can happen eg.
+ * on mode change */
+ ret = 0;
+ } else
+ return 0;
+ }
- /* Since we are going to write rf buffer
- * check if we have any pending gain_F
- * optimization settings */
- if (change_channel && ah->ah_rf_banks != NULL)
- ath5k_hw_gainf_calibrate(ah);
+ /*
+ * Save some registers before a reset
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Save frame sequence count
+ * For revs. after Oahu, only save
+ * seq num for DCU 0 (Global seq num)
+ */
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+
+ for (i = 0; i < 10; i++)
+ s_seq[i] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(i));
+
+ } else {
+ s_seq[0] = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
+
+ /* TSF accelerates on AR5211 during reset
+ * As a workaround save it here and restore
+ * it later so that it's back in time after
+ * reset. This way it'll get re-synced on the
+ * next beacon without breaking ad-hoc.
+ *
+ * On AR5212 TSF is almost preserved across a
+ * reset so it stays back in time anyway and
+ * we don't have to save/restore it.
+ *
+ * XXX: Since this breaks power saving we have
+ * to disable power saving until we receive the
+ * next beacon, so we can resync beacon timers */
+ if (ah->ah_version == AR5K_AR5211) {
+ tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
}
}
+
/*GPIOs*/
s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) &
AR5K_PCICFG_LEDSTATE;
s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
- /* AR5K_STA_ID1 flags, only preserve antenna
- * settings and ack/cts rate mode */
- staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) &
- (AR5K_STA_ID1_DEFAULT_ANTENNA |
- AR5K_STA_ID1_DESC_ANTENNA |
- AR5K_STA_ID1_RTS_DEF_ANTENNA |
- AR5K_STA_ID1_ACKCTS_6MB |
- AR5K_STA_ID1_BASE_RATE_11B |
- AR5K_STA_ID1_SELFGEN_DEF_ANT);
+
+ /*
+ * Since we are going to write rf buffer
+ * check if we have any pending gain_F
+ * optimization settings
+ */
+ if (ah->ah_version == AR5K_AR5212 &&
+ (ah->ah_radio <= AR5K_RF5112)) {
+ if (!fast && ah->ah_rf_banks != NULL)
+ ath5k_hw_gainf_calibrate(ah);
+ }
/* Wakeup the device */
ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
@@ -1021,121 +1202,42 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
AR5K_PHY(0));
/* Write initial settings */
- ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+ ret = ath5k_hw_write_initvals(ah, mode, skip_pcu);
if (ret)
return ret;
+ /* Initialize core clock settings */
+ ath5k_hw_init_core_clock(ah);
+
/*
- * 5211/5212 Specific
+ * Tweak initval settings for revised
+ * chipsets and add some more config
+ * bits
*/
- if (ah->ah_version != AR5K_AR5210) {
-
- /*
- * Write initial RF gain settings
- * This should work for both 5111/5112
- */
- ret = ath5k_hw_rfgain_init(ah, freq);
- if (ret)
- return ret;
-
- mdelay(1);
-
- /*
- * Tweak initval settings for revised
- * chipsets and add some more config
- * bits
- */
- ath5k_hw_tweak_initval_settings(ah, channel);
-
- /*
- * Set TX power
- */
- ret = ath5k_hw_txpower(ah, channel, ee_mode,
- ah->ah_txpower.txp_max_pwr / 2);
- if (ret)
- return ret;
+ ath5k_hw_tweak_initval_settings(ah, channel);
- /* Write rate duration table only on AR5212 and if
- * virtual interface has already been brought up
- * XXX: rethink this after new mode changes to
- * mac80211 are integrated */
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->nvifs)
- ath5k_hw_write_rate_duration(ah, mode);
+ /* Commit values from EEPROM */
+ ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
- /*
- * Write RF buffer
- */
- ret = ath5k_hw_rfregs_init(ah, channel, mode);
- if (ret)
- return ret;
-
-
- /* Write OFDM timings on 5212*/
- if (ah->ah_version == AR5K_AR5212 &&
- channel->hw_value & CHANNEL_OFDM) {
-
- ret = ath5k_hw_write_ofdm_timings(ah, channel);
- if (ret)
- return ret;
-
- /* Spur info is available only from EEPROM versions
- * greater than 5.3, but the EEPROM routines will use
- * static values for older versions */
- if (ah->ah_mac_srev >= AR5K_SREV_AR5424)
- ath5k_hw_set_spur_mitigation_filter(ah,
- channel);
- }
-
- /*Enable/disable 802.11b mode on 5111
- (enable 2111 frequency converter + CCK)*/
- if (ah->ah_radio == AR5K_RF5111) {
- if (mode == AR5K_MODE_11B)
- AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_B_MODE);
- else
- AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_B_MODE);
- }
-
- /* Commit values from EEPROM */
- ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode);
-
- } else {
- /*
- * For 5210 we do all initialization using
- * initvals, so we don't have to modify
- * any settings (5210 also only supports
- * a/aturbo modes)
- */
- mdelay(1);
- /* Disable phy and wait */
- ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
- mdelay(1);
- }
/*
* Restore saved values
*/
- /*DCU/Antenna selection not available on 5210*/
+ /* Seqnum, TSF */
if (ah->ah_version != AR5K_AR5210) {
+ if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
+ for (i = 0; i < 10; i++)
+ ath5k_hw_reg_write(ah, s_seq[i],
+ AR5K_QUEUE_DCU_SEQNUM(i));
+ } else {
+ ath5k_hw_reg_write(ah, s_seq[0],
+ AR5K_QUEUE_DCU_SEQNUM(0));
+ }
- if (change_channel) {
- if (ah->ah_mac_srev < AR5K_SREV_AR5211) {
- for (i = 0; i < 10; i++)
- ath5k_hw_reg_write(ah, s_seq[i],
- AR5K_QUEUE_DCU_SEQNUM(i));
- } else {
- ath5k_hw_reg_write(ah, s_seq[0],
- AR5K_QUEUE_DCU_SEQNUM(0));
- }
-
-
- if (ah->ah_version == AR5K_AR5211) {
- ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
- ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
- }
+ if (ah->ah_version == AR5K_AR5211) {
+ ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32);
+ ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32);
}
}
@@ -1146,203 +1248,34 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
- /* Restore sta_id flags and preserve our mac address*/
- ath5k_hw_reg_write(ah,
- get_unaligned_le32(common->macaddr),
- AR5K_STA_ID0);
- ath5k_hw_reg_write(ah,
- staid1_flags | get_unaligned_le16(common->macaddr + 4),
- AR5K_STA_ID1);
-
-
/*
- * Configure PCU
+ * Initialize PCU
*/
-
- /* Restore bssid and bssid mask */
- ath5k_hw_set_bssid(ah);
-
- /* Set PCU config */
- ath5k_hw_set_opmode(ah, op_mode);
-
- /* Clear any pending interrupts
- * PISR/SISR Not available on 5210 */
- if (ah->ah_version != AR5K_AR5210)
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
-
- /* Set RSSI/BRSSI thresholds
- *
- * Note: If we decide to set this value
- * dynamically, keep in mind that when AR5K_RSSI_THR
- * register is read, it might return 0x40 if we haven't
- * written anything to it. Also, BMISS RSSI threshold is zeroed.
- * So doing a save/restore procedure here isn't the right
- * choice. Instead, store it in ath5k_hw */
- ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES |
- AR5K_TUNE_BMISS_THRES <<
- AR5K_RSSI_THR_BMISS_S),
- AR5K_RSSI_THR);
-
- /* MIC QoS support */
- if (ah->ah_mac_srev >= AR5K_SREV_AR2413) {
- ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL);
- ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL);
- }
-
- /* QoS NOACK Policy */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah,
- AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) |
- AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) |
- AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET),
- AR5K_QOS_NOACK);
- }
-
+ ath5k_hw_pcu_init(ah, op_mode, mode);
/*
- * Configure PHY
+ * Initialize PHY
*/
-
- /* Set channel on PHY */
- ret = ath5k_hw_channel(ah, channel);
- if (ret)
+ ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq, false);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "failed to initialize PHY (%i) !\n", ret);
return ret;
-
- /*
- * Enable the PHY and wait until completion
- * This includes BaseBand and Synthesizer
- * activation.
- */
- ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
-
- /*
- * On 5211+ read activation -> rx delay
- * and use it.
- *
- * TODO: Half/quarter rate support
- */
- if (ah->ah_version != AR5K_AR5210) {
- u32 delay;
- delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
- AR5K_PHY_RX_DELAY_M;
- delay = (channel->hw_value & CHANNEL_CCK) ?
- ((delay << 2) / 22) : (delay / 10);
-
- udelay(100 + (2 * delay));
- } else {
- mdelay(1);
}
/*
- * Perform ADC test to see if baseband is ready
- * Set TX hold and check ADC test register
- */
- phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
- ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
- for (i = 0; i <= 20; i++) {
- if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
- break;
- udelay(200);
- }
- ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1);
-
- /*
- * Start automatic gain control calibration
- *
- * During AGC calibration RX path is re-routed to
- * a power detector so we don't receive anything.
- *
- * This method is used to calibrate some static offsets
- * used together with on-the fly I/Q calibration (the
- * one performed via ath5k_hw_phy_calibrate), which doesn't
- * interrupt rx path.
- *
- * While rx path is re-routed to the power detector we also
- * start a noise floor calibration to measure the
- * card's noise floor (the noise we measure when we are not
- * transmitting or receiving anything).
- *
- * If we are in a noisy environment, AGC calibration may time
- * out and/or noise floor calibration might timeout.
- */
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
-
- /* At the same time start I/Q calibration for QAM constellation
- * -no need for CCK- */
- ah->ah_calibration = false;
- if (!(mode == AR5K_MODE_11B)) {
- ah->ah_calibration = true;
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
- AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_RUN);
- }
-
- /* Wait for gain calibration to finish (we check for I/Q calibration
- * during ath5k_phy_calibrate) */
- if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL, 0, false)) {
- ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
- channel->center_freq);
- }
-
- /* Restore antenna mode */
- ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
-
- /* Restore slot time and ACK timeouts */
- if (ah->ah_coverage_class > 0)
- ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class);
-
- /*
* Configure QCUs/DCUs
*/
+ ret = ath5k_hw_init_queues(ah);
+ if (ret)
+ return ret;
- /* TODO: HW Compression support for data queues */
- /* TODO: Burst prefetch for data queues */
-
- /*
- * Reset queues and start beacon timers at the end of the reset routine
- * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping
- * Note: If we want we can assign multiple qcus on one dcu.
- */
- for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
- ret = ath5k_hw_reset_tx_queue(ah, i);
- if (ret) {
- ATH5K_ERR(ah->ah_sc,
- "failed to reset TX queue #%d\n", i);
- return ret;
- }
- }
-
-
- /*
- * Configure DMA/Interrupts
- */
/*
- * Set Rx/Tx DMA Configuration
- *
- * Set standard DMA size (128). Note that
- * a DMA size of 512 causes rx overruns and tx errors
- * on pci-e cards (tested on 5424 but since rx overruns
- * also occur on 5416/5418 with madwifi we set 128
- * for all PCI-E cards to be safe).
- *
- * XXX: need to check 5210 for this
- * TODO: Check out tx triger level, it's always 64 on dumps but I
- * guess we can tweak it and see how it goes ;-)
+ * Initialize DMA/Interrupts
*/
- if (ah->ah_version != AR5K_AR5210) {
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
- AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
- }
+ ath5k_hw_dma_init(ah);
- /* Pre-enable interrupts on 5211/5212*/
- if (ah->ah_version != AR5K_AR5210)
- ath5k_hw_set_imr(ah, ah->ah_imr);
/* Enable 32KHz clock function for AR5212+ chips
* Set clocks to 32KHz operation and use an
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h
index 3ac4cff4239d..16b67e84906d 100644
--- a/drivers/net/wireless/ath/ath5k/rfbuffer.h
+++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h
@@ -51,7 +51,7 @@
struct ath5k_ini_rfbuffer {
u8 rfb_bank; /* RF Bank number */
u16 rfb_ctrl_register; /* RF Buffer control register */
- u32 rfb_mode_data[5]; /* RF Buffer data for each mode */
+ u32 rfb_mode_data[3]; /* RF Buffer data for each mode */
};
/*
@@ -79,8 +79,10 @@ struct ath5k_rf_reg {
* life easier by using an index for each register
* instead of a full rfb_field */
enum ath5k_rf_regs_idx {
+ /* BANK 2 */
+ AR5K_RF_TURBO = 0,
/* BANK 6 */
- AR5K_RF_OB_2GHZ = 0,
+ AR5K_RF_OB_2GHZ,
AR5K_RF_OB_5GHZ,
AR5K_RF_DB_2GHZ,
AR5K_RF_DB_5GHZ,
@@ -134,6 +136,9 @@ enum ath5k_rf_regs_idx {
* RF5111 (Sombrero) *
\*******************/
+/* BANK 2 len pos col */
+#define AR5K_RF5111_RF_TURBO { 1, 3, 0 }
+
/* BANK 6 len pos col */
#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 }
#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 }
@@ -158,6 +163,7 @@ enum ath5k_rf_regs_idx {
#define AR5K_RF5111_MAX_TIME { 2, 49, 0 }
static const struct ath5k_rf_reg rf_regs_5111[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF5111_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ},
{6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ},
@@ -177,97 +183,52 @@ static const struct ath5k_rf_reg rf_regs_5111[] = {
/* Default mode specific settings */
static const struct ath5k_ini_rfbuffer rfb_5111[] = {
- { 0, 0x989c,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 0, 0x989c,
- { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
- { 0, 0x989c,
- { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
- { 0, 0x98d4,
- { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
- { 1, 0x98d4,
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d4,
- { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
- { 3, 0x98d8,
- { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
- { 6, 0x989c,
- { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
- { 6, 0x989c,
- { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
- { 6, 0x989c,
- { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
- { 6, 0x989c,
- { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
- { 6, 0x989c,
- { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
- { 6, 0x98d4,
- { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
- { 7, 0x989c,
- { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
- { 7, 0x989c,
- { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
- { 7, 0x989c,
- { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
- { 7, 0x989c,
- { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
- { 7, 0x989c,
- { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
- { 7, 0x989c,
- { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
- { 7, 0x989c,
- { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c, { 0x00000000, 0x000000c0, 0x00000080 } },
+ { 0, 0x989c, { 0x000400f9, 0x000400ff, 0x000400fd } },
+ { 0, 0x98d4, { 0x00000000, 0x00000004, 0x00000004 } },
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d4, { 0x00000010, 0x00000010, 0x00000010 } },
+ { 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x0a000000, 0x00000000 } },
+ { 6, 0x989c, { 0x003800c0, 0x023800c0, 0x003800c0 } },
+ { 6, 0x989c, { 0x00020006, 0x00000006, 0x00020006 } },
+ { 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089 } },
+ { 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0 } },
+ { 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007 } },
+ { 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a } },
+ { 7, 0x989c, { 0x00000040, 0x00000040, 0x00000040 } },
+ { 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010 } },
+ { 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008 } },
+ { 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f } },
+ { 7, 0x989c, { 0x000000f1, 0x00000061, 0x000000f1 } },
+ { 7, 0x989c, { 0x0000904f, 0x0000904c, 0x0000904f } },
+ { 7, 0x989c, { 0x0000125a, 0x0000129a, 0x0000125a } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000f, 0x0000000e } },
};
@@ -276,6 +237,9 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {
* RF5112/RF2112 (Derby) *
\***********************/
+/* BANK 2 (Common) len pos col */
+#define AR5K_RF5112X_RF_TURBO { 1, 1, 2 }
+
/* BANK 7 (Common) len pos col */
#define AR5K_RF5112X_GAIN_I { 6, 14, 0 }
#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 }
@@ -307,6 +271,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {
#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 }
static const struct ath5k_rf_reg rf_regs_5112[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ},
{6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ},
@@ -335,115 +300,61 @@ static const struct ath5k_rf_reg rf_regs_5112[] = {
/* Default mode specific settings */
static const struct ath5k_ini_rfbuffer rfb_5112[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
- { 3, 0x98dc,
- { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
- { 6, 0x989c,
- { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
- { 6, 0x989c,
- { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
- { 6, 0x989c,
- { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
- { 6, 0x989c,
- { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
- { 6, 0x989c,
- { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
- { 6, 0x989c,
- { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
- { 6, 0x989c,
- { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
- { 6, 0x989c,
- { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
- { 6, 0x989c,
- { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
- { 6, 0x989c,
- { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
- { 6, 0x989c,
- { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
- { 6, 0x989c,
- { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
- { 6, 0x989c,
- { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
- { 6, 0x989c,
- { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
- { 6, 0x989c,
- { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
- { 6, 0x989c,
- { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
- { 6, 0x989c,
- { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
- { 6, 0x989c,
- { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
- { 6, 0x989c,
- { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
- { 6, 0x989c,
- { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
- { 6, 0x989c,
- { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
- { 6, 0x989c,
- { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
- { 6, 0x989c,
- { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
- { 6, 0x989c,
- { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
- { 6, 0x989c,
- { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
- { 6, 0x989c,
- { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
- { 6, 0x989c,
- { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
- { 6, 0x989c,
- { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
- { 6, 0x989c,
- { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
- { 6, 0x98d0,
- { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
- { 7, 0x989c,
- { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
- { 7, 0x989c,
- { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
- { 7, 0x989c,
- { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
- { 7, 0x989c,
- { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
- { 7, 0x989c,
- { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
- { 7, 0x989c,
- { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
- { 7, 0x989c,
- { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
- { 7, 0x989c,
- { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
- { 7, 0x989c,
- { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
- { 7, 0x989c,
- { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
- { 7, 0x989c,
- { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
- { 7, 0x989c,
- { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
- { 7, 0x98c4,
- { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } },
+ { 3, 0x98dc, { 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+ { 6, 0x989c, { 0x00a00000, 0x00a00000, 0x00a00000 } },
+ { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00660000, 0x00660000, 0x00660000 } },
+ { 6, 0x989c, { 0x00db0000, 0x00db0000, 0x00db0000 } },
+ { 6, 0x989c, { 0x00f10000, 0x00f10000, 0x00f10000 } },
+ { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x008b0000, 0x008b0000, 0x008b0000 } },
+ { 6, 0x989c, { 0x00600000, 0x00600000, 0x00600000 } },
+ { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c, { 0x00640000, 0x00640000, 0x00640000 } },
+ { 6, 0x989c, { 0x00200000, 0x00200000, 0x00200000 } },
+ { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c, { 0x00250000, 0x00250000, 0x00250000 } },
+ { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c, { 0x00510000, 0x00510000, 0x00510000 } },
+ { 6, 0x989c, { 0x1c040000, 0x1c040000, 0x1c040000 } },
+ { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c, { 0x00a10000, 0x00a10000, 0x00a10000 } },
+ { 6, 0x989c, { 0x00400000, 0x00400000, 0x00400000 } },
+ { 6, 0x989c, { 0x03090000, 0x03090000, 0x03090000 } },
+ { 6, 0x989c, { 0x06000000, 0x06000000, 0x06000000 } },
+ { 6, 0x989c, { 0x000000b0, 0x000000a8, 0x000000a8 } },
+ { 6, 0x989c, { 0x0000002e, 0x0000002e, 0x0000002e } },
+ { 6, 0x989c, { 0x006c4a41, 0x006c4af1, 0x006c4a61 } },
+ { 6, 0x989c, { 0x0050892a, 0x0050892b, 0x0050892b } },
+ { 6, 0x989c, { 0x00842400, 0x00842400, 0x00842400 } },
+ { 6, 0x989c, { 0x00c69200, 0x00c69200, 0x00c69200 } },
+ { 6, 0x98d0, { 0x0002000c, 0x0002000c, 0x0002000c } },
+ { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c, { 0x0000000a, 0x00000012, 0x00000012 } },
+ { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c, { 0x000000c1, 0x000000c1, 0x000000c1 } },
+ { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c, { 0x00000022, 0x00000022, 0x00000022 } },
+ { 7, 0x989c, { 0x00000092, 0x00000092, 0x00000092 } },
+ { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } },
};
/* RFX112A (Derby 2) */
@@ -477,6 +388,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112[] = {
#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 }
static const struct ath5k_rf_reg rf_regs_5112a[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ},
{6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ},
@@ -515,119 +427,63 @@ static const struct ath5k_rf_reg rf_regs_5112a[] = {
/* Default mode specific settings */
static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
- { 6, 0x989c,
- { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
- { 6, 0x989c,
- { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
- { 6, 0x989c,
- { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
- { 6, 0x989c,
- { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
- { 6, 0x989c,
- { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
- { 6, 0x989c,
- { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
- { 6, 0x989c,
- { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } },
- { 6, 0x989c,
- { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
- { 6, 0x989c,
- { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
- { 6, 0x989c,
- { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } },
- { 6, 0x989c,
- { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
- { 6, 0x989c,
- { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
- { 6, 0x989c,
- { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
- { 6, 0x989c,
- { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
- { 6, 0x989c,
- { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
- { 6, 0x989c,
- { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
- { 6, 0x989c,
- { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
- { 6, 0x989c,
- { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
- { 6, 0x989c,
- { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
- { 6, 0x989c,
- { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
- { 6, 0x989c,
- { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
- { 6, 0x989c,
- { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } },
- { 6, 0x989c,
- { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } },
- { 6, 0x989c,
- { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
- { 6, 0x989c,
- { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
- { 6, 0x989c,
- { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
- { 6, 0x989c,
- { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
- { 6, 0x989c,
- { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
- { 6, 0x98d8,
- { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
- { 7, 0x989c,
- { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
- { 7, 0x989c,
- { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
- { 7, 0x989c,
- { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
- { 7, 0x989c,
- { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
- { 7, 0x989c,
- { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
- { 7, 0x989c,
- { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
- { 7, 0x989c,
- { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
- { 7, 0x989c,
- { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
- { 7, 0x989c,
- { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
- { 7, 0x989c,
- { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
- { 7, 0x989c,
- { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
- { 7, 0x989c,
- { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
- { 7, 0x98c4,
- { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000 } },
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000 } },
+ { 6, 0x989c, { 0x00600000, 0x006e0000, 0x006e0000 } },
+ { 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000 } },
+ { 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000 } },
+ { 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000 } },
+ { 6, 0x989c, { 0x004c0000, 0x004c0000, 0x004c0000 } },
+ { 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000 } },
+ { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000 } },
+ { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000 } },
+ { 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000 } },
+ { 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000 } },
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000 } },
+ { 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000 } },
+ { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000 } },
+ { 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000 } },
+ { 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080 } },
+ { 6, 0x989c, { 0x00270019, 0x00270019, 0x00270019 } },
+ { 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2 } },
+ { 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084 } },
+ { 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4 } },
+ { 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220 } },
+ { 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800 } },
+ { 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230 } },
+ { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9 } },
+ { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2 } },
+ { 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052 } },
+ { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } },
};
@@ -636,11 +492,15 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = {
* RF2413 (Griffin) *
\******************/
+/* BANK 2 len pos col */
+#define AR5K_RF2413_RF_TURBO { 1, 1, 2 }
+
/* BANK 6 len pos col */
#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 }
#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 }
static const struct ath5k_rf_reg rf_regs_2413[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF2413_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ},
};
@@ -649,73 +509,40 @@ static const struct ath5k_rf_reg rf_regs_2413[] = {
* XXX: a/aTurbo ???
*/
static const struct ath5k_ini_rfbuffer rfb_2413[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } },
- { 6, 0x989c,
- { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } },
- { 6, 0x989c,
- { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } },
- { 6, 0x989c,
- { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } },
- { 6, 0x989c,
- { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } },
- { 6, 0x989c,
- { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } },
- { 6, 0x989c,
- { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
- { 6, 0x989c,
- { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } },
- { 6, 0x989c,
- { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } },
- { 6, 0x989c,
- { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } },
- { 6, 0x989c,
- { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } },
- { 6, 0x989c,
- { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } },
- { 6, 0x989c,
- { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } },
- { 6, 0x98d8,
- { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0xf0000000, 0xf0000000, 0xf0000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x03000000, 0x03000000, 0x03000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x40400000, 0x40400000, 0x40400000 } },
+ { 6, 0x989c, { 0x65050000, 0x65050000, 0x65050000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00420000, 0x00420000, 0x00420000 } },
+ { 6, 0x989c, { 0x00b50000, 0x00b50000, 0x00b50000 } },
+ { 6, 0x989c, { 0x00030000, 0x00030000, 0x00030000 } },
+ { 6, 0x989c, { 0x00f70000, 0x00f70000, 0x00f70000 } },
+ { 6, 0x989c, { 0x009d0000, 0x009d0000, 0x009d0000 } },
+ { 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000 } },
+ { 6, 0x989c, { 0x04220000, 0x04220000, 0x04220000 } },
+ { 6, 0x989c, { 0x00230018, 0x00230018, 0x00230018 } },
+ { 6, 0x989c, { 0x00280000, 0x00280060, 0x00280060 } },
+ { 6, 0x989c, { 0x005000c0, 0x005000c3, 0x005000c3 } },
+ { 6, 0x989c, { 0x0004007f, 0x0004007f, 0x0004007f } },
+ { 6, 0x989c, { 0x00000458, 0x00000458, 0x00000458 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x0000c000, 0x0000c000, 0x0000c000 } },
+ { 6, 0x98d8, { 0x00400230, 0x00400230, 0x00400230 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
@@ -724,88 +551,57 @@ static const struct ath5k_ini_rfbuffer rfb_2413[] = {
* RF2315/RF2316 (Cobra SoC) *
\***************************/
+/* BANK 2 len pos col */
+#define AR5K_RF2316_RF_TURBO { 1, 1, 2 }
+
/* BANK 6 len pos col */
#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 }
#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 }
static const struct ath5k_rf_reg rf_regs_2316[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF2316_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ},
};
/* Default mode specific settings */
static const struct ath5k_ini_rfbuffer rfb_2316[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } },
- { 6, 0x989c,
- { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
- { 6, 0x989c,
- { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } },
- { 6, 0x989c,
- { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } },
- { 6, 0x989c,
- { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } },
- { 6, 0x989c,
- { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } },
- { 6, 0x989c,
- { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
- { 6, 0x989c,
- { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
- { 6, 0x989c,
- { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } },
- { 6, 0x989c,
- { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } },
- { 6, 0x989c,
- { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } },
- { 6, 0x989c,
- { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } },
- { 6, 0x989c,
- { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } },
- { 6, 0x989c,
- { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } },
- { 6, 0x989c,
- { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
- { 6, 0x989c,
- { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
- { 6, 0x989c,
- { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } },
- { 6, 0x989c,
- { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } },
- { 6, 0x98c0,
- { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0xc0000000, 0xc0000000, 0xc0000000 } },
+ { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c, { 0x02000000, 0x02000000, 0x02000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0xf8000000, 0xf8000000, 0xf8000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x95150000, 0x95150000, 0x95150000 } },
+ { 6, 0x989c, { 0xc1000000, 0xc1000000, 0xc1000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00080000, 0x00080000, 0x00080000 } },
+ { 6, 0x989c, { 0x00d50000, 0x00d50000, 0x00d50000 } },
+ { 6, 0x989c, { 0x000e0000, 0x000e0000, 0x000e0000 } },
+ { 6, 0x989c, { 0x00dc0000, 0x00dc0000, 0x00dc0000 } },
+ { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c, { 0x008a0000, 0x008a0000, 0x008a0000 } },
+ { 6, 0x989c, { 0x10880000, 0x10880000, 0x10880000 } },
+ { 6, 0x989c, { 0x008c0060, 0x008c0060, 0x008c0060 } },
+ { 6, 0x989c, { 0x00a00000, 0x00a00080, 0x00a00080 } },
+ { 6, 0x989c, { 0x00400000, 0x0040000d, 0x0040000d } },
+ { 6, 0x989c, { 0x00110400, 0x00110400, 0x00110400 } },
+ { 6, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } },
+ { 6, 0x989c, { 0x00000001, 0x00000001, 0x00000001 } },
+ { 6, 0x989c, { 0x00000b00, 0x00000b00, 0x00000b00 } },
+ { 6, 0x989c, { 0x00000be8, 0x00000be8, 0x00000be8 } },
+ { 6, 0x98c0, { 0x00010000, 0x00010000, 0x00010000 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
@@ -835,93 +631,50 @@ static const struct ath5k_rf_reg rf_regs_5413[] = {
/* Default mode specific settings */
static const struct ath5k_ini_rfbuffer rfb_5413[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
- { 3, 0x98dc,
- { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
- { 6, 0x989c,
- { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
- { 6, 0x989c,
- { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
- { 6, 0x989c,
- { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
- { 6, 0x989c,
- { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
- { 6, 0x989c,
- { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
- { 6, 0x989c,
- { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
- { 6, 0x989c,
- { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
- { 6, 0x989c,
- { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
- { 6, 0x989c,
- { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
- { 6, 0x989c,
- { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
- { 6, 0x989c,
- { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
- { 6, 0x989c,
- { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
- { 6, 0x989c,
- { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
- { 6, 0x989c,
- { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
- { 6, 0x989c,
- { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
- { 6, 0x989c,
- { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
- { 6, 0x989c,
- { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
- { 6, 0x989c,
- { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
- { 6, 0x989c,
- { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
- { 6, 0x989c,
- { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } },
- { 6, 0x989c,
- { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
- { 6, 0x989c,
- { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } },
- { 6, 0x98c8,
- { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x00000008, 0x00000008, 0x00000008 } },
+ { 3, 0x98dc, { 0x00a000c0, 0x00e000c0, 0x00e000c0 } },
+ { 6, 0x989c, { 0x33000000, 0x33000000, 0x33000000 } },
+ { 6, 0x989c, { 0x01000000, 0x01000000, 0x01000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x1f000000, 0x1f000000, 0x1f000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00b80000, 0x00b80000, 0x00b80000 } },
+ { 6, 0x989c, { 0x00b70000, 0x00b70000, 0x00b70000 } },
+ { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c, { 0x00c00000, 0x00c00000, 0x00c00000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c, { 0x00d70000, 0x00d70000, 0x00d70000 } },
+ { 6, 0x989c, { 0x00610000, 0x00610000, 0x00610000 } },
+ { 6, 0x989c, { 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+ { 6, 0x989c, { 0x00de0000, 0x00de0000, 0x00de0000 } },
+ { 6, 0x989c, { 0x007f0000, 0x007f0000, 0x007f0000 } },
+ { 6, 0x989c, { 0x043d0000, 0x043d0000, 0x043d0000 } },
+ { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c, { 0x00440000, 0x00440000, 0x00440000 } },
+ { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c, { 0x00100080, 0x00100080, 0x00100080 } },
+ { 6, 0x989c, { 0x0005c034, 0x0005c034, 0x0005c034 } },
+ { 6, 0x989c, { 0x003100f0, 0x003100f0, 0x003100f0 } },
+ { 6, 0x989c, { 0x000c011f, 0x000c011f, 0x000c011f } },
+ { 6, 0x989c, { 0x00510040, 0x00510040, 0x00510040 } },
+ { 6, 0x989c, { 0x005000da, 0x005000da, 0x005000da } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00004044, 0x00004044, 0x00004044 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x000060c0, 0x000060c0, 0x000060c0 } },
+ { 6, 0x989c, { 0x00002c00, 0x00003600, 0x00003600 } },
+ { 6, 0x98c8, { 0x00000403, 0x00040403, 0x00040403 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
@@ -931,92 +684,59 @@ static const struct ath5k_ini_rfbuffer rfb_5413[] = {
* AR2317 (Spider SoC) *
\***************************/
+/* BANK 2 len pos col */
+#define AR5K_RF2425_RF_TURBO { 1, 1, 2 }
+
/* BANK 6 len pos col */
#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 }
#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 }
static const struct ath5k_rf_reg rf_regs_2425[] = {
+ {2, AR5K_RF_TURBO, AR5K_RF2425_RF_TURBO},
{6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ},
{6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ},
};
/* Default mode specific settings
- * XXX: a/aTurbo ?
*/
static const struct ath5k_ini_rfbuffer rfb_2425[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
- { 6, 0x989c,
- { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
- { 6, 0x989c,
- { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
- { 6, 0x989c,
- { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
- { 6, 0x989c,
- { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
- { 6, 0x989c,
- { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
- { 6, 0x989c,
- { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
- { 6, 0x989c,
- { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
- { 6, 0x989c,
- { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
- { 6, 0x989c,
- { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
- { 6, 0x989c,
- { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
- { 6, 0x989c,
- { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
- { 6, 0x98c4,
- { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+ { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
/*
@@ -1024,158 +744,85 @@ static const struct ath5k_ini_rfbuffer rfb_2425[] = {
* bank modification and get rid of this
*/
static const struct ath5k_ini_rfbuffer rfb_2317[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
- { 6, 0x989c,
- { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
- { 6, 0x989c,
- { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
- { 6, 0x989c,
- { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
- { 6, 0x989c,
- { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } },
- { 6, 0x989c,
- { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } },
- { 6, 0x989c,
- { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
- { 6, 0x989c,
- { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } },
- { 6, 0x989c,
- { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
- { 6, 0x989c,
- { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
- { 6, 0x989c,
- { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
- { 6, 0x989c,
- { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } },
- { 6, 0x98c4,
- { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } },
+ { 6, 0x989c, { 0x00140100, 0x00140100, 0x00140100 } },
+ { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } },
+ { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+ { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c, { 0x00009688, 0x00009688, 0x00009688 } },
+ { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
/*
* TODO: Handle the few differences with swan during
* bank modification and get rid of this
- * XXX: a/aTurbo ?
*/
static const struct ath5k_ini_rfbuffer rfb_2417[] = {
- { 1, 0x98d4,
- /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
- { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
- { 2, 0x98d0,
- { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } },
- { 3, 0x98dc,
- { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
- { 6, 0x989c,
- { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } },
- { 6, 0x989c,
- { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } },
- { 6, 0x989c,
- { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
- { 6, 0x989c,
- { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } },
- { 6, 0x989c,
- { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } },
- { 6, 0x989c,
- { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } },
- { 6, 0x989c,
- { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } },
- { 6, 0x989c,
- { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } },
- { 6, 0x989c,
- { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } },
- { 6, 0x989c,
- { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } },
- { 6, 0x989c,
- { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
- { 6, 0x989c,
- { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } },
- { 6, 0x989c,
- { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } },
- { 6, 0x98c4,
- { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
- { 7, 0x989c,
- { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
- { 7, 0x989c,
- { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
- { 7, 0x98cc,
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ /* BANK / C.R. A/XR B G */
+ { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } },
+ { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } },
+ { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } },
+ { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } },
+ { 6, 0x989c, { 0x00e70000, 0x80e70000, 0x80e70000 } },
+ { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } },
+ { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } },
+ { 6, 0x989c, { 0x0007001a, 0x0207001a, 0x0207001a } },
+ { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } },
+ { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } },
+ { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } },
+ { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } },
+ { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } },
+ { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } },
};
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index 90757de7bf59..929c68cdf8ab 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -95,7 +95,7 @@ static struct attribute_group ath5k_attribute_group_ani = {
int
ath5k_sysfs_register(struct ath5k_softc *sc)
{
- struct device *dev = &sc->pdev->dev;
+ struct device *dev = sc->dev;
int err;
err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani);
@@ -110,7 +110,7 @@ ath5k_sysfs_register(struct ath5k_softc *sc)
void
ath5k_sysfs_unregister(struct ath5k_softc *sc)
{
- struct device *dev = &sc->pdev->dev;
+ struct device *dev = sc->dev;
sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani);
}
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 63ccb39cdcd4..29a045da184b 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -834,10 +834,10 @@ void ath9k_hw_ani_setup(struct ath_hw *ah)
{
int i;
- const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
- const int coarseHigh[] = { -14, -14, -14, -14, -12 };
- const int coarseLow[] = { -64, -64, -64, -64, -70 };
- const int firpwr[] = { -78, -78, -78, -78, -80 };
+ static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+ static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+ static const int coarseLow[] = { -64, -64, -64, -64, -70 };
+ static const int firpwr[] = { -78, -78, -78, -78, -80 };
for (i = 0; i < 5; i++) {
ah->totalSizeDesired[i] = totalSizeDesired[i];
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index ea9f4497f58c..06e34d293dc8 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -244,13 +244,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
int upper, lower, cur_vit_mask;
int tmp, new;
int i;
- int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
- AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ static int pilot_mask_reg[4] = {
+ AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
- int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
- AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ static int chan_mask_reg[4] = {
+ AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
- int inc[4] = { 0, 100, 0, 0 };
+ static int inc[4] = { 0, 100, 0, 0 };
int8_t mask_m[123];
int8_t mask_p[123];
@@ -873,7 +875,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), false);
/* Write analog registers */
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
@@ -1084,12 +1086,12 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
break;
}
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
- const int m1ThreshLow[] = { 127, 50 };
- const int m2ThreshLow[] = { 127, 40 };
- const int m1Thresh[] = { 127, 0x4d };
- const int m2Thresh[] = { 127, 0x40 };
- const int m2CountThr[] = { 31, 16 };
- const int m2CountThrLow[] = { 63, 48 };
+ static const int m1ThreshLow[] = { 127, 50 };
+ static const int m2ThreshLow[] = { 127, 40 };
+ static const int m1Thresh[] = { 127, 0x4d };
+ static const int m2Thresh[] = { 127, 0x40 };
+ static const int m2CountThr[] = { 31, 16 };
+ static const int m2CountThrLow[] = { 63, 48 };
u32 on = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
@@ -1141,7 +1143,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
break;
}
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
- const int weakSigThrCck[] = { 8, 6 };
+ static const int weakSigThrCck[] = { 8, 6 };
u32 high = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
@@ -1157,7 +1159,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
break;
}
case ATH9K_ANI_FIRSTEP_LEVEL:{
- const int firstep[] = { 0, 4, 8 };
+ static const int firstep[] = { 0, 4, 8 };
u32 level = param;
if (level >= ARRAY_SIZE(firstep)) {
@@ -1178,7 +1180,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah,
break;
}
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
- const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
+ static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 };
u32 level = param;
if (level >= ARRAY_SIZE(cycpwrThr1)) {
@@ -1490,25 +1492,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
int16_t nf;
nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
- nfarray[0] = sign_extend(nf, 9);
+ nfarray[0] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
- nfarray[1] = sign_extend(nf, 9);
+ nfarray[1] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
- nfarray[2] = sign_extend(nf, 9);
+ nfarray[2] = sign_extend32(nf, 8);
if (!IS_CHAN_HT40(ah->curchan))
return;
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
- nfarray[3] = sign_extend(nf, 9);
+ nfarray[3] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
- nfarray[4] = sign_extend(nf, 9);
+ nfarray[4] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
- nfarray[5] = sign_extend(nf, 9);
+ nfarray[5] = sign_extend32(nf, 8);
}
/*
@@ -1579,10 +1581,55 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
}
+static void ar5008_hw_set_radar_params(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf)
+{
+ u32 radar_0 = 0, radar_1 = 0;
+
+ if (!conf) {
+ REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+ return;
+ }
+
+ radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+ radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+ radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+ radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+ radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+ radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+ radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+ radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+ radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+ REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+ REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+ if (conf->ext_channel)
+ REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+ else
+ REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
+{
+ struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+ conf->fir_power = -33;
+ conf->radar_rssi = 20;
+ conf->pulse_height = 10;
+ conf->pulse_rssi = 24;
+ conf->pulse_inband = 15;
+ conf->pulse_maxlen = 255;
+ conf->pulse_inband_step = 12;
+ conf->radar_inband = 8;
+}
+
void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- const u32 ar5416_cca_regs[6] = {
+ static const u32 ar5416_cca_regs[6] = {
AR_PHY_CCA,
AR_PHY_CH1_CCA,
AR_PHY_CH2_CCA,
@@ -1609,6 +1656,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->restore_chainmask = ar5008_restore_chainmask;
priv_ops->set_diversity = ar5008_set_diversity;
priv_ops->do_getnf = ar5008_hw_do_getnf;
+ priv_ops->set_radar_params = ar5008_hw_set_radar_params;
if (modparam_force_new_ani) {
priv_ops->ani_control = ar5008_hw_ani_control_new;
@@ -1624,5 +1672,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
ar5008_hw_set_nf_limits(ah);
+ ar5008_hw_set_radar_conf(ah);
memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 50dda394f8be..f0268e5eab34 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
*masked = isr & ATH9K_INT_COMMON;
- if (ah->config.rx_intr_mitigation) {
- if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
- *masked |= ATH9K_INT_RX;
- }
-
- if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+ if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
+ AR_ISR_RXOK | AR_ISR_RXERR))
*masked |= ATH9K_INT_RX;
+
if (isr &
(AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
AR_ISR_TXEOL)) {
@@ -118,14 +115,6 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
"receive FIFO overrun interrupt\n");
}
- if (!AR_SREV_9100(ah)) {
- if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
- u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
- if (isr5 & AR_ISR_S5_TIM_TIMER)
- *masked |= ATH9K_INT_TIM_TIMER;
- }
- }
-
*masked |= mask2;
}
@@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
u32 s5_s;
s5_s = REG_READ(ah, AR_ISR_S5_S);
- if (isr & AR_ISR_GENTMR) {
- ah->intr_gen_timer_trigger =
+ ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
- ah->intr_gen_timer_thresh =
- MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+ ah->intr_gen_timer_thresh =
+ MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
- if (ah->intr_gen_timer_trigger)
- *masked |= ATH9K_INT_GENTIMER;
+ if (ah->intr_gen_timer_trigger)
+ *masked |= ATH9K_INT_GENTIMER;
- }
+ if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
+ !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ *masked |= ATH9K_INT_TIM_TIMER;
}
if (sync_cause) {
@@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar5416_desc *ads = AR5416DESC(ds);
+ u32 status;
- if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+ status = ACCESS_ONCE(ads->ds_txstatus9);
+ if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
- ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
ts->ts_tstamp = ads->AR_SendTimestamp;
ts->ts_status = 0;
ts->ts_flags = 0;
- if (ads->ds_txstatus1 & AR_FrmXmitOK)
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
+ ts->tid = MS(status, AR_TxTid);
+ ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+ ts->ts_seqnum = MS(status, AR_SeqNum);
+
+ status = ACCESS_ONCE(ads->ds_txstatus0);
+ ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+ ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+ ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+ if (status & AR_TxBaStatus) {
+ ts->ts_flags |= ATH9K_TX_BA;
+ ts->ba_low = ads->AR_BaBitmapLow;
+ ts->ba_high = ads->AR_BaBitmapHigh;
+ }
+
+ status = ACCESS_ONCE(ads->ds_txstatus1);
+ if (status & AR_FrmXmitOK)
ts->ts_status |= ATH9K_TX_ACKED;
- if (ads->ds_txstatus1 & AR_ExcessiveRetries)
- ts->ts_status |= ATH9K_TXERR_XRETRY;
- if (ads->ds_txstatus1 & AR_Filtered)
- ts->ts_status |= ATH9K_TXERR_FILT;
- if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
- ts->ts_status |= ATH9K_TXERR_FIFO;
- ath9k_hw_updatetxtriglevel(ah, true);
+ else {
+ if (status & AR_ExcessiveRetries)
+ ts->ts_status |= ATH9K_TXERR_XRETRY;
+ if (status & AR_Filtered)
+ ts->ts_status |= ATH9K_TXERR_FILT;
+ if (status & AR_FIFOUnderrun) {
+ ts->ts_status |= ATH9K_TXERR_FIFO;
+ ath9k_hw_updatetxtriglevel(ah, true);
+ }
}
- if (ads->ds_txstatus9 & AR_TxOpExceeded)
- ts->ts_status |= ATH9K_TXERR_XTXOP;
- if (ads->ds_txstatus1 & AR_TxTimerExpired)
+ if (status & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
- if (ads->ds_txstatus1 & AR_DescCfgErr)
+ if (status & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
- if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+ if (status & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
- if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+ if (status & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
- if (ads->ds_txstatus0 & AR_TxBaStatus) {
- ts->ts_flags |= ATH9K_TX_BA;
- ts->ba_low = ads->AR_BaBitmapLow;
- ts->ba_high = ads->AR_BaBitmapHigh;
- }
+ ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+ ts->ts_longretry = MS(status, AR_DataFailCnt);
+ ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
- ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
- switch (ts->ts_rateindex) {
- case 0:
- ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
- break;
- case 1:
- ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
- break;
- case 2:
- ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
- break;
- case 3:
- ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
- break;
- }
+ status = ACCESS_ONCE(ads->ds_txstatus5);
+ ts->ts_rssi = MS(status, AR_TxRSSICombined);
+ ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+ ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+ ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
- ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
- ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
- ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
- ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
- ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
- ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
- ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
ts->evm0 = ads->AR_TxEVM0;
ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2;
- ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
- ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
- ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
- ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
- ts->ts_antenna = 0;
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index c00cdc67b55b..7ae66a889f5a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -175,13 +175,15 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
int upper, lower, cur_vit_mask;
int tmp, newVal;
int i;
- int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
- AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
+ static const int pilot_mask_reg[4] = {
+ AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
- int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
- AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
+ static const int chan_mask_reg[4] = {
+ AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
- int inc[4] = { 0, 100, 0, 0 };
+ static const int inc[4] = { 0, 100, 0, 0 };
struct chan_centers centers;
int8_t mask_m[123];
@@ -473,21 +475,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
int16_t nf;
nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
- nfarray[0] = sign_extend(nf, 9);
+ nfarray[0] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
if (IS_CHAN_HT40(ah->curchan))
- nfarray[3] = sign_extend(nf, 9);
+ nfarray[3] = sign_extend32(nf, 8);
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
return;
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
- nfarray[1] = sign_extend(nf, 9);
+ nfarray[1] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
if (IS_CHAN_HT40(ah->curchan))
- nfarray[4] = sign_extend(nf, 9);
+ nfarray[4] = sign_extend32(nf, 8);
}
static void ar9002_hw_set_nf_limits(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 9e6edffe0bd1..4c94c9ed5f81 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -196,7 +196,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
u32 qCoffDenom, iCoffDenom;
int32_t qCoff, iCoff;
int iqCorrNeg, i;
- const u_int32_t offset_array[3] = {
+ static const u_int32_t offset_array[3] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
@@ -603,22 +603,22 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
- const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+ static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_STATUS_B0,
AR_PHY_TX_IQCAL_STATUS_B1,
AR_PHY_TX_IQCAL_STATUS_B2,
};
- const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
+ static const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
AR_PHY_TX_IQCAL_CORR_COEFF_01_B2,
};
- const u32 rx_corr[AR9300_MAX_CHAINS] = {
+ static const u32 rx_corr[AR9300_MAX_CHAINS] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
};
- const u_int32_t chan_info_tab[] = {
+ static const u_int32_t chan_info_tab[] = {
AR_PHY_CHAN_INFO_TAB_0,
AR_PHY_CHAN_INFO_TAB_1,
AR_PHY_CHAN_INFO_TAB_2,
@@ -718,12 +718,19 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
+ int val;
- /*
- * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before
- * running AGC/TxIQ cals
- */
- ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
+ val = REG_READ(ah, AR_ENT_OTP);
+ ath_print(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
+
+ if (val & AR_ENT_OTP_CHAIN2_DISABLE)
+ ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
+ else
+ /*
+ * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
+ * mode before running AGC/TxIQ cals
+ */
+ ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
/* Do Tx IQ Calibration */
ar9003_hw_tx_iq_cal(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index a7b82f0085d2..872b1a3b21c6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -22,12 +22,14 @@
#define COMP_CKSUM_LEN 2
#define AR_CH0_TOP (0x00016288)
-#define AR_CH0_TOP_XPABIASLVL (0x3)
+#define AR_CH0_TOP_XPABIASLVL (0x300)
#define AR_CH0_TOP_XPABIASLVL_S (8)
#define AR_CH0_THERM (0x00016290)
-#define AR_CH0_THERM_SPARE (0x3f)
-#define AR_CH0_THERM_SPARE_S (0)
+#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
+#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
+#define AR_CH0_THERM_XPASHORT2GND 0x4
+#define AR_CH0_THERM_XPASHORT2GND_S 2
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
#define AR_SWITCH_TABLE_COM_ALL_S (0)
@@ -57,6 +59,9 @@
#define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6))
+static int ar9003_hw_power_interpolate(int32_t x,
+ int32_t *px, int32_t *py, u_int16_t np);
+
static const struct ar9300_eeprom ar9300_default = {
.eepromVersion = 2,
.templateVersion = 2,
@@ -146,13 +151,16 @@ static const struct ar9300_eeprom ar9300_default = {
.txEndToRxOn = 0x2,
.txFrameToXpaOn = 0xe,
.thresh62 = 28,
- .papdRateMaskHt20 = LE32(0x80c080),
- .papdRateMaskHt40 = LE32(0x80c080),
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
},
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
.calFreqPier2G = {
FREQ2FBIN(2412, 1),
FREQ2FBIN(2437, 1),
@@ -287,8 +295,7 @@ static const struct ar9300_eeprom ar9300_default = {
/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
- /* Data[11].ctlEdges[3].bChannel */
- FREQ2FBIN(2462, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
}
},
.ctlPowerData_2G = {
@@ -346,13 +353,20 @@ static const struct ar9300_eeprom ar9300_default = {
.txEndToRxOn = 0x2,
.txFrameToXpaOn = 0xe,
.thresh62 = 28,
- .papdRateMaskHt20 = LE32(0xf0e0e0),
- .papdRateMaskHt40 = LE32(0xf0e0e0),
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
.futureModal = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
},
},
+ .base_ext2 = {
+ .tempSlopeLow = 0,
+ .tempSlopeHigh = 0,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
.calFreqPier5G = {
FREQ2FBIN(5180, 0),
FREQ2FBIN(5220, 0),
@@ -626,6 +640,2338 @@ static const struct ar9300_eeprom ar9300_default = {
}
};
+static const struct ar9300_eeprom ar9300_x113 = {
+ .eepromVersion = 2,
+ .templateVersion = 6,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"x113-023-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x21,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x11111),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 68,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 72,
+ .tempSlopeHigh = 105,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5190, 0),
+ FREQ2FBIN(5230, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5410, 0),
+ FREQ2FBIN(5510, 0),
+ FREQ2FBIN(5670, 0),
+ FREQ2FBIN(5755, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ { {42, 40, 40, 34} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} },
+ { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} },
+ { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} },
+ { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} },
+ { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom ar9300_h112 = {
+ .eepromVersion = 2,
+ .templateVersion = 3,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"h112-241-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x10,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x80c080),
+ .papdRateMaskHt40 = LE32(0x80c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2484, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0, 0, 0},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0, 0, 0},
+ .tempSlope = 45,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 40,
+ .tempSlopeHigh = 50,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom ar9300_x112 = {
+ .eepromVersion = 2,
+ .templateVersion = 5,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"x112-041-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastclock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x0,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+
+ /*
+ * antCtrlChain[ar9300_max_chains]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+ /*
+ * xatten1DB[AR9300_max_chains]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0x1b, 0x1b, 0x1b},
+
+ /*
+ * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x15, 0x15, 0x15},
+ .tempSlope = 50,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPrey_eeprom_modal_sPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80c080),
+ .papdRateMaskHt40 = LE32(0x0080c080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11s */
+ { {38, 38, 38, 38} },
+ { {38, 38, 38, 38} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {38, 38, 36, 34} },
+ { {38, 38, 36, 34} },
+ { {38, 38, 34, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+ { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} },
+ { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} },
+ },
+ .calTargetPower2GHT40 = {
+ { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+ { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} },
+ { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x22222),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x0), LE16(0x0), LE16(0x0),
+ },
+ /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0x13, 0x19, 0x17},
+
+ /*
+ * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x19, 0x19, 0x19},
+ .tempSlope = 70,
+ .voltSlope = 15,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshch check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 72,
+ .tempSlopeHigh = 105,
+ .xatten1DBLow = {0x10, 0x14, 0x10},
+ .xatten1MarginLow = {0x19, 0x19 , 0x19},
+ .xatten1DBHigh = {0x1d, 0x20, 0x24},
+ .xatten1MarginHigh = {0x10, 0x10, 0x10}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5725, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {32, 32, 28, 26} },
+ { {32, 32, 28, 26} },
+ { {32, 32, 28, 26} },
+ { {32, 32, 26, 24} },
+ { {32, 32, 26, 24} },
+ { {32, 32, 24, 22} },
+ { {30, 30, 24, 22} },
+ { {30, 30, 24, 22} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} },
+ { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} },
+ { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} },
+ { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} },
+ { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} },
+ { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctledges[6].bchannel */ 0xFF,
+ /* Data[3].ctledges[7].bchannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctledges[4].bchannel */ 0xFF,
+ /* Data[4].ctledges[5].bchannel */ 0xFF,
+ /* Data[4].ctledges[6].bchannel */ 0xFF,
+ /* Data[4].ctledges[7].bchannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctledges[6].bchannel */ 0xFF,
+ /* Data[5].ctledges[7].bchannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+static const struct ar9300_eeprom ar9300_h116 = {
+ .eepromVersion = 2,
+ .templateVersion = 4,
+ .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0},
+ .custData = {"h116-041-f0000"},
+ .baseEepHeader = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+ .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+ .blueToothOptions = 0,
+ .deviceCap = 0,
+ .deviceType = 5, /* takes lower byte in eeprom location */
+ .pwrTableOffset = AR9300_PWR_TABLE_OFFSET,
+ .params_for_tuning_caps = {0, 0},
+ .featureEnable = 0x0d,
+ /*
+ * bit0 - enable tx temp comp - disabled
+ * bit1 - enable tx volt comp - disabled
+ * bit2 - enable fastClock - enabled
+ * bit3 - enable doubling - enabled
+ * bit4 - enable internal regulator - disabled
+ * bit5 - enable pa predistortion - disabled
+ */
+ .miscConfiguration = 0, /* bit0 - turn down drivestrength */
+ .eepromWriteEnableGpio = 6,
+ .wlanDisableGpio = 0,
+ .wlanLedGpio = 8,
+ .rxBandSelectGpio = 0xff,
+ .txrxgain = 0x10,
+ .swreg = 0,
+ },
+ .modalHeader2G = {
+ /* ar9300_modal_eep_header 2g */
+ /* 4 idle,t1,t2,b(4 bits per setting) */
+ .antCtrlCommon = LE32(0x110),
+ /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+
+ /*
+ * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
+ * rx1, rx12, b (2 bits each)
+ */
+ .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) },
+
+ /*
+ * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
+ * for ar9280 (0xa20c/b20c 5:0)
+ */
+ .xatten1DB = {0x1f, 0x1f, 0x1f},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for ar9280 (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x12, 0x12, 0x12},
+ .tempSlope = 25,
+ .voltSlope = 0,
+
+ /*
+ * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur
+ * channels in usual fbin coding format
+ */
+ .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0},
+
+ /*
+ * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check
+ * if the register is per chain
+ */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {1, 1, 1},/* 3 chain */
+ .db_stage2 = {1, 1, 1}, /* 3 chain */
+ .db_stage3 = {0, 0, 0},
+ .db_stage4 = {0, 0, 0},
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2c,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0c80C080),
+ .papdRateMaskHt40 = LE32(0x0080C080),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext1 = {
+ .ant_div_control = 0,
+ .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ },
+ .calFreqPier2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ /* ar9300_cal_data_per_freq_op_loop 2g */
+ .calPierData2G = {
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} },
+ },
+ .calTarget_freqbin_Cck = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2472, 1),
+ },
+ .calTarget_freqbin_2G = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT20 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTarget_freqbin_2GHT40 = {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2437, 1),
+ FREQ2FBIN(2472, 1)
+ },
+ .calTargetPowerCck = {
+ /* 1L-5L,5S,11L,11S */
+ { {34, 34, 34, 34} },
+ { {34, 34, 34, 34} },
+ },
+ .calTargetPower2G = {
+ /* 6-24,36,48,54 */
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ { {34, 34, 32, 32} },
+ },
+ .calTargetPower2GHT20 = {
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} },
+ },
+ .calTargetPower2GHT40 = {
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} },
+ },
+ .ctlIndex_2G = {
+ 0x11, 0x12, 0x15, 0x17, 0x41, 0x42,
+ 0x45, 0x47, 0x31, 0x32, 0x35, 0x37,
+ },
+ .ctl_freqbin_2G = {
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2457, 1),
+ FREQ2FBIN(2462, 1)
+ },
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+
+ {
+ FREQ2FBIN(2412, 1),
+ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2462, 1),
+ 0xFF,
+ },
+ {
+ FREQ2FBIN(2422, 1),
+ FREQ2FBIN(2427, 1),
+ FREQ2FBIN(2447, 1),
+ FREQ2FBIN(2452, 1)
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1),
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ FREQ2FBIN(2472, 1),
+ 0,
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ },
+
+ {
+ /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1),
+ /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1),
+ /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1),
+ 0
+ },
+
+ {
+ /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1),
+ /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1),
+ /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1),
+ /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1),
+ }
+ },
+ .ctlPowerData_2G = {
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
+
+ { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } },
+ },
+ .modalHeader5G = {
+ /* 4 idle,t1,t2,b (4 bits per setting) */
+ .antCtrlCommon = LE32(0x220),
+ /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
+ .antCtrlCommon2 = LE32(0x44444),
+ /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
+ .antCtrlChain = {
+ LE16(0x150), LE16(0x150), LE16(0x150),
+ },
+ /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
+ .xatten1DB = {0x19, 0x19, 0x19},
+
+ /*
+ * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin
+ * for merlin (0xa20c/b20c 16:12
+ */
+ .xatten1Margin = {0x14, 0x14, 0x14},
+ .tempSlope = 70,
+ .voltSlope = 0,
+ /* spurChans spur channels in usual fbin coding format */
+ .spurChans = {0, 0, 0, 0, 0},
+ /* noiseFloorThreshCh Check if the register is per chain */
+ .noiseFloorThreshCh = {-1, 0, 0},
+ .ob = {3, 3, 3}, /* 3 chain */
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+ .xpaBiasLvl = 0,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+ .antennaGain = 0,
+ .switchSettling = 0x2d,
+ .adcDesiredSize = -30,
+ .txEndToXpaOff = 0,
+ .txEndToRxOn = 0x2,
+ .txFrameToXpaOn = 0xe,
+ .thresh62 = 28,
+ .papdRateMaskHt20 = LE32(0x0cf0e0e0),
+ .papdRateMaskHt40 = LE32(0x6cf0e0e0),
+ .futureModal = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+ },
+ .base_ext2 = {
+ .tempSlopeLow = 35,
+ .tempSlopeHigh = 50,
+ .xatten1DBLow = {0, 0, 0},
+ .xatten1MarginLow = {0, 0, 0},
+ .xatten1DBHigh = {0, 0, 0},
+ .xatten1MarginHigh = {0, 0, 0}
+ },
+ .calFreqPier5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5220, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5785, 0)
+ },
+ .calPierData5G = {
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+ {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ },
+
+ },
+ .calTarget_freqbin_5G = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5600, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT20 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTarget_freqbin_5GHT40 = {
+ FREQ2FBIN(5180, 0),
+ FREQ2FBIN(5240, 0),
+ FREQ2FBIN(5320, 0),
+ FREQ2FBIN(5400, 0),
+ FREQ2FBIN(5500, 0),
+ FREQ2FBIN(5700, 0),
+ FREQ2FBIN(5745, 0),
+ FREQ2FBIN(5825, 0)
+ },
+ .calTargetPower5G = {
+ /* 6-24,36,48,54 */
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ { {30, 30, 28, 24} },
+ },
+ .calTargetPower5GHT20 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+ { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+ { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+ { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+ { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} },
+ },
+ .calTargetPower5GHT40 = {
+ /*
+ * 0_8_16,1-3_9-11_17-19,
+ * 4,5,6,7,12,13,14,15,20,21,22,23
+ */
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+ { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+ { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+ { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+ { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} },
+ },
+ .ctlIndex_5G = {
+ 0x10, 0x16, 0x18, 0x40, 0x46,
+ 0x48, 0x30, 0x36, 0x38
+ },
+ .ctl_freqbin_5G = {
+ {
+ /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+ {
+ /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0),
+ /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0),
+ /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0)
+ },
+
+ {
+ /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[3].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[3].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[4].ctlEdges[4].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[5].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[4].ctlEdges[7].bChannel */ 0xFF,
+ },
+
+ {
+ /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0),
+ /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0),
+ /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[5].ctlEdges[6].bChannel */ 0xFF,
+ /* Data[5].ctlEdges[7].bChannel */ 0xFF
+ },
+
+ {
+ /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0),
+ /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0),
+ /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0),
+ /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0)
+ },
+
+ {
+ /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0),
+ /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0),
+ /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0),
+ /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0),
+ /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0),
+ /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0),
+ /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0),
+ /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0)
+ },
+
+ {
+ /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0),
+ /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0),
+ /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0),
+ /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0),
+ /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0),
+ /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0),
+ /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0),
+ /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0)
+ }
+ },
+ .ctlPowerData_5G = {
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0),
+ }
+ },
+ {
+ {
+ CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1),
+ CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1),
+ }
+ },
+ }
+};
+
+
+static const struct ar9300_eeprom *ar9300_eep_templates[] = {
+ &ar9300_default,
+ &ar9300_x112,
+ &ar9300_h116,
+ &ar9300_h112,
+ &ar9300_x113,
+};
+
+static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
+{
+#define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0]))
+ int it;
+
+ for (it = 0; it < N_LOOP; it++)
+ if (ar9300_eep_templates[it]->templateVersion == id)
+ return ar9300_eep_templates[it];
+ return NULL;
+#undef N_LOOP
+}
+
+
static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
{
if (fbin == AR9300_BCHAN_UNUSED)
@@ -639,6 +2985,16 @@ static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
return 0;
}
+static int interpolate(int x, int xa, int xb, int ya, int yb)
+{
+ int bf, factor, plus;
+
+ bf = 2 * (yb - ya) * (x - xa) / (xb - xa);
+ factor = bf / 2;
+ plus = bf % 2;
+ return ya + factor + plus;
+}
+
static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
@@ -676,6 +3032,8 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return le32_to_cpu(pBase->swreg);
case EEP_PAPRD:
return !!(pBase->featureEnable & BIT(5));
+ case EEP_CHAIN_MASK_REDUCE:
+ return (pBase->miscConfiguration >> 0x3) & 0x1;
default:
return 0;
}
@@ -751,6 +3109,36 @@ error:
return false;
}
+static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data)
+{
+ REG_READ(ah, AR9300_OTP_BASE + (4 * addr));
+
+ if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE,
+ AR9300_OTP_STATUS_VALID, 1000))
+ return false;
+
+ *data = REG_READ(ah, AR9300_OTP_READ_DATA);
+ return true;
+}
+
+static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer,
+ int count)
+{
+ u32 data;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ int offset = 8 * ((address - i) % 4);
+ if (!ar9300_otp_read_word(ah, (address - i) / 4, &data))
+ return false;
+
+ buffer[i] = (data >> offset) & 0xff;
+ }
+
+ return true;
+}
+
+
static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
int *length, int *major, int *minor)
{
@@ -827,6 +3215,7 @@ static int ar9300_compress_decision(struct ath_hw *ah,
{
struct ath_common *common = ath9k_hw_common(ah);
u8 *dptr;
+ const struct ar9300_eeprom *eep = NULL;
switch (code) {
case _CompressNone:
@@ -844,13 +3233,14 @@ static int ar9300_compress_decision(struct ath_hw *ah,
if (reference == 0) {
dptr = mptr;
} else {
- if (reference != 2) {
+ eep = ar9003_eeprom_struct_find_by_id(reference);
+ if (eep == NULL) {
ath_print(common, ATH_DBG_EEPROM,
"cant find reference eeprom"
"struct %d\n", reference);
return -1;
}
- memcpy(mptr, &ar9300_default, mdata_size);
+ memcpy(mptr, eep, mdata_size);
}
ath_print(common, ATH_DBG_EEPROM,
"restore eeprom %d: block, reference %d,"
@@ -866,6 +3256,38 @@ static int ar9300_compress_decision(struct ath_hw *ah,
return 0;
}
+typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer,
+ int count);
+
+static bool ar9300_check_header(void *data)
+{
+ u32 *word = data;
+ return !(*word == 0 || *word == ~0);
+}
+
+static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read,
+ int base_addr)
+{
+ u8 header[4];
+
+ if (!read(ah, base_addr, header, 4))
+ return false;
+
+ return ar9300_check_header(header);
+}
+
+static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr,
+ int mdata_size)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u16 *data = (u16 *) mptr;
+ int i;
+
+ for (i = 0; i < mdata_size / 2; i++, data++)
+ ath9k_hw_nvram_read(common, i, data);
+
+ return 0;
+}
/*
* Read the configuration data from the eeprom.
* The data can be put in any specified memory buffer.
@@ -886,6 +3308,10 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
int it;
u16 checksum, mchecksum;
struct ath_common *common = ath9k_hw_common(ah);
+ eeprom_read_op read;
+
+ if (ath9k_hw_use_flash(ah))
+ return ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
word = kzalloc(2048, GFP_KERNEL);
if (!word)
@@ -893,14 +3319,42 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
memcpy(mptr, &ar9300_default, mdata_size);
+ read = ar9300_read_eeprom;
cptr = AR9300_BASE_ADDR;
+ ath_print(common, ATH_DBG_EEPROM,
+ "Trying EEPROM accesss at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ cptr = AR9300_BASE_ADDR_512;
+ ath_print(common, ATH_DBG_EEPROM,
+ "Trying EEPROM accesss at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ read = ar9300_read_otp;
+ cptr = AR9300_BASE_ADDR;
+ ath_print(common, ATH_DBG_EEPROM,
+ "Trying OTP accesss at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ cptr = AR9300_BASE_ADDR_512;
+ ath_print(common, ATH_DBG_EEPROM,
+ "Trying OTP accesss at Address 0x%04x\n", cptr);
+ if (ar9300_check_eeprom_header(ah, read, cptr))
+ goto found;
+
+ goto fail;
+
+found:
+ ath_print(common, ATH_DBG_EEPROM, "Found valid EEPROM data");
+
for (it = 0; it < MSTATE; it++) {
- if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN))
+ if (!read(ah, cptr, word, COMP_HDR_LEN))
goto fail;
- if ((word[0] == 0 && word[1] == 0 && word[2] == 0 &&
- word[3] == 0) || (word[0] == 0xff && word[1] == 0xff
- && word[2] == 0xff && word[3] == 0xff))
+ if (!ar9300_check_header(word))
break;
ar9300_comp_hdr_unpack(word, &code, &reference,
@@ -917,8 +3371,7 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
}
osize = length;
- ar9300_read_eeprom(ah, cptr, word,
- COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
+ read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN);
checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length);
mchecksum = word[COMP_HDR_LEN + osize] |
(word[COMP_HDR_LEN + osize + 1] << 8);
@@ -995,9 +3448,9 @@ static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
{
int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
- REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3));
- REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE,
- ((bias >> 2) & 0x3));
+ REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
+ REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2);
+ REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1);
}
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
@@ -1100,6 +3553,82 @@ static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg);
}
+static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain,
+ struct ath9k_channel *chan)
+{
+ int f[3], t[3];
+ u16 value;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (chain >= 0 && chain < 3) {
+ if (IS_CHAN_2GHZ(chan))
+ return eep->modalHeader2G.xatten1DB[chain];
+ else if (eep->base_ext2.xatten1DBLow[chain] != 0) {
+ t[0] = eep->base_ext2.xatten1DBLow[chain];
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.xatten1DB[chain];
+ f[1] = 5500;
+ t[2] = eep->base_ext2.xatten1DBHigh[chain];
+ f[2] = 5785;
+ value = ar9003_hw_power_interpolate((s32) chan->channel,
+ f, t, 3);
+ return value;
+ } else
+ return eep->modalHeader5G.xatten1DB[chain];
+ }
+
+ return 0;
+}
+
+
+static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain,
+ struct ath9k_channel *chan)
+{
+ int f[3], t[3];
+ u16 value;
+ struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+
+ if (chain >= 0 && chain < 3) {
+ if (IS_CHAN_2GHZ(chan))
+ return eep->modalHeader2G.xatten1Margin[chain];
+ else if (eep->base_ext2.xatten1MarginLow[chain] != 0) {
+ t[0] = eep->base_ext2.xatten1MarginLow[chain];
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.xatten1Margin[chain];
+ f[1] = 5500;
+ t[2] = eep->base_ext2.xatten1MarginHigh[chain];
+ f[2] = 5785;
+ value = ar9003_hw_power_interpolate((s32) chan->channel,
+ f, t, 3);
+ return value;
+ } else
+ return eep->modalHeader5G.xatten1Margin[chain];
+ }
+
+ return 0;
+}
+
+static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ int i;
+ u16 value;
+ unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0,
+ AR_PHY_EXT_ATTEN_CTL_1,
+ AR_PHY_EXT_ATTEN_CTL_2,
+ };
+
+ /* Test value. if 0 then attenuation is unused. Don't load anything. */
+ for (i = 0; i < 3; i++) {
+ value = ar9003_hw_atten_chain_get(ah, i, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+ value = ar9003_hw_atten_chain_get_margin(ah, i, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[i],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value);
+ }
+}
+
static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
{
int internal_regulator =
@@ -1131,6 +3660,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_drive_strength_apply(ah);
+ ar9003_hw_atten_apply(ah, chan);
ar9003_hw_internal_regulator_apply(ah);
}
@@ -1192,7 +3722,7 @@ static int ar9003_hw_power_interpolate(int32_t x,
if (hx == lx)
y = ly;
else /* interpolate */
- y = ly + (((x - lx) * (hy - ly)) / (hx - lx));
+ y = interpolate(x, lx, hx, ly, hy);
} else /* only low is good, use it */
y = ly;
} else if (hhave) /* only high is good, use it */
@@ -1640,6 +4170,7 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
{
int tempSlope = 0;
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
+ int f[3], t[3];
REG_RMW(ah, AR_PHY_TPC_11_B0,
(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
@@ -1668,7 +4199,16 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
*/
if (frequency < 4000)
tempSlope = eep->modalHeader2G.tempSlope;
- else
+ else if (eep->base_ext2.tempSlopeLow != 0) {
+ t[0] = eep->base_ext2.tempSlopeLow;
+ f[0] = 5180;
+ t[1] = eep->modalHeader5G.tempSlope;
+ f[1] = 5500;
+ t[2] = eep->base_ext2.tempSlopeHigh;
+ f[2] = 5785;
+ tempSlope = ar9003_hw_power_interpolate((s32) frequency,
+ f, t, 3);
+ } else
tempSlope = eep->modalHeader5G.tempSlope;
REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
@@ -1772,25 +4312,23 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
/* so is the high frequency, interpolate */
if (hfrequency[ichain] - frequency < 1000) {
- correction[ichain] = lcorrection[ichain] +
- (((frequency - lfrequency[ichain]) *
- (hcorrection[ichain] -
- lcorrection[ichain])) /
- (hfrequency[ichain] - lfrequency[ichain]));
-
- temperature[ichain] = ltemperature[ichain] +
- (((frequency - lfrequency[ichain]) *
- (htemperature[ichain] -
- ltemperature[ichain])) /
- (hfrequency[ichain] - lfrequency[ichain]));
-
- voltage[ichain] =
- lvoltage[ichain] +
- (((frequency -
- lfrequency[ichain]) * (hvoltage[ichain] -
- lvoltage[ichain]))
- / (hfrequency[ichain] -
- lfrequency[ichain]));
+ correction[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ lcorrection[ichain],
+ hcorrection[ichain]);
+
+ temperature[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ ltemperature[ichain],
+ htemperature[ichain]);
+
+ voltage[ichain] = interpolate(frequency,
+ lfrequency[ichain],
+ hfrequency[ichain],
+ lvoltage[ichain],
+ hvoltage[ichain]);
}
/* only low is good, use it */
else {
@@ -1922,14 +4460,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
int i;
int16_t twiceLargestAntenna;
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11a[] = {
+ static const u16 ctlModesFor11a[] = {
CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
};
- u16 ctlModesFor11g[] = {
+ static const u16 ctlModesFor11g[] = {
CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
CTL_11G_EXT, CTL_2GHT40
};
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
struct chan_centers centers;
u8 *ctlIndex;
u8 ctlNum;
@@ -2134,8 +4674,9 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+ u8 powerLimit, bool test)
{
+ struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
u8 targetPowerValT2[ar9300RateSize];
unsigned int i = 0;
@@ -2147,7 +4688,16 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
twiceMaxRegulatoryPower,
powerLimit);
- while (i < ar9300RateSize) {
+ regulatory->max_power_level = 0;
+ for (i = 0; i < ar9300RateSize; i++) {
+ if (targetPowerValT2[i] > regulatory->max_power_level)
+ regulatory->max_power_level = targetPowerValT2[i];
+ }
+
+ if (test)
+ return;
+
+ for (i = 0; i < ar9300RateSize; i++) {
ath_print(common, ATH_DBG_EEPROM,
"TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
i++;
@@ -2162,9 +4712,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
i++;
}
- /* Write target power array to registers */
- ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
-
/*
* This is the TX power we send back to driver core,
* and it can use to pass to userspace to display our
@@ -2183,7 +4730,10 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
i = ALL_TARGET_HT20_0_8_16; /* ht20 */
ah->txpower_limit = targetPowerValT2[i];
+ regulatory->max_power_level = targetPowerValT2[i];
+ /* Write target power array to registers */
+ ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
ar9003_hw_calibration_apply(ah, chan->channel);
}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
index 655b3033396c..9c1463307f0c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
@@ -79,6 +79,15 @@
#define FIXED_CCA_THRESHOLD 15
#define AR9300_BASE_ADDR 0x3ff
+#define AR9300_BASE_ADDR_512 0x1ff
+
+#define AR9300_OTP_BASE 0x14000
+#define AR9300_OTP_STATUS 0x15f18
+#define AR9300_OTP_STATUS_TYPE 0x7
+#define AR9300_OTP_STATUS_VALID 0x4
+#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
+#define AR9300_OTP_STATUS_SM_BUSY 0x1
+#define AR9300_OTP_READ_DATA 0x15f1c
enum targetPowerHTRates {
HT_TARGET_RATE_0_8_16,
@@ -236,7 +245,7 @@ struct ar9300_modal_eep_header {
u8 thresh62;
__le32 papdRateMaskHt20;
__le32 papdRateMaskHt40;
- u8 futureModal[24];
+ u8 futureModal[10];
} __packed;
struct ar9300_cal_data_per_freq_op_loop {
@@ -269,6 +278,20 @@ struct cal_ctl_data_5g {
u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G];
} __packed;
+struct ar9300_BaseExtension_1 {
+ u8 ant_div_control;
+ u8 future[13];
+} __packed;
+
+struct ar9300_BaseExtension_2 {
+ int8_t tempSlopeLow;
+ int8_t tempSlopeHigh;
+ u8 xatten1DBLow[AR9300_MAX_CHAINS];
+ u8 xatten1MarginLow[AR9300_MAX_CHAINS];
+ u8 xatten1DBHigh[AR9300_MAX_CHAINS];
+ u8 xatten1MarginHigh[AR9300_MAX_CHAINS];
+} __packed;
+
struct ar9300_eeprom {
u8 eepromVersion;
u8 templateVersion;
@@ -278,6 +301,7 @@ struct ar9300_eeprom {
struct ar9300_base_eep_hdr baseEepHeader;
struct ar9300_modal_eep_header modalHeader2G;
+ struct ar9300_BaseExtension_1 base_ext1;
u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
struct ar9300_cal_data_per_freq_op_loop
calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
@@ -297,6 +321,7 @@ struct ar9300_eeprom {
u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
struct ar9300_modal_eep_header modalHeader5G;
+ struct ar9300_BaseExtension_2 base_ext2;
u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
struct ar9300_cal_data_per_freq_op_loop
calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 3b424ca1ba84..f5896aa30005 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar9003_txs *ads;
+ u32 status;
ads = &ah->ts_ring[ah->ts_tail];
- if ((ads->status8 & AR_TxDone) == 0)
+ status = ACCESS_ONCE(ads->status8);
+ if ((status & AR_TxDone) == 0)
return -EINPROGRESS;
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
@@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return -EIO;
}
+ if (status & AR_TxOpExceeded)
+ ts->ts_status |= ATH9K_TXERR_XTXOP;
+ ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+ ts->ts_seqnum = MS(status, AR_SeqNum);
+ ts->tid = MS(status, AR_TxTid);
+
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
- ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
ts->ts_flags = 0;
- if (ads->status3 & AR_ExcessiveRetries)
+ status = ACCESS_ONCE(ads->status2);
+ ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+ ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+ ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+ if (status & AR_TxBaStatus) {
+ ts->ts_flags |= ATH9K_TX_BA;
+ ts->ba_low = ads->status5;
+ ts->ba_high = ads->status6;
+ }
+
+ status = ACCESS_ONCE(ads->status3);
+ if (status & AR_ExcessiveRetries)
ts->ts_status |= ATH9K_TXERR_XRETRY;
- if (ads->status3 & AR_Filtered)
+ if (status & AR_Filtered)
ts->ts_status |= ATH9K_TXERR_FILT;
- if (ads->status3 & AR_FIFOUnderrun) {
+ if (status & AR_FIFOUnderrun) {
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
- if (ads->status8 & AR_TxOpExceeded)
- ts->ts_status |= ATH9K_TXERR_XTXOP;
- if (ads->status3 & AR_TxTimerExpired)
+ if (status & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
- if (ads->status3 & AR_DescCfgErr)
+ if (status & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
- if (ads->status3 & AR_TxDataUnderrun) {
+ if (status & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
- if (ads->status3 & AR_TxDelimUnderrun) {
+ if (status & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
- if (ads->status2 & AR_TxBaStatus) {
- ts->ts_flags |= ATH9K_TX_BA;
- ts->ba_low = ads->status5;
- ts->ba_high = ads->status6;
- }
-
- ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
-
- ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
- ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
- ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
- ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
- ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
- ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
- ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
- ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
- ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
- ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
- ts->ts_antenna = 0;
+ ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+ ts->ts_longretry = MS(status, AR_DataFailCnt);
+ ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
- ts->tid = MS(ads->status8, AR_TxTid);
+ status = ACCESS_ONCE(ads->status7);
+ ts->ts_rssi = MS(status, AR_TxRSSICombined);
+ ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+ ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+ ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
memset(ads, 0, sizeof(*ads));
@@ -407,12 +410,36 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
+#define FIRST_DESC_NDELIMS 60
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
- ads->ctl17 &= ~AR_AggrLen;
- ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+ if (ah->ent_mode & AR_ENT_OTP_MPSD) {
+ u32 ctl17, ndelim;
+ /*
+ * Add delimiter when using RTS/CTS with aggregation
+ * and non enterprise AR9003 card
+ */
+ ctl17 = ads->ctl17;
+ ndelim = MS(ctl17, AR_PadDelim);
+
+ if (ndelim < FIRST_DESC_NDELIMS) {
+ aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
+ ndelim = FIRST_DESC_NDELIMS;
+ }
+
+ ctl17 &= ~AR_AggrLen;
+ ctl17 |= SM(aggrLen, AR_AggrLen);
+
+ ctl17 &= ~AR_PadDelim;
+ ctl17 |= SM(ndelim, AR_PadDelim);
+
+ ads->ctl17 = ctl17;
+ } else {
+ ads->ctl17 &= ~AR_AggrLen;
+ ads->ctl17 |= SM(aggrLen, AR_AggrLen);
+ }
}
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
index 9f2cea70a840..45cc7e80436c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
@@ -65,7 +65,7 @@ struct ar9003_rxs {
u32 status9;
u32 status10;
u32 status11;
-} __packed;
+} __packed __aligned(4);
/* Transmit Control Descriptor */
struct ar9003_txc {
@@ -93,7 +93,7 @@ struct ar9003_txc {
u32 ctl21; /* DMA control 21 */
u32 ctl22; /* DMA control 22 */
u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
-} __packed;
+} __packed __aligned(4);
struct ar9003_txs {
u32 ds_info;
@@ -105,7 +105,7 @@ struct ar9003_txs {
u32 status6;
u32 status7;
u32 status8;
-} __packed;
+} __packed __aligned(4);
void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 716db414c258..850bc9866c19 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -32,12 +32,12 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_modal_eep_header *hdr;
- const u32 ctrl0[3] = {
+ static const u32 ctrl0[3] = {
AR_PHY_PAPRD_CTRL0_B0,
AR_PHY_PAPRD_CTRL0_B1,
AR_PHY_PAPRD_CTRL0_B2
};
- const u32 ctrl1[3] = {
+ static const u32 ctrl1[3] = {
AR_PHY_PAPRD_CTRL1_B0,
AR_PHY_PAPRD_CTRL1_B1,
AR_PHY_PAPRD_CTRL1_B2
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 669b777729b3..b34a9e91edd8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -128,7 +128,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
struct ath9k_channel *chan)
{
- u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
+ static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 };
int cur_bb_spur, negative = 0, cck_spur_freq;
int i;
@@ -487,7 +487,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
break;
}
- REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+ if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
+ REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+ else
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+
if (tx == 0x5) {
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
AR_PHY_SWAP_ALT_CHAIN);
@@ -614,7 +618,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), false);
return 0;
}
@@ -1023,25 +1027,25 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
int16_t nf;
nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
- nfarray[0] = sign_extend(nf, 9);
+ nfarray[0] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
- nfarray[1] = sign_extend(nf, 9);
+ nfarray[1] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
- nfarray[2] = sign_extend(nf, 9);
+ nfarray[2] = sign_extend32(nf, 8);
if (!IS_CHAN_HT40(ah->curchan))
return;
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
- nfarray[3] = sign_extend(nf, 9);
+ nfarray[3] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
- nfarray[4] = sign_extend(nf, 9);
+ nfarray[4] = sign_extend32(nf, 8);
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
- nfarray[5] = sign_extend(nf, 9);
+ nfarray[5] = sign_extend32(nf, 8);
}
static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
@@ -1113,10 +1117,55 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK;
}
+static void ar9003_hw_set_radar_params(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf)
+{
+ u32 radar_0 = 0, radar_1 = 0;
+
+ if (!conf) {
+ REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
+ return;
+ }
+
+ radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA;
+ radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR);
+ radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI);
+ radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT);
+ radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
+ radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
+
+ radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
+ radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
+ radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH);
+
+ REG_WRITE(ah, AR_PHY_RADAR_0, radar_0);
+ REG_WRITE(ah, AR_PHY_RADAR_1, radar_1);
+ if (conf->ext_channel)
+ REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+ else
+ REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+}
+
+static void ar9003_hw_set_radar_conf(struct ath_hw *ah)
+{
+ struct ath_hw_radar_conf *conf = &ah->radar_conf;
+
+ conf->fir_power = -28;
+ conf->radar_rssi = 0;
+ conf->pulse_height = 10;
+ conf->pulse_rssi = 24;
+ conf->pulse_inband = 8;
+ conf->pulse_maxlen = 255;
+ conf->pulse_inband_step = 12;
+ conf->radar_inband = 8;
+}
+
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
- const u32 ar9300_cca_regs[6] = {
+ static const u32 ar9300_cca_regs[6] = {
AR_PHY_CCA_0,
AR_PHY_CCA_1,
AR_PHY_CCA_2,
@@ -1141,8 +1190,10 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->ani_control = ar9003_hw_ani_control;
priv_ops->do_getnf = ar9003_hw_do_getnf;
priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
+ priv_ops->set_radar_params = ar9003_hw_set_radar_params;
ar9003_hw_set_nf_limits(ah);
+ ar9003_hw_set_radar_conf(ah);
memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
}
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 0d0bec3628ec..4210a9306955 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -87,33 +87,19 @@ struct ath_config {
/**
* enum buffer_type - Buffer type flags
*
- * @BUF_HT: Send this buffer using HT capabilities
* @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
* @BUF_AGGR: Indicates whether the buffer can be aggregated
* (used in aggregation scheduling)
- * @BUF_RETRY: Indicates whether the buffer is retried
* @BUF_XRETRY: To denote excessive retries of the buffer
*/
enum buffer_type {
- BUF_HT = BIT(1),
BUF_AMPDU = BIT(2),
BUF_AGGR = BIT(3),
- BUF_RETRY = BIT(4),
BUF_XRETRY = BIT(5),
};
-#define bf_nframes bf_state.bfs_nframes
-#define bf_al bf_state.bfs_al
-#define bf_frmlen bf_state.bfs_frmlen
-#define bf_retries bf_state.bfs_retries
-#define bf_seqno bf_state.bfs_seqno
-#define bf_tidno bf_state.bfs_tidno
-#define bf_keyix bf_state.bfs_keyix
-#define bf_keytype bf_state.bfs_keytype
-#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT)
#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
-#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
#define ATH_TXSTATUS_RING_SIZE 64
@@ -178,8 +164,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
/* returns delimiter padding required given the packet length */
#define ATH_AGGR_GET_NDELIM(_len) \
- (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
- (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+ (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \
+ DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ))
#define BAW_WITHIN(_start, _bawsz, _seqno) \
((((_seqno) - (_start)) & 4095) < (_bawsz))
@@ -196,7 +182,6 @@ enum ATH_AGGR_STATUS {
#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
- int axq_class;
u32 axq_qnum;
u32 *axq_link;
struct list_head axq_q;
@@ -209,27 +194,28 @@ struct ath_txq {
struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
+ int pending_frames;
};
struct ath_atx_ac {
+ struct ath_txq *txq;
int sched;
- int qnum;
struct list_head list;
struct list_head tid_q;
};
+struct ath_frame_info {
+ int framelen;
+ u32 keyix;
+ enum ath9k_key_type keytype;
+ u8 retries;
+ u16 seqno;
+};
+
struct ath_buf_state {
- int bfs_nframes;
- u16 bfs_al;
- u16 bfs_frmlen;
- int bfs_seqno;
- int bfs_tidno;
- int bfs_retries;
u8 bf_type;
u8 bfs_paprd;
- unsigned long bfs_paprd_timestamp;
- u32 bfs_keyix;
- enum ath9k_key_type bfs_keytype;
+ enum ath9k_internal_frame_type bfs_ftype;
};
struct ath_buf {
@@ -242,7 +228,6 @@ struct ath_buf {
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
- bool bf_tx_aborted;
u16 bf_flags;
struct ath_buf_state bf_state;
struct ath_wiphy *aphy;
@@ -271,7 +256,6 @@ struct ath_node {
struct ath_atx_ac ac[WME_NUM_AC];
u16 maxampdu;
u8 mpdudensity;
- int last_rssi;
};
#define AGGR_CLEANUP BIT(1)
@@ -280,6 +264,7 @@ struct ath_node {
struct ath_tx_control {
struct ath_txq *txq;
+ struct ath_node *an;
int if_id;
enum ath9k_internal_frame_type frame_type;
u8 paprd;
@@ -292,12 +277,11 @@ struct ath_tx_control {
struct ath_tx {
u16 seq_no;
u32 txqsetup;
- int hwq_map[WME_NUM_AC];
spinlock_t txbuflock;
struct list_head txbuf;
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma txdma;
- int pending_frames[WME_NUM_AC];
+ struct ath_txq *txq_map[WME_NUM_AC];
};
struct ath_rx_edma {
@@ -311,7 +295,6 @@ struct ath_rx {
u8 rxotherant;
u32 *rxlink;
unsigned int rxfilter;
- spinlock_t pcu_lock;
spinlock_t rxbuflock;
struct list_head rxbuf;
struct ath_descdma rxdma;
@@ -328,7 +311,6 @@ void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
-int ath_tx_setup(struct ath_softc *sc, int haltype);
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
void ath_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx);
@@ -343,7 +325,6 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_edma_tasklet(struct ath_softc *sc);
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
@@ -564,6 +545,7 @@ struct ath_ant_comb {
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
+#define SC_OP_ENABLE_APM BIT(15)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
@@ -601,13 +583,14 @@ struct ath_softc {
struct ath_hw *sc_ah;
void __iomem *mem;
int irq;
- spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
spinlock_t sc_pm_lock;
+ spinlock_t sc_pcu_lock;
struct mutex mutex;
struct work_struct paprd_work;
struct work_struct hw_check_work;
struct completion paprd_complete;
+ bool paprd_pending;
u32 intrstatus;
u32 sc_flags; /* SC_OP_* */
@@ -665,11 +648,11 @@ struct ath_wiphy {
bool idle;
int chan_idx;
int chan_is_ht;
+ int last_rssi;
};
void ath9k_tasklet(unsigned long data);
int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -715,10 +698,12 @@ static inline void ath_ahb_exit(void) {};
void ath9k_ps_wakeup(struct ath_softc *sc);
void ath9k_ps_restore(struct ath_softc *sc);
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
+
void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int ath9k_wiphy_add(struct ath_softc *sc);
int ath9k_wiphy_del(struct ath_wiphy *aphy);
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb);
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype);
int ath9k_wiphy_pause(struct ath_wiphy *aphy);
int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
int ath9k_wiphy_select(struct ath_wiphy *aphy);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 19891e7d49ae..47bedd82e9a9 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info qi, qi_be;
- int qnum;
+ struct ath_txq *txq;
ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc *sc)
qi.tqi_cwmax = 0;
} else {
/* Adhoc mode; important thing is to use 2x cwmin. */
- qnum = sc->tx.hwq_map[WME_AC_BE];
- ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+ txq = sc->tx.txq_map[WME_AC_BE];
+ ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
qi.tqi_aifs = qi_be.tqi_aifs;
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
qi.tqi_cwmax = qi_be.tqi_cwmax;
@@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
series[0].Tries = 1;
series[0].Rate = rate;
- series[0].ChSel = common->tx_chainmask;
+ series[0].ChSel = ath_txchainmask_reduction(sc,
+ common->tx_chainmask, series[0].Rate);
series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
series, 4, 0);
}
+static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_tx_control txctl;
+
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
+ txctl.txq = sc->beacon.cabq;
+
+ ath_print(common, ATH_DBG_XMIT,
+ "transmitting CABQ packet, skb: %p\n", skb);
+
+ if (ath_tx_start(hw, skb, &txctl) != 0) {
+ ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n");
+ dev_kfree_skb_any(skb);
+ }
+}
+
static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -503,7 +523,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
/* Set the computed AP beacon timers */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, ah->imask);
@@ -638,7 +658,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
/* Set the computed STA beacon timers */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath9k_hw_set_sta_beacon_timers(ah, &bs);
ah->imask |= ATH9K_INT_BMISS;
ath9k_hw_set_interrupts(ah, ah->imask);
@@ -686,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
/* Set the computed ADHOC beacon timers */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, ah->imask);
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 6a92e57fddf0..d33bf204c995 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -35,29 +35,6 @@ struct ath_btcoex_config {
bool bt_hold_rx_clear;
};
-static const u16 ath_subsysid_tbl[] = {
- AR9280_COEX2WIRE_SUBSYSID,
- AT9285_COEX3WIRE_SA_SUBSYSID,
- AT9285_COEX3WIRE_DA_SUBSYSID
-};
-
-/*
- * Checks the subsystem id of the device to see if it
- * supports btcoex
- */
-bool ath9k_hw_btcoex_supported(struct ath_hw *ah)
-{
- int i;
-
- if (!ah->hw_version.subsysid)
- return false;
-
- for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
- if (ah->hw_version.subsysid == ath_subsysid_tbl[i])
- return true;
-
- return false;
-}
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
{
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 1ee5a15ccbb1..588dfd464dd1 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -49,7 +49,6 @@ struct ath_btcoex_hw {
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
};
-bool ath9k_hw_btcoex_supported(struct ath_hw *ah);
void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index f43a2d98421c..48b07c319a7f 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
/*
* Update internal channel flags.
*/
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
- struct ath9k_channel *ichan)
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
{
- struct ieee80211_channel *chan = hw->conf.channel;
- struct ieee80211_conf *conf = &hw->conf;
-
ichan->channel = chan->center_freq;
ichan->chan = chan;
@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
}
- if (conf_is_ht(conf))
- ichan->chanmode = ath9k_get_extchanmode(chan,
- conf->channel_type);
+ if (channel_type != NL80211_CHAN_NO_HT)
+ ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
}
EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
chan_idx = curchan->hw_value;
channel = &ah->channels[chan_idx];
- ath9k_cmn_update_ichannel(hw, channel);
+ ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
return channel;
}
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index fea3b3315391..4c04ee85ff0e 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -31,10 +31,11 @@
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
-#define WME_AC_BE 0
-#define WME_AC_BK 1
-#define WME_AC_VI 2
-#define WME_AC_VO 3
+/* These must match mac80211 skb queue mapping numbers */
+#define WME_AC_VO 0
+#define WME_AC_VI 1
+#define WME_AC_BE 2
+#define WME_AC_BK 3
#define WME_NUM_AC 4
#define ATH_RSSI_DUMMY_MARKER 0x127
@@ -62,8 +63,9 @@ enum ath_stomp_type {
int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
- struct ath9k_channel *ichan);
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type);
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
struct ath_hw *ah);
int ath9k_cmn_count_streams(unsigned int chainmask, int max);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 43e71a944cb1..3586c43077a7 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -24,8 +24,6 @@
#define REG_READ_D(_ah, _reg) \
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
-static struct dentry *ath9k_debugfs_root;
-
static int ath9k_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
@@ -461,16 +459,16 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
/* Put variable-length stuff down here, and check for overflows. */
for (i = 0; i < sc->num_sec_wiphy; i++) {
- struct ath_wiphy *aphy = sc->sec_wiphy[i];
- if (aphy == NULL)
+ struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
+ if (aphy_tmp == NULL)
continue;
- chan = aphy->hw->conf.channel;
+ chan = aphy_tmp->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),
+ wiphy_name(aphy_tmp->hw->wiphy),
+ ath_wiphy_state_str(aphy_tmp->state),
ieee80211_frequency_to_channel(chan->center_freq),
- aphy->chan_is_ht);
+ aphy_tmp->chan_is_ht);
}
if (len > sizeof(buf))
len = sizeof(buf);
@@ -585,10 +583,10 @@ static const struct file_operations fops_wiphy = {
do { \
len += snprintf(buf + len, size - len, \
"%s%13u%11u%10u%10u\n", str, \
- sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \
- sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \
- sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \
- sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \
+ sc->debug.stats.txstats[WME_AC_BE].elem, \
+ sc->debug.stats.txstats[WME_AC_BK].elem, \
+ sc->debug.stats.txstats[WME_AC_VI].elem, \
+ sc->debug.stats.txstats[WME_AC_VO].elem); \
} while(0)
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -630,33 +628,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
return retval;
}
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_buf *bf, struct ath_tx_status *ts)
+void ath_debug_stat_tx(struct ath_softc *sc, 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;
+ int qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
+ TX_STAT_INC(qnum, tx_pkts_all);
+ sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) {
if (bf_isxretried(bf))
- TX_STAT_INC(txq->axq_qnum, a_xretries);
+ TX_STAT_INC(qnum, a_xretries);
else
- TX_STAT_INC(txq->axq_qnum, a_completed);
+ TX_STAT_INC(qnum, a_completed);
} else {
- TX_STAT_INC(txq->axq_qnum, completed);
+ TX_STAT_INC(qnum, completed);
}
if (ts->ts_status & ATH9K_TXERR_FIFO)
- TX_STAT_INC(txq->axq_qnum, fifo_underrun);
+ TX_STAT_INC(qnum, fifo_underrun);
if (ts->ts_status & ATH9K_TXERR_XTXOP)
- TX_STAT_INC(txq->axq_qnum, xtxop);
+ TX_STAT_INC(qnum, xtxop);
if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
- TX_STAT_INC(txq->axq_qnum, timer_exp);
+ TX_STAT_INC(qnum, timer_exp);
if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
- TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
+ TX_STAT_INC(qnum, desc_cfg_err);
if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
- TX_STAT_INC(txq->axq_qnum, data_underrun);
+ TX_STAT_INC(qnum, data_underrun);
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
- TX_STAT_INC(txq->axq_qnum, delim_underrun);
+ TX_STAT_INC(qnum, delim_underrun);
}
static const struct file_operations fops_xmit = {
@@ -876,11 +876,8 @@ int ath9k_init_debug(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv;
- if (!ath9k_debugfs_root)
- return -ENOENT;
-
- sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
- ath9k_debugfs_root);
+ sc->debug.debugfs_phy = debugfs_create_dir("ath9k",
+ sc->hw->wiphy->debugfsdir);
if (!sc->debug.debugfs_phy)
return -ENOMEM;
@@ -933,29 +930,7 @@ int ath9k_init_debug(struct ath_hw *ah)
sc->debug.regidx = 0;
return 0;
err:
- ath9k_exit_debug(ah);
- return -ENOMEM;
-}
-
-void ath9k_exit_debug(struct ath_hw *ah)
-{
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_softc *sc = (struct ath_softc *) common->priv;
-
debugfs_remove_recursive(sc->debug.debugfs_phy);
-}
-
-int ath9k_debug_create_root(void)
-{
- ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!ath9k_debugfs_root)
- return -ENOENT;
-
- return 0;
-}
-
-void ath9k_debug_remove_root(void)
-{
- debugfs_remove(ath9k_debugfs_root);
- ath9k_debugfs_root = NULL;
+ sc->debug.debugfs_phy = NULL;
+ return -ENOMEM;
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index bb0823242ba0..1e5078bd0344 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -164,13 +164,10 @@ struct ath9k_debug {
};
int ath9k_init_debug(struct ath_hw *ah);
-void ath9k_exit_debug(struct ath_hw *ah);
-int ath9k_debug_create_root(void);
-void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_buf *bf, struct ath_tx_status *ts);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_status *ts);
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
#else
@@ -180,26 +177,12 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
-static inline void ath9k_exit_debug(struct ath_hw *ah)
-{
-}
-
-static inline int ath9k_debug_create_root(void)
-{
- return 0;
-}
-
-static inline void ath9k_debug_remove_root(void)
-{
-}
-
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
}
static inline void ath_debug_stat_tx(struct ath_softc *sc,
- struct ath_txq *txq,
struct ath_buf *bf,
struct ath_tx_status *ts)
{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index dd59f09441a3..8b9885b5243f 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -280,6 +280,7 @@ enum eeprom_param {
EEP_PAPRD,
EEP_MODAL_VER,
EEP_ANT_DIV_CTL1,
+ EEP_CHAIN_MASK_REDUCE
};
enum ar5416_rates {
@@ -681,7 +682,8 @@ struct eeprom_ops {
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
u16 cfgCtl, u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower, u8 powerLimit);
+ u8 twiceMaxRegulatoryPower, u8 powerLimit,
+ bool test);
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 4fa4d8e28c64..c2481b3ac7e6 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -534,7 +534,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
u16 twiceMinEdgePower;
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
struct chan_centers centers;
struct cal_ctl_data_4k *rep;
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -550,10 +552,10 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
0, {0, 0, 0, 0}
};
- u16 ctlModesFor11g[] =
- { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
- CTL_2GHT40
- };
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
ath9k_hw_get_channel_centers(ah, chan, &centers);
@@ -726,7 +728,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+ u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -751,15 +753,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
+ regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > AR5416_MAX_RATE_POWER)
ratesArray[i] = AR5416_MAX_RATE_POWER;
+
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
}
+ if (test)
+ return;
/* Update regulatory */
-
i = rate6mb;
if (IS_CHAN_HT40(chan))
i = rateHt40_0;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 195406db3bd8..bcb9ed39c047 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -37,10 +37,10 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
int addr, eep_start_loc;
eep_data = (u16 *)eep;
- if (AR9287_HTC_DEVID(ah))
- eep_start_loc = AR9287_HTC_EEP_START_LOC;
- else
+ if (!common->driver_info)
eep_start_loc = AR9287_EEP_START_LOC;
+ else
+ eep_start_loc = AR9287_HTC_EEP_START_LOC;
if (!ath9k_hw_use_flash(ah)) {
ath_print(common, ATH_DBG_EEPROM,
@@ -626,13 +626,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
struct cal_target_power_ht targetPowerHt20,
targetPowerHt40 = {0, {0, 0, 0, 0} };
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11g[] = {CTL_11B,
- CTL_11G,
- CTL_2GHT20,
- CTL_11B_EXT,
- CTL_11G_EXT,
- CTL_2GHT40};
- u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
+ u16 numCtlModes = 0;
+ const u16 *pCtlMode = NULL;
+ u16 ctlMode, freq;
struct chan_centers centers;
int tx_chainmask;
u16 twiceMinEdgePower;
@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+ u8 powerLimit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
@@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
+ regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > AR9287_MAX_RATE_POWER)
ratesArray[i] = AR9287_MAX_RATE_POWER;
+
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
}
+ if (test)
+ return;
+
+ if (IS_CHAN_2GHZ(chan))
+ i = rate1l;
+ else
+ i = rate6mb;
+
+ regulatory->max_power_level = ratesArray[i];
+
if (AR_SREV_9280_20_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++)
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
@@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
}
-
- if (IS_CHAN_2GHZ(chan))
- i = rate1l;
- else
- i = rate6mb;
-
- if (AR_SREV_9280_20_OR_LATER(ah))
- regulatory->max_power_level =
- ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
- else
- regulatory->max_power_level = ratesArray[i];
}
static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 526d7c933f7f..45f70b2404a1 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -1022,13 +1022,16 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
0, {0, 0, 0, 0}
};
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11a[] =
- { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
- u16 ctlModesFor11g[] =
- { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
- CTL_2GHT40
- };
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ static const u16 ctlModesFor11a[] = {
+ CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+ };
+ static const u16 ctlModesFor11g[] = {
+ CTL_11B, CTL_11G, CTL_2GHT20,
+ CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
+ };
+ u16 numCtlModes;
+ const u16 *pCtlMode;
+ u16 ctlMode, freq;
struct chan_centers centers;
int tx_chainmask;
u16 twiceMinEdgePower;
@@ -1259,7 +1262,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
u16 cfgCtl,
u8 twiceAntennaReduction,
u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+ u8 powerLimit, bool test)
{
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -1286,12 +1289,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
+ regulatory->max_power_level = 0;
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
if (ratesArray[i] > AR5416_MAX_RATE_POWER)
ratesArray[i] = AR5416_MAX_RATE_POWER;
+ if (ratesArray[i] > regulatory->max_power_level)
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ if (!test) {
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ regulatory->max_power_level = ratesArray[i];
+ }
+
+ switch(ar5416_get_ntxchains(ah->txchainmask)) {
+ case 1:
+ break;
+ case 2:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+ break;
+ case 3:
+ regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+ break;
+ default:
+ ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
+ "Invalid chainmask configuration\n");
+ break;
}
+ if (test)
+ return;
+
if (AR_SREV_9280_20_OR_LATER(ah)) {
for (i = 0; i < Ar5416RateSize; i++) {
int8_t pwr_table_offset;
@@ -1388,34 +1423,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
| ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
-
- i = rate6mb;
-
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
-
- if (AR_SREV_9280_20_OR_LATER(ah))
- regulatory->max_power_level =
- ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
- else
- regulatory->max_power_level = ratesArray[i];
-
- switch(ar5416_get_ntxchains(ah->txchainmask)) {
- case 1:
- break;
- case 2:
- regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
- break;
- case 3:
- regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
- break;
- default:
- ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
- "Invalid chainmask configuration\n");
- break;
- }
}
static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 4a9a68bba324..6a1a482f9dc3 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ah->imask |= ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->imask);
}
@@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
/* if no timer is enabled, turn off interrupt mask */
if (timer_table->timer_mask.val == 0) {
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ah->imask &= ~ATH9K_INT_GENTIMER;
ath9k_hw_set_interrupts(ah, ah->imask);
}
@@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsigned long data)
timer_period = is_btscan ? btcoex->btscan_no_stomp :
btcoex->btcoex_no_stomp;
- ath9k_gen_timer_start(ah,
- btcoex->no_stomp_timer,
- (ath9k_hw_gettsf32(ah) +
- timer_period), timer_period * 10);
+ ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0,
+ timer_period * 10);
btcoex->hw_timer_enabled = true;
}
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index dfb6560dab92..8946e8ad1b85 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -28,10 +28,16 @@ MODULE_FIRMWARE(FIRMWARE_AR9271);
static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
{ USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
- { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */
- { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */
+ { USB_DEVICE(0x0cf3, 0x7010),
+ .driver_info = AR7010_DEVICE },
+ /* Atheros */
+ { USB_DEVICE(0x0cf3, 0x7015),
+ .driver_info = AR7010_DEVICE | AR9287_DEVICE },
+ /* Atheros */
{ USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
- { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */
+ { USB_DEVICE(0x0846, 0x9018),
+ .driver_info = AR7010_DEVICE },
+ /* Netgear WNDA3200 */
{ USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
{ USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
{ USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
@@ -40,9 +46,13 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */
{ USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
- { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
+ { USB_DEVICE(0x083A, 0xA704),
+ .driver_info = AR7010_DEVICE },
+ /* SMC Networks */
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
- { USB_DEVICE(0x1668, 0x1200) }, /* Verizon */
+ { USB_DEVICE(0x1668, 0x1200),
+ .driver_info = AR7010_DEVICE | AR9287_DEVICE },
+ /* Verizon */
{ },
};
@@ -353,9 +363,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
struct sk_buff *skb)
{
struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
- int index = 0, i = 0, chk_idx, len = skb->len;
- int rx_remain_len = 0, rx_pkt_len = 0;
- u16 pkt_len, pkt_tag, pool_index = 0;
+ int index = 0, i = 0, len = skb->len;
+ int rx_remain_len, rx_pkt_len;
+ u16 pool_index = 0;
u8 *ptr;
spin_lock(&hif_dev->rx_lock);
@@ -389,64 +399,64 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
spin_unlock(&hif_dev->rx_lock);
while (index < len) {
+ u16 pkt_len;
+ u16 pkt_tag;
+ u16 pad_len;
+ int chk_idx;
+
ptr = (u8 *) skb->data;
pkt_len = ptr[index] + (ptr[index+1] << 8);
pkt_tag = ptr[index+2] + (ptr[index+3] << 8);
- if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) {
- u16 pad_len;
-
- pad_len = 4 - (pkt_len & 0x3);
- if (pad_len == 4)
- pad_len = 0;
-
- chk_idx = index;
- index = index + 4 + pkt_len + pad_len;
-
- if (index > MAX_RX_BUF_SIZE) {
- spin_lock(&hif_dev->rx_lock);
- hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
- hif_dev->rx_transfer_len =
- MAX_RX_BUF_SIZE - chk_idx - 4;
- hif_dev->rx_pad_len = pad_len;
-
- nskb = __dev_alloc_skb(pkt_len + 32,
- GFP_ATOMIC);
- if (!nskb) {
- dev_err(&hif_dev->udev->dev,
- "ath9k_htc: RX memory allocation"
- " error\n");
- spin_unlock(&hif_dev->rx_lock);
- goto err;
- }
- skb_reserve(nskb, 32);
- RX_STAT_INC(skb_allocated);
-
- memcpy(nskb->data, &(skb->data[chk_idx+4]),
- hif_dev->rx_transfer_len);
-
- /* Record the buffer pointer */
- hif_dev->remain_skb = nskb;
+ if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
+ RX_STAT_INC(skb_dropped);
+ return;
+ }
+
+ pad_len = 4 - (pkt_len & 0x3);
+ if (pad_len == 4)
+ pad_len = 0;
+
+ chk_idx = index;
+ index = index + 4 + pkt_len + pad_len;
+
+ if (index > MAX_RX_BUF_SIZE) {
+ spin_lock(&hif_dev->rx_lock);
+ hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
+ hif_dev->rx_transfer_len =
+ MAX_RX_BUF_SIZE - chk_idx - 4;
+ hif_dev->rx_pad_len = pad_len;
+
+ nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
+ if (!nskb) {
+ dev_err(&hif_dev->udev->dev,
+ "ath9k_htc: RX memory allocation error\n");
spin_unlock(&hif_dev->rx_lock);
- } else {
- nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
- if (!nskb) {
- dev_err(&hif_dev->udev->dev,
- "ath9k_htc: RX memory allocation"
- " error\n");
- goto err;
- }
- skb_reserve(nskb, 32);
- RX_STAT_INC(skb_allocated);
-
- memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
- skb_put(nskb, pkt_len);
- skb_pool[pool_index++] = nskb;
+ goto err;
}
+ skb_reserve(nskb, 32);
+ RX_STAT_INC(skb_allocated);
+
+ memcpy(nskb->data, &(skb->data[chk_idx+4]),
+ hif_dev->rx_transfer_len);
+
+ /* Record the buffer pointer */
+ hif_dev->remain_skb = nskb;
+ spin_unlock(&hif_dev->rx_lock);
} else {
- RX_STAT_INC(skb_dropped);
- return;
+ nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
+ if (!nskb) {
+ dev_err(&hif_dev->udev->dev,
+ "ath9k_htc: RX memory allocation error\n");
+ goto err;
+ }
+ skb_reserve(nskb, 32);
+ RX_STAT_INC(skb_allocated);
+
+ memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
+ skb_put(nskb, pkt_len);
+ skb_pool[pool_index++] = nskb;
}
}
@@ -461,7 +471,7 @@ err:
static void ath9k_hif_usb_rx_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
- struct hif_device_usb *hif_dev = (struct hif_device_usb *)
+ struct hif_device_usb *hif_dev =
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
int ret;
@@ -508,7 +518,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *) urb->context;
struct sk_buff *nskb;
- struct hif_device_usb *hif_dev = (struct hif_device_usb *)
+ struct hif_device_usb *hif_dev =
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
int ret;
@@ -776,7 +786,8 @@ static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
}
-static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev,
+ u32 drv_info)
{
int transfer, err;
const void *data = hif_dev->firmware->data;
@@ -807,18 +818,10 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
}
kfree(buf);
- switch (hif_dev->device_id) {
- case 0x7010:
- case 0x7015:
- case 0x9018:
- case 0xA704:
- case 0x1200:
+ if (drv_info & AR7010_DEVICE)
firm_offset = AR7010_FIRMWARE_TEXT;
- break;
- default:
+ else
firm_offset = AR9271_FIRMWARE_TEXT;
- break;
- }
/*
* Issue FW download complete command to firmware.
@@ -836,7 +839,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
return 0;
}
-static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
+static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
{
int ret, idx;
struct usb_host_interface *alt = &hif_dev->interface->altsetting[0];
@@ -852,7 +855,7 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev)
}
/* Download firmware */
- ret = ath9k_hif_usb_download_fw(hif_dev);
+ ret = ath9k_hif_usb_download_fw(hif_dev, drv_info);
if (ret) {
dev_err(&hif_dev->udev->dev,
"ath9k_htc: Firmware - %s download failed\n",
@@ -931,23 +934,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
/* Find out which firmware to load */
- switch(hif_dev->device_id) {
- case 0x7010:
- case 0x7015:
- case 0x9018:
- case 0xA704:
- case 0x1200:
+ if (id->driver_info & AR7010_DEVICE)
if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
hif_dev->fw_name = FIRMWARE_AR7010_1_1;
else
hif_dev->fw_name = FIRMWARE_AR7010;
- break;
- default:
+ else
hif_dev->fw_name = FIRMWARE_AR9271;
- break;
- }
- ret = ath9k_hif_usb_dev_init(hif_dev);
+ ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info);
if (ret) {
ret = -EINVAL;
goto err_hif_init_usb;
@@ -955,7 +950,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
ret = ath9k_htc_hw_init(hif_dev->htc_handle,
&hif_dev->udev->dev, hif_dev->device_id,
- hif_dev->udev->product);
+ hif_dev->udev->product, id->driver_info);
if (ret) {
ret = -EINVAL;
goto err_htc_hw_init;
@@ -998,8 +993,7 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev)
static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct hif_device_usb *hif_dev =
- (struct hif_device_usb *) usb_get_intfdata(interface);
+ struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
if (hif_dev) {
ath9k_htc_hw_deinit(hif_dev->htc_handle,
@@ -1021,8 +1015,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
static int ath9k_hif_usb_suspend(struct usb_interface *interface,
pm_message_t message)
{
- struct hif_device_usb *hif_dev =
- (struct hif_device_usb *) usb_get_intfdata(interface);
+ struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
ath9k_hif_usb_dealloc_urbs(hif_dev);
@@ -1031,8 +1024,8 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface,
static int ath9k_hif_usb_resume(struct usb_interface *interface)
{
- struct hif_device_usb *hif_dev =
- (struct hif_device_usb *) usb_get_intfdata(interface);
+ struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
+ struct htc_target *htc_handle = hif_dev->htc_handle;
int ret;
ret = ath9k_hif_usb_alloc_urbs(hif_dev);
@@ -1040,7 +1033,8 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
return ret;
if (hif_dev->firmware) {
- ret = ath9k_hif_usb_download_fw(hif_dev);
+ ret = ath9k_hif_usb_download_fw(hif_dev,
+ htc_handle->drv_priv->ah->common.driver_info);
if (ret)
goto fail_resume;
} else {
@@ -1050,7 +1044,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface)
mdelay(100);
- ret = ath9k_htc_resume(hif_dev->htc_handle);
+ ret = ath9k_htc_resume(htc_handle);
if (ret)
goto fail_resume;
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 75ecf6a30d25..afe39a911906 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -368,7 +368,7 @@ struct ath9k_htc_priv {
u16 seq_no;
u32 bmiss_cnt;
- struct ath9k_hw_cal_data caldata[38];
+ struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS];
spinlock_t beacon_lock;
@@ -461,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv);
void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
- u16 devid, char *product);
+ u16 devid, char *product, u32 drv_info);
void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug);
#ifdef CONFIG_PM
int ath9k_htc_resume(struct htc_target *htc_handle);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 7c8a38d04561..071d0c974747 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -181,7 +181,8 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
return htc_connect_service(priv->htc, &req, ep_id);
}
-static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
+static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
+ u32 drv_info)
{
int ret;
@@ -245,17 +246,10 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
* the HIF layer, shouldn't matter much.
*/
- switch(devid) {
- case 0x7010:
- case 0x7015:
- case 0x9018:
- case 0xA704:
- case 0x1200:
+ if (drv_info & AR7010_DEVICE)
priv->htc->credits = 45;
- break;
- default:
+ else
priv->htc->credits = 33;
- }
ret = htc_init(priv->htc);
if (ret)
@@ -308,7 +302,7 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
- __be32 buf[2] = {
+ const __be32 buf[2] = {
cpu_to_be32(reg_offset),
cpu_to_be32(val),
};
@@ -627,7 +621,8 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
}
static int ath9k_init_priv(struct ath9k_htc_priv *priv,
- u16 devid, char *product)
+ u16 devid, char *product,
+ u32 drv_info)
{
struct ath_hw *ah = NULL;
struct ath_common *common;
@@ -641,6 +636,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
ah->hw_version.devid = devid;
ah->hw_version.subsysid = 0; /* FIXME */
+ ah->ah_flags |= AH_USE_EEPROM;
priv->ah = ah;
common = ath9k_hw_common(ah);
@@ -650,6 +646,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
common->hw = priv->hw;
common->priv = priv;
common->debug_mask = ath9k_debug;
+ common->driver_info = drv_info;
spin_lock_init(&priv->wmi->wmi_lock);
spin_lock_init(&priv->beacon_lock);
@@ -762,7 +759,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
}
static int ath9k_init_device(struct ath9k_htc_priv *priv,
- u16 devid, char *product)
+ u16 devid, char *product, u32 drv_info)
{
struct ieee80211_hw *hw = priv->hw;
struct ath_common *common;
@@ -771,7 +768,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
struct ath_regulatory *reg;
/* Bring up device */
- error = ath9k_init_priv(priv, devid, product);
+ error = ath9k_init_priv(priv, devid, product, drv_info);
if (error != 0)
goto err_init;
@@ -829,7 +826,7 @@ err_init:
}
int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
- u16 devid, char *product)
+ u16 devid, char *product, u32 drv_info)
{
struct ieee80211_hw *hw;
struct ath9k_htc_priv *priv;
@@ -856,14 +853,14 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
goto err_free;
}
- ret = ath9k_init_htc_services(priv, devid);
+ ret = ath9k_init_htc_services(priv, devid, drv_info);
if (ret)
goto err_init;
/* The device may have been unplugged earlier. */
priv->op_flags &= ~OP_UNPLUGGED;
- ret = ath9k_init_device(priv, devid, product);
+ ret = ath9k_init_device(priv, devid, product, drv_info);
if (ret)
goto err_init;
@@ -893,14 +890,15 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
#ifdef CONFIG_PM
int ath9k_htc_resume(struct htc_target *htc_handle)
{
+ struct ath9k_htc_priv *priv = htc_handle->drv_priv;
int ret;
- ret = ath9k_htc_wait_for_target(htc_handle->drv_priv);
+ ret = ath9k_htc_wait_for_target(priv);
if (ret)
return ret;
- ret = ath9k_init_htc_services(htc_handle->drv_priv,
- htc_handle->drv_priv->ah->hw_version.devid);
+ ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
+ priv->ah->common.driver_info);
return ret;
}
#endif
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 9a3be8da755d..8266ce1f02e3 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9k_htc_priv *priv)
struct ath_hw *ah = priv->ah;
if (priv->curtxpow != priv->txpowlimit) {
- ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
+ ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
/* read back in case value is clamped */
priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
}
@@ -1400,7 +1400,9 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
curchan->center_freq);
- ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
+ ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
+ hw->conf.channel,
+ hw->conf.channel_type);
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
ath_print(common, ATH_DBG_FATAL,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 29d80ca78393..77958675b55f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -20,8 +20,15 @@
/* TX */
/******/
+static const int subtype_txq_to_hwq[] = {
+ [WME_AC_BE] = ATH_TXQ_AC_BE,
+ [WME_AC_BK] = ATH_TXQ_AC_BK,
+ [WME_AC_VI] = ATH_TXQ_AC_VI,
+ [WME_AC_VO] = ATH_TXQ_AC_VO,
+};
+
#define ATH9K_HTC_INIT_TXQ(subtype) do { \
- qi.tqi_subtype = subtype; \
+ qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 861ec9269309..c41ab8c30161 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -462,9 +462,10 @@ void ath9k_htc_hw_free(struct htc_target *htc)
}
int ath9k_htc_hw_init(struct htc_target *target,
- struct device *dev, u16 devid, char *product)
+ struct device *dev, u16 devid,
+ char *product, u32 drv_info)
{
- if (ath9k_htc_probe_device(target, dev, devid, product)) {
+ if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) {
printk(KERN_ERR "Failed to initialize the device\n");
return -ENODEV;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h
index 07b6509d5896..ecd018798c47 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.h
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.h
@@ -77,20 +77,6 @@ struct htc_config_pipe_msg {
u8 credits;
} __packed;
-struct htc_packet {
- void *pktcontext;
- u8 *buf;
- u8 *buf_payload;
- u32 buflen;
- u32 payload_len;
-
- int endpoint;
- int status;
-
- void *context;
- u32 reserved;
-};
-
struct htc_ep_callbacks {
void *priv;
void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok);
@@ -123,11 +109,6 @@ struct htc_endpoint {
#define HTC_CONTROL_BUFFER_SIZE \
(HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr))
-struct htc_control_buf {
- struct htc_packet htc_pkt;
- u8 buf[HTC_CONTROL_BUFFER_SIZE];
-};
-
#define HTC_OP_START_WAIT BIT(0)
#define HTC_OP_CONFIG_PIPE_CREDITS BIT(1)
@@ -239,7 +220,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
struct device *dev);
void ath9k_htc_hw_free(struct htc_target *htc);
int ath9k_htc_hw_init(struct htc_target *target,
- struct device *dev, u16 devid, char *product);
+ struct device *dev, u16 devid, char *product,
+ u32 drv_info);
void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);
#endif /* HTC_HST_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c7fbe25cc128..9b1ee7fc05c1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -310,10 +310,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
struct ath_common *common = ath9k_hw_common(ah);
u32 regAddr[2] = { AR_STA_ID0 };
u32 regHold[2];
- u32 patternData[4] = { 0x55555555,
- 0xaaaaaaaa,
- 0x66666666,
- 0x99999999 };
+ static const u32 patternData[4] = {
+ 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
+ };
int i, j, loop_max;
if (!AR_SREV_9300_20_OR_LATER(ah)) {
@@ -419,10 +418,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->hw_version.magic = AR5416_MAGIC;
ah->hw_version.subvendorid = 0;
- ah->ah_flags = 0;
- if (!AR_SREV_9100(ah))
- ah->ah_flags = AH_USE_EEPROM;
-
ah->atim_window = 0;
ah->sta_id1_defaults =
AR_STA_ID1_CRPT_MIC_ENABLE |
@@ -440,7 +435,7 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
u32 sum;
int i;
u16 eeval;
- u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
+ static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
sum = 0;
for (i = 0; i < 3; i++) {
@@ -1170,7 +1165,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), false);
ath9k_hw_rfbus_done(ah);
@@ -1833,6 +1828,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+ /* enable key search for every frame in an aggregate */
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
+
pCap->low_2ghz_chan = 2312;
pCap->high_2ghz_chan = 2732;
@@ -1926,8 +1925,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->num_antcfg_2ghz =
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
- if (AR_SREV_9280_20_OR_LATER(ah) &&
- ath9k_hw_btcoex_supported(ah)) {
+ if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) {
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
@@ -1963,6 +1961,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
+ if (AR_SREV_9300_20_OR_LATER(ah))
+ ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
+
if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
@@ -1973,6 +1974,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
}
+ if (AR_SREV_9300_20_OR_LATER(ah)) {
+ if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
+ pCap->hw_caps |= ATH9K_HW_CAP_APM;
+ }
+
+
return 0;
}
@@ -2177,7 +2184,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable);
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
@@ -2190,7 +2197,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
channel->max_antenna_gain * 2,
channel->max_power * 2,
min((u32) MAX_RATE_POWER,
- (u32) regulatory->power_limit));
+ (u32) regulatory->power_limit), test);
}
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
@@ -2324,11 +2331,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
return timer_table->gen_timer_index[b];
}
-u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
{
return REG_READ(ah, AR_TSF_L32);
}
-EXPORT_SYMBOL(ath9k_hw_gettsf32);
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index d47d1b4b6002..5fcfa48a45df 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -157,6 +157,13 @@
#define PAPRD_GAIN_TABLE_ENTRIES 32
#define PAPRD_TABLE_SZ 24
+enum ath_hw_txq_subtype {
+ ATH_TXQ_AC_BE = 0,
+ ATH_TXQ_AC_BK = 1,
+ ATH_TXQ_AC_VI = 2,
+ ATH_TXQ_AC_VO = 3,
+};
+
enum ath_ini_subsys {
ATH_INI_PRE = 0,
ATH_INI_CORE,
@@ -180,6 +187,7 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
ATH9K_HW_CAP_2GHZ = BIT(13),
ATH9K_HW_CAP_5GHZ = BIT(14),
+ ATH9K_HW_CAP_APM = BIT(15),
};
struct ath9k_hw_capabilities {
@@ -478,6 +486,40 @@ struct ath_hw_antcomb_conf {
};
/**
+ * struct ath_hw_radar_conf - radar detection initialization parameters
+ *
+ * @pulse_inband: threshold for checking the ratio of in-band power
+ * to total power for short radar pulses (half dB steps)
+ * @pulse_inband_step: threshold for checking an in-band power to total
+ * power ratio increase for short radar pulses (half dB steps)
+ * @pulse_height: threshold for detecting the beginning of a short
+ * radar pulse (dB step)
+ * @pulse_rssi: threshold for detecting if a short radar pulse is
+ * gone (dB step)
+ * @pulse_maxlen: maximum pulse length (0.8 us steps)
+ *
+ * @radar_rssi: RSSI threshold for starting long radar detection (dB steps)
+ * @radar_inband: threshold for checking the ratio of in-band power
+ * to total power for long radar pulses (half dB steps)
+ * @fir_power: threshold for detecting the end of a long radar pulse (dB)
+ *
+ * @ext_channel: enable extension channel radar detection
+ */
+struct ath_hw_radar_conf {
+ unsigned int pulse_inband;
+ unsigned int pulse_inband_step;
+ unsigned int pulse_height;
+ unsigned int pulse_rssi;
+ unsigned int pulse_maxlen;
+
+ unsigned int radar_rssi;
+ unsigned int radar_inband;
+ int fir_power;
+
+ bool ext_channel;
+};
+
+/**
* struct ath_hw_private_ops - callbacks used internally by hardware code
*
* This structure contains private callbacks designed to only be used internally
@@ -542,6 +584,8 @@ struct ath_hw_private_ops {
bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
int param);
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
+ void (*set_radar_params)(struct ath_hw *ah,
+ struct ath_hw_radar_conf *conf);
/* ANI */
void (*ani_cache_ini_regs)(struct ath_hw *ah);
@@ -740,6 +784,8 @@ struct ath_hw {
u8 txchainmask;
u8 rxchainmask;
+ struct ath_hw_radar_conf radar_conf;
+
u32 originalGain[22];
int initPDADC;
int PDADCdelta;
@@ -797,6 +843,9 @@ struct ath_hw {
* this register when in sleep states.
*/
u32 WARegVal;
+
+ /* Enterprise mode cap */
+ u32 ent_mode;
};
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@ -819,12 +868,6 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
return &ah->ops;
}
-static inline int sign_extend(int val, const int nbits)
-{
- int order = BIT(nbits-1);
- return (val ^ order) - order;
-}
-
/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah);
@@ -861,7 +904,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
bool ath9k_hw_phy_disable(struct ath_hw *ah);
bool ath9k_hw_disable(struct ath_hw *ah);
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
void ath9k_hw_setopmode(struct ath_hw *ah);
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
void ath9k_hw_setbssidmask(struct ath_hw *ah);
@@ -893,7 +936,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_isr(struct ath_hw *hw);
-u32 ath9k_hw_gettsf32(struct ath_hw *ah);
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 14b8ab386daf..918308a28410 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -37,6 +37,10 @@ int led_blink;
module_param_named(blink, led_blink, int, 0444);
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+static int ath9k_btcoex_enable;
+module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
+MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
+
/* We use the hw_value as an index into our private channel structure */
#define CHAN2G(_freq, _idx) { \
@@ -395,7 +399,8 @@ static void ath9k_init_crypto(struct ath_softc *sc)
static int ath9k_init_btcoex(struct ath_softc *sc)
{
- int r, qnum;
+ struct ath_txq *txq;
+ int r;
switch (sc->sc_ah->btcoex_hw.scheme) {
case ATH_BTCOEX_CFG_NONE:
@@ -408,8 +413,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
r = ath_init_btcoex_timer(sc);
if (r)
return -1;
- qnum = sc->tx.hwq_map[WME_AC_BE];
- ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
+ txq = sc->tx.txq_map[WME_AC_BE];
+ ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
break;
default:
@@ -422,59 +427,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
static int ath9k_init_queues(struct ath_softc *sc)
{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
- for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
- sc->tx.hwq_map[i] = -1;
-
sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
- if (sc->beacon.beaconq == -1) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup a beacon xmit queue\n");
- goto err;
- }
-
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
- if (sc->beacon.cabq == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup CAB xmit queue\n");
- goto err;
- }
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
ath_cabq_update(sc);
- if (!ath_tx_setup(sc, WME_AC_BK)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BK traffic\n");
- goto err;
- }
-
- if (!ath_tx_setup(sc, WME_AC_BE)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for BE traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, WME_AC_VI)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VI traffic\n");
- goto err;
- }
- if (!ath_tx_setup(sc, WME_AC_VO)) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to setup xmit queue for VO traffic\n");
- goto err;
- }
+ for (i = 0; i < WME_NUM_AC; i++)
+ sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
return 0;
-
-err:
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
- return -EIO;
}
static int ath9k_init_channels_rates(struct ath_softc *sc)
@@ -570,6 +534,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
ah->hw_version.subsysid = subsysid;
sc->sc_ah = ah;
+ if (!sc->dev->platform_data)
+ ah->ah_flags |= AH_USE_EEPROM;
+
common = ath9k_hw_common(ah);
common->ops = &ath9k_common_ops;
common->bus_ops = bus_ops;
@@ -577,10 +544,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
common->hw = sc->hw;
common->priv = sc;
common->debug_mask = ath9k_debug;
+ common->btcoex_enabled = ath9k_btcoex_enable == 1;
spin_lock_init(&common->cc_lock);
spin_lock_init(&sc->wiphy_lock);
- spin_lock_init(&sc->sc_resetlock);
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->sc_pm_lock);
mutex_init(&sc->mutex);
@@ -600,13 +567,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
if (ret)
goto err_hw;
- ret = ath9k_init_debug(ah);
- if (ret) {
- ath_print(common, ATH_DBG_FATAL,
- "Unable to create debugfs files\n");
- goto err_debug;
- }
-
ret = ath9k_init_queues(sc);
if (ret)
goto err_queues;
@@ -629,8 +589,6 @@ err_btcoex:
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
err_queues:
- ath9k_exit_debug(ah);
-err_debug:
ath9k_hw_deinit(ah);
err_hw:
tasklet_kill(&sc->intr_tq);
@@ -642,6 +600,37 @@ err_hw:
return ret;
}
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *chan;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ int i;
+
+ sband = &sc->sbands[band];
+ for (i = 0; i < sband->n_channels; i++) {
+ chan = &sband->channels[i];
+ ah->curchan = &ah->channels[chan->hw_value];
+ ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+ ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+ chan->max_power = reg->max_power_level / 2;
+ }
+}
+
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *curchan = ah->curchan;
+
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+ ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+ ah->curchan = curchan;
+}
+
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -705,6 +694,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
const struct ath_bus_ops *bus_ops)
{
struct ieee80211_hw *hw = sc->hw;
+ struct ath_wiphy *aphy = hw->priv;
struct ath_common *common;
struct ath_hw *ah;
int error = 0;
@@ -737,11 +727,20 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
if (error != 0)
goto error_rx;
+ ath9k_init_txpower_limits(sc);
+
/* Register with mac80211 */
error = ieee80211_register_hw(hw);
if (error)
goto error_register;
+ error = ath9k_init_debug(ah);
+ if (error) {
+ ath_print(common, ATH_DBG_FATAL,
+ "Unable to create debugfs files\n");
+ goto error_world;
+ }
+
/* Handle world regulatory */
if (!ath_is_world_regd(reg)) {
error = regulatory_hint(hw->wiphy, reg->alpha2);
@@ -754,6 +753,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+ aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
ath_init_leds(sc);
ath_start_rfkill_poll(sc);
@@ -799,7 +799,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
- ath9k_exit_debug(sc->sc_ah);
ath9k_hw_deinit(sc->sc_ah);
tasklet_kill(&sc->intr_tq);
@@ -866,20 +865,12 @@ static int __init ath9k_init(void)
goto err_out;
}
- error = ath9k_debug_create_root();
- if (error) {
- printk(KERN_ERR
- "ath9k: Unable to create debugfs root: %d\n",
- error);
- goto err_rate_unregister;
- }
-
error = ath_pci_init();
if (error < 0) {
printk(KERN_ERR
"ath9k: No PCI devices found, driver not installed.\n");
error = -ENODEV;
- goto err_remove_root;
+ goto err_rate_unregister;
}
error = ath_ahb_init();
@@ -893,8 +884,6 @@ static int __init ath9k_init(void)
err_pci_exit:
ath_pci_exit();
- err_remove_root:
- ath9k_debug_remove_root();
err_rate_unregister:
ath_rate_control_unregister();
err_out:
@@ -906,7 +895,6 @@ static void __exit ath9k_exit(void)
{
ath_ahb_exit();
ath_pci_exit();
- ath9k_debug_remove_root();
ath_rate_control_unregister();
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 8c13479b17cd..b04b37b1124b 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
{
u32 txcfg, curLevel, newLevel;
- enum ath9k_int omask;
if (ah->tx_trig_level >= ah->config.max_txtrig_level)
return false;
- omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
+ ath9k_hw_disable_interrupts(ah);
txcfg = REG_READ(ah, AR_TXCFG);
curLevel = MS(txcfg, AR_FTRIG);
@@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
REG_WRITE(ah, AR_TXCFG,
(txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
- ath9k_hw_set_interrupts(ah, omask);
+ ath9k_hw_enable_interrupts(ah);
ah->tx_trig_level = newLevel;
@@ -767,14 +766,6 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning)
}
EXPORT_SYMBOL(ath9k_hw_startpcureceive);
-void ath9k_hw_stoppcurecv(struct ath_hw *ah)
-{
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-
- ath9k_hw_disable_mib_counters(ah);
-}
-EXPORT_SYMBOL(ath9k_hw_stoppcurecv);
-
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
{
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
@@ -849,28 +840,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_intrpend);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
- enum ath9k_int ints)
+void ath9k_hw_disable_interrupts(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
+ REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+ (void) REG_READ(ah, AR_IER);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+ (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+ }
+}
+EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!(ah->imask & ATH9K_INT_GLOBAL))
+ return;
+
+ ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
+ REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+ AR_INTR_MAC_IRQ);
+ REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+ AR_INTR_SYNC_DEFAULT);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK,
+ AR_INTR_SYNC_DEFAULT);
+ }
+ ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+ REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+}
+EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
{
enum ath9k_int omask = ah->imask;
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
- ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-
- if (omask & ATH9K_INT_GLOBAL) {
- ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
- REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
- (void) REG_READ(ah, AR_IER);
- if (!AR_SREV_9100(ah)) {
- REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
- (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+ if (!(ints & ATH9K_INT_GLOBAL))
+ ath9k_hw_enable_interrupts(ah);
- REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
- (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
- }
- }
+ ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
/* TODO: global int Ref count */
mask = ints & ATH9K_INT_COMMON;
@@ -946,24 +968,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
}
- if (ints & ATH9K_INT_GLOBAL) {
- ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
- REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
- if (!AR_SREV_9100(ah)) {
- REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
- AR_INTR_MAC_IRQ);
- REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-
-
- REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
- AR_INTR_SYNC_DEFAULT);
- REG_WRITE(ah, AR_INTR_SYNC_MASK,
- AR_INTR_SYNC_DEFAULT);
- }
- ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
- REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
- }
+ ath9k_hw_enable_interrupts(ah);
- return omask;
+ return;
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7c1a34d64f6d..7512f97e8f49 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -104,13 +104,11 @@ struct ath_tx_status {
u32 ts_tstamp;
u16 ts_seqnum;
u8 ts_status;
- u8 ts_ratecode;
u8 ts_rateindex;
int8_t ts_rssi;
u8 ts_shortretry;
u8 ts_longretry;
u8 ts_virtcol;
- u8 ts_antenna;
u8 ts_flags;
int8_t ts_rssi_ctl0;
int8_t ts_rssi_ctl1;
@@ -121,7 +119,6 @@ struct ath_tx_status {
u8 qid;
u16 desc_id;
u8 tid;
- u8 pad[2];
u32 ba_low;
u32 ba_high;
u32 evm0;
@@ -240,7 +237,7 @@ struct ath_desc {
u32 ds_ctl1;
u32 ds_hw[20];
void *ds_vdata;
-} __packed;
+} __packed __aligned(4);
#define ATH9K_TXDESC_CLRDMASK 0x0001
#define ATH9K_TXDESC_NOACK 0x0002
@@ -310,7 +307,7 @@ struct ar5416_desc {
u32 status8;
} rx;
} u;
-} __packed;
+} __packed __aligned(4);
#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
@@ -669,6 +666,7 @@ enum ath9k_key_type {
struct ath_hw;
struct ath9k_channel;
+enum ath9k_int;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
@@ -693,15 +691,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
-void ath9k_hw_stoppcurecv(struct ath_hw *ah);
void ath9k_hw_abortpcurecv(struct ath_hw *ah);
bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
int ath9k_hw_beaconq_setup(struct ath_hw *ah);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
- enum ath9k_int ints);
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+void ath9k_hw_disable_interrupts(struct ath_hw *ah);
void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index dace215b693e..f026a031713b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -23,7 +23,7 @@ static void ath_update_txpow(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
if (sc->curtxpow != sc->config.txpowlimit) {
- ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
+ ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
/* read back in case value is clamped */
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
}
@@ -234,6 +234,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
/*
* This is only performed if the channel settings have
* actually changed.
@@ -243,11 +245,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
* hardware at the new frequency, and then re-enable
* the relevant bits of the h/w.
*/
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false);
- spin_lock_bh(&sc->rx.pcu_lock);
-
stopped = ath_stoprecv(sc);
/* XXX: do not flush receive queue here. We don't want
@@ -266,30 +266,22 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
channel->center_freq, conf_is_ht40(conf),
fastcc);
- spin_lock_bh(&sc->sc_resetlock);
-
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u MHz), "
"reset status %d\n",
channel->center_freq, r);
- spin_unlock_bh(&sc->sc_resetlock);
- spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore;
}
- spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
r = -EIO;
- spin_unlock_bh(&sc->rx.pcu_lock);
goto ps_restore;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
-
ath_update_txpow(sc);
ath9k_hw_set_interrupts(ah, ah->imask);
@@ -300,6 +292,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
}
ps_restore:
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
return r;
}
@@ -340,7 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
- int qnum, ftype;
+ int ftype;
int chain_ok = 0;
int chain;
int len = 1800;
@@ -367,8 +361,7 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
memset(&txctl, 0, sizeof(txctl));
- qnum = sc->tx.hwq_map[WME_AC_BE];
- txctl.txq = &sc->tx.txq[qnum];
+ txctl.txq = sc->tx.txq_map[WME_AC_BE];
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
@@ -386,6 +379,7 @@ void ath_paprd_calibrate(struct work_struct *work)
}
init_completion(&sc->paprd_complete);
+ sc->paprd_pending = true;
ar9003_paprd_setup_gain_table(ah, chain);
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0)
@@ -393,6 +387,7 @@ void ath_paprd_calibrate(struct work_struct *work)
time_left = wait_for_completion_timeout(&sc->paprd_complete,
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
+ sc->paprd_pending = false;
if (!time_left) {
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on "
@@ -558,15 +553,17 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht)
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
-
+ struct ath_hw *ah = sc->sc_ah;
an = (struct ath_node *)sta->drv_priv;
+ if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
+ sc->sc_flags |= SC_OP_ENABLE_APM;
+
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
- an->last_rssi = ATH_RSSI_DUMMY_MARKER;
}
}
@@ -614,6 +611,8 @@ void ath9k_tasklet(unsigned long data)
return;
}
+ spin_lock_bh(&sc->sc_pcu_lock);
+
if (!ath9k_hw_check_alive(ah))
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
@@ -624,15 +623,12 @@ void ath9k_tasklet(unsigned long data)
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
if (status & rxmask) {
- spin_lock_bh(&sc->rx.pcu_lock);
-
/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false);
- spin_unlock_bh(&sc->rx.pcu_lock);
}
if (status & ATH9K_INT_TX) {
@@ -657,7 +653,9 @@ void ath9k_tasklet(unsigned long data)
ath_gen_timer_isr(sc->sc_ah);
/* re-enable hardware interrupt */
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_enable_interrupts(ah);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
}
@@ -756,7 +754,7 @@ irqreturn_t ath_isr(int irq, void *dev)
* interrupt; otherwise it will continue to
* fire.
*/
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
/*
* Let the hal handle the event. We assume
* it will clear whatever condition caused
@@ -765,7 +763,7 @@ irqreturn_t ath_isr(int irq, void *dev)
spin_lock(&common->cc_lock);
ath9k_hw_proc_mib_event(ah);
spin_unlock(&common->cc_lock);
- ath9k_hw_set_interrupts(ah, ah->imask);
+ ath9k_hw_enable_interrupts(ah);
}
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
@@ -782,8 +780,8 @@ chip_reset:
ath_debug_stat_interrupt(sc, status);
if (sched) {
- /* turn off every interrupt except SWBA */
- ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
+ /* turn off every interrupt */
+ ath9k_hw_disable_interrupts(ah);
tasklet_schedule(&sc->intr_tq);
}
@@ -835,9 +833,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
}
static void ath9k_bss_assoc_info(struct ath_softc *sc,
+ struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
+ struct ath_wiphy *aphy = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -861,6 +861,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
ath_beacon_config(sc, vif);
/* Reset rssi stats */
+ aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_flags |= SC_OP_ANI_RUN;
@@ -882,13 +883,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
int r;
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ath9k_hw_configpcipowersave(ah, 0, 0);
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, sc->hw);
- spin_lock_bh(&sc->rx.pcu_lock);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
@@ -896,17 +897,14 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
"reset status %d\n",
channel->center_freq, r);
}
- spin_unlock_bh(&sc->sc_resetlock);
ath_update_txpow(sc);
if (ath_startrecv(sc) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Unable to restart recv logic\n");
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
return;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
-
if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */
@@ -919,6 +917,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
ieee80211_wake_queues(hw);
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
}
@@ -929,6 +929,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
int r;
ath9k_ps_wakeup(sc);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ieee80211_stop_queues(hw);
/*
@@ -941,19 +943,16 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
}
/* Disable interrupts */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, false); /* clear pending tx frames */
- spin_lock_bh(&sc->rx.pcu_lock);
-
ath_stoprecv(sc); /* turn off frame recv */
ath_flushrecv(sc); /* flush recv queue */
if (!ah->curchan)
ah->curchan = ath_get_curchannel(sc, hw);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
if (r) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
@@ -961,14 +960,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
"reset status %d\n",
channel->center_freq, r);
}
- spin_unlock_bh(&sc->sc_resetlock);
ath9k_hw_phy_disable(ah);
- spin_unlock_bh(&sc->rx.pcu_lock);
-
ath9k_hw_configpcipowersave(ah, 1, 1);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
+
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
}
@@ -982,29 +981,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
/* Stop ANI */
del_timer_sync(&common->ani.timer);
+ spin_lock_bh(&sc->sc_pcu_lock);
+
ieee80211_stop_queues(hw);
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
ath_drain_all_txq(sc, retry_tx);
- spin_lock_bh(&sc->rx.pcu_lock);
-
ath_stoprecv(sc);
ath_flushrecv(sc);
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d\n", r);
- spin_unlock_bh(&sc->sc_resetlock);
if (ath_startrecv(sc) != 0)
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");
- spin_unlock_bh(&sc->rx.pcu_lock);
-
/*
* We may be doing a reset in response to a request
* that changes the channel so update any state that
@@ -1029,6 +1024,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
}
ieee80211_wake_queues(hw);
+ spin_unlock_bh(&sc->sc_pcu_lock);
/* Start ANI */
ath_start_ani(common);
@@ -1036,56 +1032,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
return r;
}
-static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
- int qnum;
-
- switch (queue) {
- case 0:
- qnum = sc->tx.hwq_map[WME_AC_VO];
- break;
- case 1:
- qnum = sc->tx.hwq_map[WME_AC_VI];
- break;
- case 2:
- qnum = sc->tx.hwq_map[WME_AC_BE];
- break;
- case 3:
- qnum = sc->tx.hwq_map[WME_AC_BK];
- break;
- default:
- qnum = sc->tx.hwq_map[WME_AC_BE];
- break;
- }
-
- return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
- int qnum;
-
- switch (queue) {
- case WME_AC_VO:
- qnum = 0;
- break;
- case WME_AC_VI:
- qnum = 1;
- break;
- case WME_AC_BE:
- qnum = 2;
- break;
- case WME_AC_BK:
- qnum = 3;
- break;
- default:
- qnum = -1;
- break;
- }
-
- return qnum;
-}
-
/* XXX: Remove me once we don't depend on ath9k_channel for all
* this redundant data */
void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
@@ -1167,19 +1113,16 @@ static int ath9k_start(struct ieee80211_hw *hw)
* be followed by initialization of the appropriate bits
* and then setup of the interrupt mask.
*/
- spin_lock_bh(&sc->rx.pcu_lock);
- spin_lock_bh(&sc->sc_resetlock);
+ spin_lock_bh(&sc->sc_pcu_lock);
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d "
"(freq %u MHz)\n", r,
curchan->center_freq);
- spin_unlock_bh(&sc->sc_resetlock);
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
- spin_unlock_bh(&sc->sc_resetlock);
/*
* This is needed only to setup initial state
@@ -1198,10 +1141,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath_print(common, ATH_DBG_FATAL,
"Unable to start recv logic\n");
r = -EIO;
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
goto mutex_unlock;
}
- spin_unlock_bh(&sc->rx.pcu_lock);
+ spin_unlock_bh(&sc->sc_pcu_lock);
/* Setup our intr mask. */
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
@@ -1254,14 +1197,11 @@ mutex_unlock:
static int ath9k_tx(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_tx_control txctl;
- int padpos, padsize;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- int qnum;
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
ath_print(common, ATH_DBG_XMIT,
@@ -1311,31 +1251,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
}
memset(&txctl, 0, sizeof(struct ath_tx_control));
-
- /*
- * As a temporary workaround, assign seq# here; this will likely need
- * to be cleaned up to work better with Beacon transmission and virtual
- * BSSes.
- */
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- sc->tx.seq_no += 0x10;
- hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
- }
-
- /* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
- padsize = padpos & 3;
- if (padsize && skb->len>padpos) {
- if (skb_headroom(skb) < padsize)
- return -1;
- skb_push(skb, padsize);
- memmove(skb->data, skb->data + padsize, padpos);
- }
-
- qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
- txctl.txq = &sc->tx.txq[qnum];
+ txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
@@ -1399,22 +1315,25 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_btcoex_timer_pause(sc);
}
+ spin_lock_bh(&sc->sc_pcu_lock);
+
/* make sure h/w will not generate any interrupt
* before setting the invalid flag. */
- ath9k_hw_set_interrupts(ah, 0);
+ ath9k_hw_disable_interrupts(ah);
- spin_lock_bh(&sc->rx.pcu_lock);
if (!(sc->sc_flags & SC_OP_INVALID)) {
ath_drain_all_txq(sc, false);
ath_stoprecv(sc);
ath9k_hw_phy_disable(ah);
} else
sc->rx.rxlink = NULL;
- spin_unlock_bh(&sc->rx.pcu_lock);
/* disable HAL and put h/w to sleep */
ath9k_hw_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
+
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
ath9k_ps_restore(sc);
/* Finally, put the chip in FULL SLEEP mode */
@@ -1830,12 +1749,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_txq *txq;
struct ath9k_tx_queue_info qi;
- int ret = 0, qnum;
+ int ret = 0;
if (queue >= WME_NUM_AC)
return 0;
+ txq = sc->tx.txq_map[queue];
+
mutex_lock(&sc->mutex);
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1844,20 +1766,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max;
qi.tqi_burstTime = params->txop;
- qnum = ath_get_hal_qnum(queue, sc);
ath_print(common, ATH_DBG_CONFIG,
"Configure tx [queue/halq] [%d/%d], "
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
- queue, qnum, params->aifs, params->cw_min,
+ queue, txq->axq_qnum, params->aifs, params->cw_min,
params->cw_max, params->txop);
- ret = ath_txq_update(sc, qnum, &qi);
+ ret = ath_txq_update(sc, txq->axq_qnum, &qi);
if (ret)
ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
- if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
+ if (queue == WME_AC_BE && !ret)
ath_beaconq_config(sc);
mutex_unlock(&sc->mutex);
@@ -2019,7 +1940,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) {
ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
bss_conf->assoc);
- ath9k_bss_assoc_info(sc, vif, bss_conf);
+ ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
}
mutex_unlock(&sc->mutex);
@@ -2082,6 +2003,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
+ return -EOPNOTSUPP;
+
ath9k_ps_wakeup(sc);
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
if (!ret)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index b5b651413e77..09f69a9617f4 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -16,6 +16,7 @@
#include <linux/nl80211.h>
#include <linux/pci.h>
+#include <linux/ath9k_platform.h>
#include "ath9k.h"
static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
@@ -53,21 +54,36 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
- struct ath_hw *ah = (struct ath_hw *) common->ah;
-
- common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
-
- if (!ath9k_hw_wait(ah,
- AR_EEPROM_STATUS_DATA,
- AR_EEPROM_STATUS_DATA_BUSY |
- AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
- AH_WAIT_TIMEOUT)) {
- return false;
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+
+ if (pdata) {
+ if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
+ ath_print(common, ATH_DBG_FATAL,
+ "%s: eeprom read failed, offset %08x "
+ "is out of range\n",
+ __func__, off);
+ }
+
+ *data = pdata->eeprom_data[off];
+ } else {
+ struct ath_hw *ah = (struct ath_hw *) common->ah;
+
+ common->ops->read(ah, AR5416_EEPROM_OFFSET +
+ (off << AR5416_EEPROM_S));
+
+ if (!ath9k_hw_wait(ah,
+ AR_EEPROM_STATUS_DATA,
+ AR_EEPROM_STATUS_DATA_BUSY |
+ AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
+ AH_WAIT_TIMEOUT)) {
+ return false;
+ }
+
+ *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
+ AR_EEPROM_STATUS_DATA_VAL);
}
- *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
- AR_EEPROM_STATUS_DATA_VAL);
-
return true;
}
@@ -247,34 +263,25 @@ static void ath_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int ath_pci_suspend(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
- pci_save_state(pdev);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
-
return 0;
}
-static int ath_pci_resume(struct pci_dev *pdev)
+static int ath_pci_resume(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
u32 val;
- int err;
-
- pci_restore_state(pdev);
-
- err = pci_enable_device(pdev);
- if (err)
- return err;
/*
* Suspend/Resume resets the PCI configuration space, so we have to
@@ -293,7 +300,23 @@ static int ath_pci_resume(struct pci_dev *pdev)
return 0;
}
-#endif /* CONFIG_PM */
+static const struct dev_pm_ops ath9k_pm_ops = {
+ .suspend = ath_pci_suspend,
+ .resume = ath_pci_resume,
+ .freeze = ath_pci_suspend,
+ .thaw = ath_pci_resume,
+ .poweroff = ath_pci_suspend,
+ .restore = ath_pci_resume,
+};
+
+#define ATH9K_PM_OPS (&ath9k_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define ATH9K_PM_OPS NULL
+
+#endif /* !CONFIG_PM */
+
MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
@@ -302,10 +325,7 @@ static struct pci_driver ath_pci_driver = {
.id_table = ath_pci_id_table,
.probe = ath_pci_probe,
.remove = ath_pci_remove,
-#ifdef CONFIG_PM
- .suspend = ath_pci_suspend,
- .resume = ath_pci_resume,
-#endif /* CONFIG_PM */
+ .driver.pm = ATH9K_PM_OPS,
};
int ath_pci_init(void)
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 89978d71617f..3e6ea3bc3d89 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -381,25 +381,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
struct ieee80211_tx_rate *rate);
-static inline int8_t median(int8_t a, int8_t b, int8_t c)
-{
- if (a >= b) {
- if (b >= c)
- return b;
- else if (a > c)
- return c;
- else
- return a;
- } else {
- if (a >= c)
- return a;
- else if (b >= c)
- return c;
- else
- return b;
- }
-}
-
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
struct ath_rate_priv *ath_rc_priv)
{
@@ -883,7 +864,7 @@ static bool ath_rc_update_per(struct ath_softc *sc,
bool state_change = false;
int count, n_bad_frames;
u8 last_per;
- static u32 nretry_to_per_lookup[10] = {
+ static const u32 nretry_to_per_lookup[10] = {
100 * 0 / 1,
100 * 1 / 4,
100 * 1 / 2,
@@ -1106,13 +1087,13 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
struct ieee80211_tx_rate *rate)
{
int rix = 0, i = 0;
- int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
+ static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
if (!(rate->flags & IEEE80211_TX_RC_MCS))
return rate->idx;
while (rate->idx > mcs_rix_off[i] &&
- i < sizeof(mcs_rix_off)/sizeof(int)) {
+ i < ARRAY_SIZE(mcs_rix_off)) {
rix++; i++;
}
@@ -1373,23 +1354,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
tx_info->status.ampdu_len = 1;
}
- /*
- * If an underrun error is seen assume it as an excessive retry only
- * if max frame trigger level has been reached (2 KB for singel stream,
- * and 4 KB for dual stream). Adjust the long retry as if the frame was
- * tried hw->max_rate_tries times to affect how ratectrl updates PER for
- * the failed rate. In case of congestion on the bus penalizing these
- * type of underruns should help hardware actually transmit new frames
- * successfully by eventually preferring slower rates. This itself
- * should also alleviate congestion on the bus.
- */
- if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
- (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {
- tx_status = 1;
- is_underrun = 1;
- }
-
- if (tx_info->pad[0] & ATH_TX_INFO_XRETRY)
+ if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
tx_status = 1;
ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
@@ -1398,7 +1363,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
/* Check if aggregation has to be enabled for this tid */
if (conf_is_ht(&sc->hw->conf) &&
!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
- if (ieee80211_is_data_qos(fc)) {
+ if (ieee80211_is_data_qos(fc) &&
+ skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
u8 *qc, tid;
struct ath_node *an;
@@ -1444,12 +1410,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
ath_rc_priv->neg_ht_rates.rs_nrates = j;
}
- is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
if (is_cw40)
- is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
+ is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
- is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
+ is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
/* Choose rate table first */
@@ -1468,10 +1434,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
struct ath_rate_priv *ath_rc_priv = priv_sta;
const struct ath_rate_table *rate_table = NULL;
bool oper_cw40 = false, oper_sgi;
- bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
- true : false;
- bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
- true : false;
+ bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
+ bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG);
/* FIXME: Handle AP mode later when we support CWM */
@@ -1617,8 +1581,6 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp
return NULL;
}
- rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max;
-
return rate_priv;
}
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 2f46a2266ba1..31a004cb60ac 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -215,7 +215,6 @@ struct ath_rate_priv {
u32 per_down_time;
u32 probe_interval;
u32 prev_data_rix;
- u32 tx_triglevel_max;
struct ath_rateset neg_rates;
struct ath_rateset neg_ht_rates;
struct ath_rate_softc *asc;
@@ -225,11 +224,6 @@ struct ath_rate_priv {
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
};
-#define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0)
-#define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1)
-#define ATH_TX_INFO_XRETRY (1 << 3)
-#define ATH_TX_INFO_UNDERRUN (1 << 4)
-
enum ath9k_internal_frame_type {
ATH9K_IFT_NOT_INTERNAL,
ATH9K_IFT_PAUSE,
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 1a62e351ec77..262c81595f6d 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
struct ath_buf *bf;
int error = 0;
- spin_lock_init(&sc->rx.pcu_lock);
+ spin_lock_init(&sc->sc_pcu_lock);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock);
@@ -528,6 +528,8 @@ bool ath_stoprecv(struct ath_softc *sc)
sc->rx.rxlink = NULL;
spin_unlock_bh(&sc->rx.rxbuflock);
+ ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
+ "confusing the DMA engine when we start RX up\n");
return stopped;
}
@@ -962,36 +964,23 @@ static void ath9k_process_rssi(struct ath_common *common,
struct ieee80211_hdr *hdr,
struct ath_rx_status *rx_stats)
{
+ struct ath_wiphy *aphy = hw->priv;
struct ath_hw *ah = common->ah;
- struct ieee80211_sta *sta;
- struct ath_node *an;
- int last_rssi = ATH_RSSI_DUMMY_MARKER;
+ int last_rssi;
__le16 fc;
+ if (ah->opmode != NL80211_IFTYPE_STATION)
+ return;
+
fc = hdr->frame_control;
+ if (!ieee80211_is_beacon(fc) ||
+ compare_ether_addr(hdr->addr3, common->curbssid))
+ return;
- rcu_read_lock();
- /*
- * XXX: use ieee80211_find_sta! This requires quite a bit of work
- * under the current ath9k virtual wiphy implementation as we have
- * no way of tying a vif to wiphy. Typically vifs are attached to
- * at least one sdata of a wiphy on mac80211 but with ath9k virtual
- * wiphy you'd have to iterate over every wiphy and each sdata.
- */
- if (is_multicast_ether_addr(hdr->addr1))
- sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
- else
- sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
-
- if (sta) {
- an = (struct ath_node *) sta->drv_priv;
- if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
- !rx_stats->rs_moreaggr)
- ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
- last_rssi = an->last_rssi;
- }
- rcu_read_unlock();
+ if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+ ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
+ last_rssi = aphy->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
ATH_RSSI_EP_MULTIPLIER);
@@ -999,8 +988,7 @@ static void ath9k_process_rssi(struct ath_common *common,
rx_stats->rs_rssi = 0;
/* Update Beacon RSSI, this is used by ANI. */
- if (ieee80211_is_beacon(fc))
- ah->stats.avgbrssi = rx_stats->rs_rssi;
+ ah->stats.avgbrssi = rx_stats->rs_rssi;
}
/*
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 2c6a22fbb0f0..c2472edab5e0 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -864,15 +864,7 @@
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
#define AR_DEVID_7010(_ah) \
- (((_ah)->hw_version.devid == 0x7010) || \
- ((_ah)->hw_version.devid == 0x7015) || \
- ((_ah)->hw_version.devid == 0x9018) || \
- ((_ah)->hw_version.devid == 0xA704) || \
- ((_ah)->hw_version.devid == 0x1200))
-
-#define AR9287_HTC_DEVID(_ah) \
- (((_ah)->hw_version.devid == 0x7015) || \
- ((_ah)->hw_version.devid == 0x1200))
+ ((_ah)->common.driver_info & AR7010_DEVICE)
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
@@ -1074,6 +1066,9 @@ enum {
#define AR_INTR_PRIO_ASYNC_MASK 0x40c8
#define AR_INTR_PRIO_SYNC_MASK 0x40cc
#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4
+#define AR_ENT_OTP 0x40d8
+#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
+#define AR_ENT_OTP_MPSD 0x00800000
#define AR_RTC_9300_PLL_DIV 0x000003ff
#define AR_RTC_9300_PLL_DIV_S 0
@@ -1574,6 +1569,7 @@ enum {
#define AR_PCU_TBTT_PROTECT 0x00200000
#define AR_PCU_CLEAR_VMF 0x01000000
#define AR_PCU_CLEAR_BA_VALID 0x04000000
+#define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000
#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000
#define AR_PCU_BT_ANT_PREVENT_RX_S 20
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index ec7cf5ee56bc..d5442c3745cc 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
aphy->sc = sc;
aphy->hw = hw;
sc->sec_wiphy[i] = aphy;
+ aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
spin_unlock_bh(&sc->wiphy_lock);
memcpy(addr, common->macaddr, ETH_ALEN);
@@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
info->control.rates[1].idx = -1;
memset(&txctl, 0, sizeof(struct ath_tx_control));
- txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]];
+ txctl.txq = sc->tx.txq_map[WME_AC_VO];
txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
@@ -304,13 +305,12 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
* ath9k version of ieee80211_tx_status() for TX frames that are generated
* internally in the driver.
*/
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype)
{
struct ath_wiphy *aphy = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) &&
- aphy->state == ATH_WIPHY_PAUSING) {
+ if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) {
if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
"frame\n", wiphy_name(hw->wiphy));
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index f2ade2402ce2..821d3679c6ff 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -48,19 +48,17 @@ static u16 bits_per_symbol[][2] = {
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head);
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct list_head *bf_head);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *head);
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf);
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, int txok);
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
- int nbad, int txok, bool update_rc);
+ int nframes, int nbad, int txok, bool update_rc);
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
int seqno);
@@ -124,7 +122,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+ struct ath_txq *txq = tid->ac->txq;
WARN_ON(!tid->paused);
@@ -140,12 +138,21 @@ unlock:
spin_unlock_bh(&txq->axq_lock);
}
+static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ BUILD_BUG_ON(sizeof(struct ath_frame_info) >
+ sizeof(tx_info->rate_driver_data));
+ return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
+}
+
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+ struct ath_txq *txq = tid->ac->txq;
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
+ struct ath_frame_info *fi;
INIT_LIST_HEAD(&bf_head);
@@ -156,12 +163,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
list_move_tail(&bf->list, &bf_head);
- if (bf_isretried(bf)) {
- ath_tx_update_baw(sc, tid, bf->bf_seqno);
+ spin_unlock_bh(&txq->axq_lock);
+ fi = get_frame_info(bf->bf_mpdu);
+ if (fi->retries) {
+ ath_tx_update_baw(sc, tid, fi->seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
} else {
- ath_tx_send_ht_normal(sc, txq, tid, &bf_head);
+ ath_tx_send_normal(sc, txq, tid, &bf_head);
}
+ spin_lock_bh(&txq->axq_lock);
}
spin_unlock_bh(&txq->axq_lock);
@@ -184,14 +194,11 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
}
static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct ath_buf *bf)
+ u16 seqno)
{
int index, cindex;
- if (bf_isretried(bf))
- return;
-
- index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno);
+ index = ATH_BA_INDEX(tid->seq_start, seqno);
cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
__set_bit(cindex, tid->tx_buf);
@@ -215,6 +222,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf;
struct list_head bf_head;
struct ath_tx_status ts;
+ struct ath_frame_info *fi;
memset(&ts, 0, sizeof(ts));
INIT_LIST_HEAD(&bf_head);
@@ -226,8 +234,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
list_move_tail(&bf->list, &bf_head);
- if (bf_isretried(bf))
- ath_tx_update_baw(sc, tid, bf->bf_seqno);
+ fi = get_frame_info(bf->bf_mpdu);
+ if (fi->retries)
+ ath_tx_update_baw(sc, tid, fi->seqno);
spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
@@ -239,16 +248,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
}
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_buf *bf)
+ struct sk_buff *skb)
{
- struct sk_buff *skb;
+ struct ath_frame_info *fi = get_frame_info(skb);
struct ieee80211_hdr *hdr;
- bf->bf_state.bf_type |= BUF_RETRY;
- bf->bf_retries++;
TX_STAT_INC(txq->axq_qnum, a_retries);
+ if (fi->retries++ > 0)
+ return;
- skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
}
@@ -298,9 +306,41 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
return tbf;
}
+static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_status *ts, int txok,
+ int *nframes, int *nbad)
+{
+ struct ath_frame_info *fi;
+ u16 seq_st = 0;
+ u32 ba[WME_BA_BMP_SIZE >> 5];
+ int ba_index;
+ int isaggr = 0;
+
+ *nbad = 0;
+ *nframes = 0;
+
+ isaggr = bf_isaggr(bf);
+ if (isaggr) {
+ seq_st = ts->ts_seqnum;
+ memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+ }
+
+ while (bf) {
+ fi = get_frame_info(bf->bf_mpdu);
+ ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
+
+ (*nframes)++;
+ if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+ (*nbad)++;
+
+ bf = bf->bf_next;
+ }
+}
+
+
static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct list_head *bf_q,
- struct ath_tx_status *ts, int txok)
+ struct ath_tx_status *ts, int txok, bool retry)
{
struct ath_node *an = NULL;
struct sk_buff *skb;
@@ -316,7 +356,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true;
struct ieee80211_tx_rate rates[4];
+ struct ath_frame_info *fi;
int nframes;
+ u8 tidno;
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -325,7 +367,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
hw = bf->aphy->hw;
memcpy(rates, tx_info->control.rates, sizeof(rates));
- nframes = bf->bf_nframes;
rcu_read_lock();
@@ -342,7 +383,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
- ath_tx_rc_status(bf, ts, 1, 0, false);
+ ath_tx_rc_status(bf, ts, 1, 1, 0, false);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
@@ -352,14 +393,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
an = (struct ath_node *)sta->drv_priv;
- tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+ tid = ATH_AN_2_TID(an, tidno);
/*
* The hardware occasionally sends a tx status for the wrong TID.
* In this case, the BA status cannot be considered valid and all
* subframes need to be retransmitted
*/
- if (bf->bf_tidno != ts->tid)
+ if (tidno != ts->tid)
txok = false;
isaggr = bf_isaggr(bf);
@@ -385,15 +427,16 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_pending);
INIT_LIST_HEAD(&bf_head);
- nbad = ath_tx_num_badfrms(sc, bf, ts, txok);
+ ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
txfail = txpending = 0;
bf_next = bf->bf_next;
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
+ fi = get_frame_info(skb);
- if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
+ if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
/* transmit completion, subframe is
* acked by block ack */
acked_cnt++;
@@ -401,10 +444,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
/* transmit completion */
acked_cnt++;
} else {
- if (!(tid->state & AGGR_CLEANUP) &&
- !bf_last->bf_tx_aborted) {
- if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
- ath_tx_set_retry(sc, txq, bf);
+ if (!(tid->state & AGGR_CLEANUP) && retry) {
+ if (fi->retries < ATH_MAX_SW_RETRIES) {
+ ath_tx_set_retry(sc, txq, bf->bf_mpdu);
txpending = 1;
} else {
bf->bf_state.bf_type |= BUF_XRETRY;
@@ -442,16 +484,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* block-ack window
*/
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid, bf->bf_seqno);
+ ath_tx_update_baw(sc, tid, fi->seqno);
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
- bf->bf_nframes = nframes;
- ath_tx_rc_status(bf, ts, nbad, txok, true);
+ ath_tx_rc_status(bf, ts, nframes, nbad, txok, true);
rc_update = false;
} else {
- ath_tx_rc_status(bf, ts, nbad, txok, false);
+ ath_tx_rc_status(bf, ts, nframes, nbad, txok, false);
}
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
@@ -470,14 +511,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
- ath_tx_update_baw(sc, tid,
- bf->bf_seqno);
+ ath_tx_update_baw(sc, tid, fi->seqno);
spin_unlock_bh(&txq->axq_lock);
bf->bf_state.bf_type |=
BUF_XRETRY;
- ath_tx_rc_status(bf, ts, nbad,
- 0, false);
+ ath_tx_rc_status(bf, ts, nframes,
+ nbad, 0, false);
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
ts, 0, 0);
@@ -611,6 +651,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
u16 minlen;
u8 flags, rix;
int width, streams, half_gi, ndelim, mindelim;
+ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
/* Select standard number of delimiters based on frame length alone */
ndelim = ATH_AGGR_GET_NDELIM(frmlen);
@@ -621,7 +662,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* TODO - this could be improved to be dependent on the rate.
* The hardware can keep up at lower rates, but not higher rates
*/
- if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR)
+ if (fi->keyix != ATH9K_TXKEYIX_INVALID)
ndelim += ATH_AGGR_ENCRYPTDELIM;
/*
@@ -665,7 +706,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
- struct list_head *bf_q)
+ struct list_head *bf_q,
+ int *aggr_len)
{
#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
struct ath_buf *bf, *bf_first, *bf_prev = NULL;
@@ -674,14 +716,16 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
al_delta, h_baw = tid->baw_size / 2;
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
struct ieee80211_tx_info *tx_info;
+ struct ath_frame_info *fi;
bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
do {
bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+ fi = get_frame_info(bf->bf_mpdu);
/* do not step over block-ack window */
- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) {
+ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
status = ATH_AGGR_BAW_CLOSED;
break;
}
@@ -692,7 +736,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
}
/* do not exceed aggregation limit */
- al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen;
+ al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
if (nframes &&
(aggr_limit < (al + bpad + al_delta + prev_al))) {
@@ -719,14 +763,15 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
- ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
+ ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
bpad = PADBYTES(al_delta) + (ndelim << 2);
bf->bf_next = NULL;
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
/* link buffers of this frame to the aggregate */
- ath_tx_addto_baw(sc, tid, bf);
+ if (!fi->retries)
+ ath_tx_addto_baw(sc, tid, fi->seqno);
ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
list_move_tail(&bf->list, bf_q);
if (bf_prev) {
@@ -738,8 +783,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
} while (!list_empty(&tid->buf_q));
- bf_first->bf_al = al;
- bf_first->bf_nframes = nframes;
+ *aggr_len = al;
return status;
#undef PADBYTES
@@ -750,7 +794,9 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
{
struct ath_buf *bf;
enum ATH_AGGR_STATUS status;
+ struct ath_frame_info *fi;
struct list_head bf_q;
+ int aggr_len;
do {
if (list_empty(&tid->buf_q))
@@ -758,7 +804,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_q);
- status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
+ status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len);
/*
* no frames picked up to be aggregated;
@@ -771,18 +817,20 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
/* if only one frame, send as non-aggregate */
- if (bf->bf_nframes == 1) {
+ if (bf == bf->bf_lastbf) {
+ fi = get_frame_info(bf->bf_mpdu);
+
bf->bf_state.bf_type &= ~BUF_AGGR;
ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
- ath_buf_set_rate(sc, bf);
+ ath_buf_set_rate(sc, bf, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_q);
continue;
}
/* setup first desc of aggregate */
bf->bf_state.bf_type |= BUF_AGGR;
- ath_buf_set_rate(sc, bf);
- ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al);
+ ath_buf_set_rate(sc, bf, aggr_len);
+ ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
/* anchor last desc of aggregate */
ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
@@ -817,7 +865,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
- struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+ struct ath_txq *txq = txtid->ac->txq;
if (txtid->state & AGGR_CLEANUP)
return;
@@ -888,10 +936,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info qi;
+ static const int subtype_txq_to_hwq[] = {
+ [WME_AC_BE] = ATH_TXQ_AC_BE,
+ [WME_AC_BK] = ATH_TXQ_AC_BK,
+ [WME_AC_VI] = ATH_TXQ_AC_VI,
+ [WME_AC_VO] = ATH_TXQ_AC_VO,
+ };
int qnum, i;
memset(&qi, 0, sizeof(qi));
- qi.tqi_subtype = subtype;
+ qi.tqi_subtype = subtype_txq_to_hwq[subtype];
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
@@ -940,7 +994,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
if (!ATH_TXQ_SETUP(sc, qnum)) {
struct ath_txq *txq = &sc->tx.txq[qnum];
- txq->axq_class = subtype;
txq->axq_qnum = qnum;
txq->axq_link = NULL;
INIT_LIST_HEAD(&txq->axq_q);
@@ -1062,8 +1115,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
}
lastbf = bf->bf_lastbf;
- if (!retry_tx)
- lastbf->bf_tx_aborted = true;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
list_cut_position(&bf_head,
@@ -1080,7 +1131,8 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0);
+ ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+ retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
}
@@ -1101,7 +1153,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head,
- &ts, 0);
+ &ts, 0, retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head,
&ts, 0, 0);
@@ -1148,13 +1200,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
ath_print(common, ATH_DBG_FATAL,
"Failed to stop TX DMA. Resetting hardware!\n");
- spin_lock_bh(&sc->sc_resetlock);
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
if (r)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d\n",
r);
- spin_unlock_bh(&sc->sc_resetlock);
}
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
@@ -1212,24 +1262,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
}
}
-int ath_tx_setup(struct ath_softc *sc, int haltype)
-{
- struct ath_txq *txq;
-
- if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
- "HAL AC %u out of range, max %zu!\n",
- haltype, ARRAY_SIZE(sc->tx.hwq_map));
- return 0;
- }
- txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
- if (txq != NULL) {
- sc->tx.hwq_map[haltype] = txq->axq_qnum;
- return 1;
- } else
- return 0;
-}
-
/***********/
/* TX, DMA */
/***********/
@@ -1299,12 +1331,11 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
- struct list_head *bf_head,
- struct ath_tx_control *txctl)
+ struct ath_buf *bf, struct ath_tx_control *txctl)
{
- struct ath_buf *bf;
+ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+ struct list_head bf_head;
- bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU;
TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
@@ -1316,56 +1347,47 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
* - h/w queue depth exceeds low water mark
*/
if (!list_empty(&tid->buf_q) || tid->paused ||
- !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
+ !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
- list_move_tail(&bf->list, &tid->buf_q);
+ list_add_tail(&bf->list, &tid->buf_q);
ath_tx_queue_tid(txctl->txq, tid);
return;
}
+ INIT_LIST_HEAD(&bf_head);
+ list_add(&bf->list, &bf_head);
+
/* Add sub-frame to BAW */
- ath_tx_addto_baw(sc, tid, bf);
+ if (!fi->retries)
+ ath_tx_addto_baw(sc, tid, fi->seqno);
/* Queue to h/w without aggregation */
- bf->bf_nframes = 1;
bf->bf_lastbf = bf;
- ath_buf_set_rate(sc, bf);
- ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
+ ath_buf_set_rate(sc, bf, fi->framelen);
+ ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
}
-static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid,
- struct list_head *bf_head)
+static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+ struct list_head *bf_head)
{
+ struct ath_frame_info *fi;
struct ath_buf *bf;
bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type &= ~BUF_AMPDU;
/* update starting sequence number for subsequent ADDBA request */
- INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-
- bf->bf_nframes = 1;
- bf->bf_lastbf = bf;
- ath_buf_set_rate(sc, bf);
- ath_tx_txqaddbuf(sc, txq, bf_head);
- TX_STAT_INC(txq->axq_qnum, queued);
-}
-
-static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *bf_head)
-{
- struct ath_buf *bf;
-
- bf = list_first_entry(bf_head, struct ath_buf, list);
+ if (tid)
+ INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf;
- bf->bf_nframes = 1;
- ath_buf_set_rate(sc, bf);
+ fi = get_frame_info(bf->bf_mpdu);
+ ath_buf_set_rate(sc, bf, fi->framelen);
ath_tx_txqaddbuf(sc, txq, bf_head);
TX_STAT_INC(txq->axq_qnum, queued);
}
@@ -1393,40 +1415,52 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
return htype;
}
-static void assign_aggr_tid_seqno(struct sk_buff *skb,
- struct ath_buf *bf)
+static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
+ int framelen)
{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sta *sta = tx_info->control.sta;
+ struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
struct ieee80211_hdr *hdr;
+ struct ath_frame_info *fi = get_frame_info(skb);
struct ath_node *an;
struct ath_atx_tid *tid;
- __le16 fc;
- u8 *qc;
+ enum ath9k_key_type keytype;
+ u16 seqno = 0;
+ u8 tidno;
- if (!tx_info->control.sta)
- return;
+ keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
- an = (struct ath_node *)tx_info->control.sta->drv_priv;
hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
+ if (sta && ieee80211_is_data_qos(hdr->frame_control) &&
+ conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
- if (ieee80211_is_data_qos(fc)) {
- qc = ieee80211_get_qos_ctl(hdr);
- bf->bf_tidno = qc[0] & 0xf;
+ an = (struct ath_node *) sta->drv_priv;
+ tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+
+ /*
+ * Override seqno set by upper layer with the one
+ * in tx aggregation state.
+ */
+ tid = ATH_AN_2_TID(an, tidno);
+ seqno = tid->seq_next;
+ hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
}
- /*
- * For HT capable stations, we save tidno for later use.
- * We also override seqno set by upper layer with the one
- * in tx aggregation state.
- */
- tid = ATH_AN_2_TID(an, bf->bf_tidno);
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
- bf->bf_seqno = tid->seq_next;
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+ memset(fi, 0, sizeof(*fi));
+ if (hw_key)
+ fi->keyix = hw_key->hw_key_idx;
+ else
+ fi->keyix = ATH9K_TXKEYIX_INVALID;
+ fi->keytype = keytype;
+ fi->framelen = framelen;
+ fi->seqno = seqno;
}
-static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)
+static int setup_tx_flags(struct sk_buff *skb)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
int flags = 0;
@@ -1437,7 +1471,7 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
flags |= ATH9K_TXDESC_NOACK;
- if (use_ldpc)
+ if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
flags |= ATH9K_TXDESC_LDPC;
return flags;
@@ -1449,13 +1483,11 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)
* width - 0 for 20 MHz, 1 for 40 MHz
* half_gi - to use 4us v/s 3.6 us for symbol time
*/
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
int width, int half_gi, bool shortPreamble)
{
u32 nbits, nsymbits, duration, nsymbols;
- int streams, pktlen;
-
- pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
+ int streams;
/* find number of symbols: PLCP + data */
streams = HT_RC_2_STREAMS(rix);
@@ -1474,7 +1506,19 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
return duration;
}
-static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
+u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath9k_channel *curchan = ah->curchan;
+ if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
+ (curchan->channelFlags & CHANNEL_5GHZ) &&
+ (chainmask == 0x7) && (rate < 0x90))
+ return 0x3;
+ else
+ return chainmask;
+}
+
+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_11n_rate_series series[4];
@@ -1514,7 +1558,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
rix = rates[i].idx;
series[i].Tries = rates[i].count;
- series[i].ChSel = common->tx_chainmask;
if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) ||
(rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) {
@@ -1537,14 +1580,16 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
if (rates[i].flags & IEEE80211_TX_RC_MCS) {
/* MCS rates */
series[i].Rate = rix | 0x80;
- series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
+ series[i].ChSel = ath_txchainmask_reduction(sc,
+ common->tx_chainmask, series[i].Rate);
+ series[i].PktDuration = ath_pkt_duration(sc, rix, len,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
series[i].RateFlags |= ATH9K_RATESERIES_STBC;
continue;
}
- /* legcay rates */
+ /* legacy rates */
if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
!(rate->flags & IEEE80211_RATE_ERP_G))
phy = WLAN_RC_PHY_CCK;
@@ -1560,12 +1605,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
is_sp = false;
}
+ if (bf->bf_state.bfs_paprd)
+ series[i].ChSel = common->tx_chainmask;
+ else
+ series[i].ChSel = ath_txchainmask_reduction(sc,
+ common->tx_chainmask, series[i].Rate);
+
series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
- phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
+ phy, rate->bitrate * 100, len, rix, is_sp);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
- if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit))
+ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
flags &= ~ATH9K_TXDESC_RTSENA;
/* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
@@ -1582,67 +1633,29 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192);
}
-static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
- struct sk_buff *skb,
- struct ath_tx_control *txctl)
+static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
+ struct ath_txq *txq,
+ struct sk_buff *skb)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- int hdrlen;
- __le16 fc;
- int padpos, padsize;
- bool use_ldpc = false;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct ath_buf *bf;
+ struct ath_desc *ds;
+ int frm_type;
- tx_info->pad[0] = 0;
- switch (txctl->frame_type) {
- case ATH9K_IFT_NOT_INTERNAL:
- break;
- case ATH9K_IFT_PAUSE:
- tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE;
- /* fall through */
- case ATH9K_IFT_UNPAUSE:
- tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL;
- break;
+ bf = ath_tx_get_buffer(sc);
+ if (!bf) {
+ ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n");
+ return NULL;
}
- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- fc = hdr->frame_control;
ATH_TXBUF_RESET(bf);
bf->aphy = aphy;
- bf->bf_frmlen = skb->len + FCS_LEN;
- /* Remove the padding size from bf_frmlen, if any */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
- padsize = padpos & 3;
- if (padsize && skb->len>padpos+padsize) {
- bf->bf_frmlen -= padsize;
- }
-
- if (!txctl->paprd && conf_is_ht(&hw->conf)) {
- bf->bf_state.bf_type |= BUF_HT;
- if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
- use_ldpc = true;
- }
-
- bf->bf_state.bfs_paprd = txctl->paprd;
- if (txctl->paprd)
- bf->bf_state.bfs_paprd_timestamp = jiffies;
- bf->bf_flags = setup_tx_flags(skb, use_ldpc);
-
- bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
- if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
- bf->bf_frmlen += tx_info->control.hw_key->icv_len;
- bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
- } else {
- bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
- }
-
- if (ieee80211_is_data_qos(fc) && bf_isht(bf) &&
- (sc->sc_flags & SC_OP_TXAGGR))
- assign_aggr_tid_seqno(skb, bf);
-
+ bf->bf_flags = setup_tx_flags(skb);
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
@@ -1652,40 +1665,17 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_buf_addr = 0;
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
"dma_mapping_error() on TX\n");
- return -ENOMEM;
+ ath_tx_return_buffer(sc, bf);
+ return NULL;
}
- bf->bf_tx_aborted = false;
-
- return 0;
-}
-
-/* FIXME: tx power */
-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_control *txctl)
-{
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath_node *an = NULL;
- struct list_head bf_head;
- struct ath_desc *ds;
- struct ath_atx_tid *tid;
- struct ath_hw *ah = sc->sc_ah;
- int frm_type;
- __le16 fc;
-
frm_type = get_hw_packet_type(skb);
- fc = hdr->frame_control;
-
- INIT_LIST_HEAD(&bf_head);
- list_add_tail(&bf->list, &bf_head);
ds = bf->bf_desc;
ath9k_hw_set_desc_link(ah, ds, 0);
- ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
- bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
+ ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
+ fi->keyix, fi->keytype, bf->bf_flags);
ath9k_hw_filltxdesc(ah, ds,
skb->len, /* segment length */
@@ -1693,42 +1683,50 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
true, /* last segment */
ds, /* first descriptor */
bf->bf_buf_addr,
- txctl->txq->axq_qnum);
+ txq->axq_qnum);
- if (bf->bf_state.bfs_paprd)
- ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd);
- spin_lock_bh(&txctl->txq->axq_lock);
+ return bf;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_control *txctl)
+{
+ struct sk_buff *skb = bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct list_head bf_head;
+ struct ath_atx_tid *tid;
+ u8 tidno;
- if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
- tx_info->control.sta) {
- an = (struct ath_node *)tx_info->control.sta->drv_priv;
- tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ spin_lock_bh(&txctl->txq->axq_lock);
- if (!ieee80211_is_data_qos(fc)) {
- ath_tx_send_normal(sc, txctl->txq, &bf_head);
- goto tx_done;
- }
+ if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && txctl->an) {
+ tidno = ieee80211_get_qos_ctl(hdr)[0] &
+ IEEE80211_QOS_CTL_TID_MASK;
+ tid = ATH_AN_2_TID(txctl->an, tidno);
- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- /*
- * Try aggregation if it's a unicast data frame
- * and the destination is HT capable.
- */
- ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
- } else {
- /*
- * Send this frame as regular when ADDBA
- * exchange is neither complete nor pending.
- */
- ath_tx_send_ht_normal(sc, txctl->txq,
- tid, &bf_head);
- }
+ WARN_ON(tid->ac->txq != txctl->txq);
+ /*
+ * Try aggregation if it's a unicast data frame
+ * and the destination is HT capable.
+ */
+ ath_tx_send_ampdu(sc, tid, bf, txctl);
} else {
- ath_tx_send_normal(sc, txctl->txq, &bf_head);
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+
+ bf->bf_state.bfs_ftype = txctl->frame_type;
+ bf->bf_state.bfs_paprd = txctl->paprd;
+
+ if (bf->bf_state.bfs_paprd)
+ ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
+ bf->bf_state.bfs_paprd);
+
+ ath_tx_send_normal(sc, txctl->txq, NULL, &bf_head);
}
-tx_done:
spin_unlock_bh(&txctl->txq->axq_lock);
}
@@ -1736,66 +1734,20 @@ tx_done:
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sta *sta = info->control.sta;
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_txq *txq = txctl->txq;
struct ath_buf *bf;
- int q, r;
-
- bf = ath_tx_get_buffer(sc);
- if (!bf) {
- ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n");
- return -1;
- }
-
- r = ath_tx_setup_buffer(hw, bf, skb, txctl);
- if (unlikely(r)) {
- ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
-
- /* upon ath_tx_processq() this TX queue will be resumed, we
- * guarantee this will happen by knowing beforehand that
- * we will at least have to run TX completionon one buffer
- * on the queue */
- spin_lock_bh(&txq->axq_lock);
- if (!txq->stopped && txq->axq_depth > 1) {
- ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
- txq->stopped = 1;
- }
- spin_unlock_bh(&txq->axq_lock);
-
- ath_tx_return_buffer(sc, bf);
-
- return r;
- }
-
- q = skb_get_queue_mapping(skb);
- if (q >= 4)
- q = 0;
-
- spin_lock_bh(&txq->axq_lock);
- if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) {
- ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
- txq->stopped = 1;
- }
- spin_unlock_bh(&txq->axq_lock);
-
- ath_tx_start_dma(sc, bf, txctl);
-
- return 0;
-}
-
-void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
int padpos, padsize;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ath_tx_control txctl;
+ int frmlen = skb->len + FCS_LEN;
+ int q;
- memset(&txctl, 0, sizeof(struct ath_tx_control));
+ txctl->an = (struct ath_node *)sta->drv_priv;
+ if (info->control.hw_key)
+ frmlen += info->control.hw_key->icv_len;
/*
* As a temporary workaround, assign seq# here; this will likely need
@@ -1812,30 +1764,37 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
/* Add the padding after the header if this is not already done */
padpos = ath9k_cmn_padpos(hdr->frame_control);
padsize = padpos & 3;
- if (padsize && skb->len>padpos) {
- if (skb_headroom(skb) < padsize) {
- ath_print(common, ATH_DBG_XMIT,
- "TX CABQ padding failed\n");
- dev_kfree_skb_any(skb);
- return;
- }
+ if (padsize && skb->len > padpos) {
+ if (skb_headroom(skb) < padsize)
+ return -ENOMEM;
+
skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, padpos);
}
- txctl.txq = sc->beacon.cabq;
+ setup_frame_info(hw, skb, frmlen);
- ath_print(common, ATH_DBG_XMIT,
- "transmitting CABQ packet, skb: %p\n", skb);
+ /*
+ * At this point, the vif, hw_key and sta pointers in the tx control
+ * info are no longer valid (overwritten by the ath_frame_info data.
+ */
+
+ bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
+ if (unlikely(!bf))
+ return -ENOMEM;
- if (ath_tx_start(hw, skb, &txctl) != 0) {
- ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n");
- goto exit;
+ q = skb_get_queue_mapping(skb);
+ spin_lock_bh(&txq->axq_lock);
+ if (txq == sc->tx.txq_map[q] &&
+ ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+ ath_mac80211_stop_queue(sc, q);
+ txq->stopped = 1;
}
+ spin_unlock_bh(&txq->axq_lock);
- return;
-exit:
- dev_kfree_skb_any(skb);
+ ath_tx_start_dma(sc, bf, txctl);
+
+ return 0;
}
/*****************/
@@ -1843,7 +1802,8 @@ exit:
/*****************/
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_wiphy *aphy, int tx_flags)
+ struct ath_wiphy *aphy, int tx_flags, int ftype,
+ struct ath_txq *txq)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1886,15 +1846,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
PS_WAIT_FOR_TX_ACK));
}
- if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL))
- ath9k_tx_status(hw, skb);
+ if (unlikely(ftype))
+ ath9k_tx_status(hw, skb, ftype);
else {
q = skb_get_queue_mapping(skb);
- if (q >= 4)
- q = 0;
-
- if (--sc->tx.pending_frames[q] < 0)
- sc->tx.pending_frames[q] = 0;
+ if (txq == sc->tx.txq_map[q]) {
+ spin_lock_bh(&txq->axq_lock);
+ if (WARN_ON(--txq->pending_frames < 0))
+ txq->pending_frames = 0;
+ spin_unlock_bh(&txq->axq_lock);
+ }
ieee80211_tx_status(hw, skb);
}
@@ -1922,15 +1883,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
bf->bf_buf_addr = 0;
if (bf->bf_state.bfs_paprd) {
- if (time_after(jiffies,
- bf->bf_state.bfs_paprd_timestamp +
- msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
+ if (!sc->paprd_pending)
dev_kfree_skb_any(skb);
else
complete(&sc->paprd_complete);
} else {
- ath_debug_stat_tx(sc, txq, bf, ts);
- ath_tx_complete(sc, skb, bf->aphy, tx_flags);
+ ath_debug_stat_tx(sc, bf, ts);
+ ath_tx_complete(sc, skb, bf->aphy, tx_flags,
+ bf->bf_state.bfs_ftype, txq);
}
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
* accidentally reference it later.
@@ -1945,42 +1905,15 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
}
-static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, int txok)
-{
- u16 seq_st = 0;
- u32 ba[WME_BA_BMP_SIZE >> 5];
- int ba_index;
- int nbad = 0;
- int isaggr = 0;
-
- if (bf->bf_lastbf->bf_tx_aborted)
- return 0;
-
- isaggr = bf_isaggr(bf);
- if (isaggr) {
- seq_st = ts->ts_seqnum;
- memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
- }
-
- while (bf) {
- ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno);
- if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
- nbad++;
-
- bf = bf->bf_next;
- }
-
- return nbad;
-}
-
static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
- int nbad, int txok, bool update_rc)
+ int nframes, int nbad, int txok, bool update_rc)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hw *hw = bf->aphy->hw;
+ struct ath_softc *sc = bf->aphy->sc;
+ struct ath_hw *ah = sc->sc_ah;
u8 i, tx_rateindex;
if (txok)
@@ -1994,22 +1927,32 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
- BUG_ON(nbad > bf->bf_nframes);
+ BUG_ON(nbad > nframes);
- tx_info->status.ampdu_len = bf->bf_nframes;
- tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad;
+ tx_info->status.ampdu_len = nframes;
+ tx_info->status.ampdu_ack_len = nframes - nbad;
}
if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
(bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
- if (ieee80211_is_data(hdr->frame_control)) {
- if (ts->ts_flags &
- (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN))
- tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN;
- if ((ts->ts_status & ATH9K_TXERR_XRETRY) ||
- (ts->ts_status & ATH9K_TXERR_FIFO))
- tx_info->pad[0] |= ATH_TX_INFO_XRETRY;
- }
+ /*
+ * If an underrun error is seen assume it as an excessive
+ * retry only if max frame trigger level has been reached
+ * (2 KB for single stream, and 4 KB for dual stream).
+ * Adjust the long retry as if the frame was tried
+ * hw->max_rate_tries times to affect how rate control updates
+ * PER for the failed rate.
+ * In case of congestion on the bus penalizing this type of
+ * underruns should help hardware actually transmit new frames
+ * successfully by eventually preferring slower rates.
+ * This itself should also alleviate congestion on the bus.
+ */
+ if (ieee80211_is_data(hdr->frame_control) &&
+ (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
+ ATH9K_TX_DELIM_UNDERRUN)) &&
+ ah->tx_trig_level >= sc->sc_ah->caps.tx_triglevel_max)
+ tx_info->status.rates[tx_rateindex].count =
+ hw->max_rate_tries;
}
for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
@@ -2020,16 +1963,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
}
-static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
+static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
{
- int qnum;
-
- qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
- if (qnum == -1)
- return;
+ struct ath_txq *txq;
+ txq = sc->tx.txq_map[qnum];
spin_lock_bh(&txq->axq_lock);
- if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
+ if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
if (ath_mac80211_start_queue(sc, qnum))
txq->stopped = 0;
}
@@ -2046,6 +1986,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
struct ath_tx_status ts;
int txok;
int status;
+ int qnum;
ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
@@ -2118,15 +2059,19 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
*/
if (ts.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
+ ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true);
}
+ qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
+ ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
+ true);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
- ath_wake_mac80211_queue(sc, txq);
+ if (txq == sc->tx.txq_map[qnum])
+ ath_wake_mac80211_queue(sc, qnum);
spin_lock_bh(&txq->axq_lock);
if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2196,6 +2141,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
struct list_head bf_head;
int status;
int txok;
+ int qnum;
for (;;) {
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
@@ -2236,16 +2182,20 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
if (!bf_isampdu(bf)) {
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
- ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
+ ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true);
}
+ qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
if (bf_isampdu(bf))
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
+ ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
+ txok, true);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head,
&txs, txok, 0);
- ath_wake_mac80211_queue(sc, txq);
+ if (txq == sc->tx.txq_map[qnum])
+ ath_wake_mac80211_queue(sc, qnum);
spin_lock_bh(&txq->axq_lock);
if (!list_empty(&txq->txq_fifo_pending)) {
@@ -2377,7 +2327,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
for (acno = 0, ac = &an->ac[acno];
acno < WME_NUM_AC; acno++, ac++) {
ac->sched = false;
- ac->qnum = sc->tx.hwq_map[acno];
+ ac->txq = sc->tx.txq_map[acno];
INIT_LIST_HEAD(&ac->tid_q);
}
}
@@ -2387,17 +2337,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
struct ath_atx_ac *ac;
struct ath_atx_tid *tid;
struct ath_txq *txq;
- int i, tidno;
+ int tidno;
for (tidno = 0, tid = &an->tid[tidno];
tidno < WME_NUM_TID; tidno++, tid++) {
- i = tid->ac->qnum;
-
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
- txq = &sc->tx.txq[i];
ac = tid->ac;
+ txq = ac->txq;
spin_lock_bh(&txq->axq_lock);
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 6cf0c9ef47aa..d07ff7f2fd92 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -48,7 +48,7 @@
#include <linux/usb.h>
#ifdef CONFIG_CARL9170_LEDS
#include <linux/leds.h>
-#endif /* CONFIG_CARL170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
#ifdef CONFIG_CARL9170_WPC
#include <linux/input.h>
#endif /* CONFIG_CARL9170_WPC */
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
CARL9170_RR_WATCHDOG,
CARL9170_RR_STUCK_TX,
- CARL9170_RR_SLOW_SYSTEM,
+ CARL9170_RR_UNRESPONSIVE_DEVICE,
CARL9170_RR_COMMAND_TIMEOUT,
CARL9170_RR_TOO_MANY_PHY_ERRORS,
CARL9170_RR_LOST_RSP,
@@ -287,6 +287,7 @@ struct ar9170 {
/* reset / stuck frames/queue detection */
struct work_struct restart_work;
+ struct work_struct ping_work;
unsigned int restart_counter;
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index c21f3364bfec..cdfc94c371b4 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -41,7 +41,7 @@
int carl9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val)
{
- __le32 buf[2] = {
+ const __le32 buf[2] = {
cpu_to_le32(reg),
cpu_to_le32(val),
};
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index d552166db505..3680dfc70f46 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -97,13 +97,13 @@ struct carl9170_set_key_cmd {
__le16 type;
u8 macAddr[6];
u32 key[4];
-} __packed;
+} __packed __aligned(4);
#define CARL9170_SET_KEY_CMD_SIZE 28
struct carl9170_disable_key_cmd {
__le16 user;
__le16 padding;
-} __packed;
+} __packed __aligned(4);
#define CARL9170_DISABLE_KEY_CMD_SIZE 4
struct carl9170_u32_list {
@@ -206,7 +206,7 @@ struct carl9170_cmd {
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
-} __packed;
+} __packed __aligned(4);
#define CARL9170_TX_STATUS_QUEUE 3
#define CARL9170_TX_STATUS_QUEUE_S 0
@@ -216,6 +216,7 @@ struct carl9170_cmd {
#define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S)
#define CARL9170_TX_STATUS_SUCCESS 0x80
+#ifdef __CARL9170FW__
/*
* NOTE:
* Both structs [carl9170_tx_status and _carl9170_tx_status]
@@ -232,6 +233,8 @@ struct carl9170_tx_status {
u8 tries:3;
u8 success:1;
} __packed;
+#endif /* __CARL9170FW__ */
+
struct _carl9170_tx_status {
/*
* This version should be immune to all alignment bugs.
@@ -272,13 +275,15 @@ struct carl9170_rsp {
struct carl9170_rf_init_result rf_init_res;
struct carl9170_u32_list rreg_res;
struct carl9170_u32_list echo;
+#ifdef __CARL9170FW__
struct carl9170_tx_status tx_status[0];
+#endif /* __CARL9170FW__ */
struct _carl9170_tx_status _tx_status[0];
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
-} __packed;
+} __packed __aligned(4);
#endif /* __CARL9170_SHARED_FWCMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index 2f471b3f05af..e85df6edfed3 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -712,7 +712,8 @@ struct ar9170_stream {
__le16 tag;
u8 payload[0];
-};
+} __packed __aligned(4);
+#define AR9170_STREAM_LEN 4
#define AR9170_MAX_ACKTABLE_ENTRIES 8
#define AR9170_MAX_VIRTUAL_MAC 7
@@ -736,4 +737,8 @@ struct ar9170_stream {
#define MOD_VAL(reg, value, newvalue) \
(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define GET_VAL(reg, value) \
+ (((value) & reg) >> reg##_S)
+
#endif /* __CARL9170_SHARED_HW_H */
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index 2305bc27151c..385cf508479b 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar)
carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
/* Aggregation MAX number and timeout */
- carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
- carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
+ carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
AR9170_MAC_FTF_DEFAULTS);
@@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
{
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
struct carl9170_vif_info *cvif;
+ struct ieee80211_tx_info *txinfo;
__le32 *data, *old = NULL;
u32 word, off, addr, len;
int i = 0, err = 0;
@@ -487,7 +488,13 @@ found:
if (!skb) {
err = -ENOMEM;
- goto out_unlock;
+ goto err_free;
+ }
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
+ err = -EINVAL;
+ goto err_free;
}
spin_lock_bh(&ar->beacon_lock);
@@ -504,11 +511,8 @@ found:
wiphy_err(ar->hw->wiphy, "beacon does not "
"fit into device memory!\n");
}
-
- spin_unlock_bh(&ar->beacon_lock);
- dev_kfree_skb_any(skb);
err = -EINVAL;
- goto out_unlock;
+ goto err_unlock;
}
if (len > AR9170_MAC_BCN_LENGTH_MAX) {
@@ -518,22 +522,22 @@ found:
AR9170_MAC_BCN_LENGTH_MAX, len);
}
- spin_unlock_bh(&ar->beacon_lock);
- dev_kfree_skb_any(skb);
err = -EMSGSIZE;
- goto out_unlock;
+ goto err_unlock;
}
- carl9170_async_regwrite_begin(ar);
+ i = txinfo->control.rates[0].idx;
+ if (txinfo->band != IEEE80211_BAND_2GHZ)
+ i += 4;
- /* XXX: use skb->cb info */
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
- ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
- } else {
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
- ((skb->len + FCS_LEN) << 16) + 0x001b);
- }
+ word = __carl9170_ratetable[i].hw_value & 0xf;
+ if (i < 4)
+ word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+ else
+ word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+
+ carl9170_async_regwrite_begin(ar);
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
/*
@@ -557,7 +561,7 @@ found:
cvif->beacon = skb;
spin_unlock_bh(&ar->beacon_lock);
if (err)
- goto out_unlock;
+ goto err_free;
if (submit) {
err = carl9170_bcn_ctrl(ar, cvif->id,
@@ -565,10 +569,18 @@ found:
addr, skb->len + FCS_LEN);
if (err)
- goto out_unlock;
+ goto err_free;
}
out_unlock:
rcu_read_unlock();
+ return 0;
+
+err_unlock:
+ spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+ rcu_read_unlock();
+ dev_kfree_skb_any(skb);
return err;
}
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index dc7b30b170d0..870df8c42622 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar)
cancel_delayed_work_sync(&ar->led_work);
#endif /* CONFIG_CARL9170_LEDS */
cancel_work_sync(&ar->ps_work);
+ cancel_work_sync(&ar->ping_work);
cancel_work_sync(&ar->ampdu_work);
}
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
*/
}
+static void carl9170_ping_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
+ int err;
+
+ if (!IS_STARTED(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_echo_test(ar, 0xdeadbeef);
+ if (err)
+ carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
+ mutex_unlock(&ar->mutex);
+}
+
static int carl9170_init_interface(struct ar9170 *ar,
struct ieee80211_vif *vif)
{
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
skb_queue_head_init(&ar->tx_pending[i]);
}
INIT_WORK(&ar->ps_work, carl9170_ps_work);
+ INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
@@ -1829,7 +1846,7 @@ int carl9170_register(struct ar9170 *ar)
err = carl9170_led_register(ar);
if (err)
goto err_unreg;
-#endif /* CONFIG_CAR9L170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
#ifdef CONFIG_CARL9170_WPC
err = carl9170_register_wps_button(ar);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 89deca37a988..82bc81c4c930 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1554,15 +1554,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
return carl9170_regwrite_result();
}
-/* TODO: replace this with sign_extend32(noise, 8) */
-static int carl9170_calc_noise_dbm(u32 raw_noise)
-{
- if (raw_noise & 0x100)
- return ~0x1ff | raw_noise;
- else
- return raw_noise;
-}
-
int carl9170_get_noisefloor(struct ar9170 *ar)
{
static const u32 phy_regs[] = {
@@ -1578,11 +1569,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
return err;
for (i = 0; i < 2; i++) {
- ar->noise[i] = carl9170_calc_noise_dbm(
- (phy_res[i] >> 19) & 0x1ff);
+ ar->noise[i] = sign_extend32(GET_VAL(
+ AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8);
- ar->noise[i + 2] = carl9170_calc_noise_dbm(
- (phy_res[i + 2] >> 23) & 0x1ff);
+ ar->noise[i + 2] = sign_extend32(GET_VAL(
+ AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
}
return 0;
diff --git a/drivers/net/wireless/ath/carl9170/phy.h b/drivers/net/wireless/ath/carl9170/phy.h
index 02c34eb4ebde..024fb42bc787 100644
--- a/drivers/net/wireless/ath/carl9170/phy.h
+++ b/drivers/net/wireless/ath/carl9170/phy.h
@@ -139,8 +139,8 @@
#define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
#define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064)
-#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CCA_MINCCA_PWR_S 19
+#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CCA_MIN_PWR_S 19
#define AR9170_PHY_CCA_THRESH62 0x0007f000
#define AR9170_PHY_CCA_THRESH62_S 12
@@ -338,8 +338,8 @@
#define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9
#define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000
#define AR9170_PHY_EXT_CCA_THRESH62_S 16
-#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0)
#define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f
@@ -546,19 +546,19 @@
#define AR9170_PHY_FORCE_XPA_CFG_S 0
#define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064)
-#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CH1_MINCCA_PWR_S 19
+#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064)
-#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000
-#define AR9170_PHY_CH2_MINCCA_PWR_S 19
+#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000
+#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19
#define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc)
-#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23
#define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc)
-#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
-#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
+#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000
+#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23
#endif /* __CARL9170_SHARED_PHY_H */
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 7e6506a77bbb..6cc58e052d10 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -242,9 +242,11 @@ static void carl9170_tx_release(struct kref *ref)
ar->tx_ampdu_schedule = true;
if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
- txinfo->status.ampdu_len = txinfo->pad[0];
- txinfo->status.ampdu_ack_len = txinfo->pad[1];
- txinfo->pad[0] = txinfo->pad[1] = 0;
+ struct _carl9170_tx_superframe *super;
+
+ super = (void *)skb->data;
+ txinfo->status.ampdu_len = super->s.rix;
+ txinfo->status.ampdu_ack_len = super->s.cnt;
} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
/*
* drop redundant tx_status reports:
@@ -337,7 +339,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
u8 tid;
if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
- txinfo->flags & IEEE80211_TX_CTL_INJECTED)
+ txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
+ (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
return;
tx_info = IEEE80211_SKB_CB(skb);
@@ -389,8 +392,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
sta_info->stats[tid].ampdu_ack_len++;
if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
- txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
- txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
+ super->s.rix = sta_info->stats[tid].ampdu_len;
+ super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
sta_info->stats[tid].clear = true;
}
@@ -524,6 +527,59 @@ next:
}
}
+static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
+{
+ struct carl9170_sta_tid *iter;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+ struct carl9170_tx_info *arinfo;
+ struct _carl9170_tx_superframe *super;
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
+ struct ieee80211_hdr *hdr;
+ unsigned int vif_id;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+ if (iter->state < CARL9170_TID_STATE_IDLE)
+ continue;
+
+ spin_lock_bh(&iter->lock);
+ skb = skb_peek(&iter->queue);
+ if (!skb)
+ goto unlock;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ arinfo = (void *)txinfo->rate_driver_data;
+ if (time_is_after_jiffies(arinfo->timeout +
+ msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
+ goto unlock;
+
+ super = (void *) skb->data;
+ hdr = (void *) super->frame_data;
+
+ vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+ CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+ if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+ goto unlock;
+
+ vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+ if (WARN_ON(!vif))
+ goto unlock;
+
+ sta = ieee80211_find_sta(vif, hdr->addr1);
+ if (WARN_ON(!sta))
+ goto unlock;
+
+ ieee80211_stop_tx_ba_session(sta, iter->tid);
+unlock:
+ spin_unlock_bh(&iter->lock);
+
+ }
+ rcu_read_unlock();
+}
+
void carl9170_tx_janitor(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170,
@@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_struct *work)
ar->tx_janitor_last_run = jiffies;
carl9170_check_queue_stop_timeout(ar);
+ carl9170_tx_ampdu_timeout(ar);
if (!atomic_read(&ar->tx_total_queued))
return;
@@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
if (unlikely(!sta || !cvif))
goto err_out;
- factor = min_t(unsigned int, 1u,
- info->control.sta->ht_cap.ampdu_factor);
-
- density = info->control.sta->ht_cap.ampdu_density;
+ factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor);
+ density = sta->ht_cap.ampdu_density;
if (density) {
/*
@@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *ar)
static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
struct ieee80211_sta *sta, struct sk_buff *skb)
{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
struct carl9170_sta_info *sta_info;
struct carl9170_sta_tid *agg;
struct sk_buff *iter;
@@ -1274,6 +1330,7 @@ err_unlock:
err_unlock_rcu:
rcu_read_unlock();
+ super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
carl9170_tx_status(ar, skb, false);
ar->tx_dropped++;
return false;
@@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
*/
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- if (WARN_ON_ONCE(!sta))
- goto err_free;
-
run = carl9170_tx_ampdu_queue(ar, sta, skb);
if (run)
carl9170_tx_ampdu(ar);
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 7504ed14c725..2d947a30d29e 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -160,8 +160,7 @@ err_acc:
static void carl9170_usb_tx_data_complete(struct urb *urb)
{
- struct ar9170 *ar = (struct ar9170 *)
- usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+ struct ar9170 *ar = usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
if (WARN_ON_ONCE(!ar)) {
dev_kfree_skb_irq(urb->context);
@@ -433,7 +432,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
* device.
*/
- carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+ ieee80211_queue_work(ar->hw, &ar->ping_work);
}
} else {
/*
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index ff53f078a0b5..ee0f84f2a2f6 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 9
-#define CARL9170FW_VERSION_DAY 28
-#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#define CARL9170FW_VERSION_MONTH 10
+#define CARL9170FW_VERSION_DAY 29
+#define CARL9170FW_VERSION_GIT "1.9.0"
#endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c
index dacfb234f491..a9600ba8ceaa 100644
--- a/drivers/net/wireless/ath/debug.c
+++ b/drivers/net/wireless/ath/debug.c
@@ -19,14 +19,19 @@
void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (likely(!(common->debug_mask & dbg_mask)))
return;
va_start(args, fmt);
- printk(KERN_DEBUG "ath: ");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_DEBUG "ath: %pV", &vaf);
+
va_end(args);
}
EXPORT_SYMBOL(ath_print);
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h
index 64e4af2c2887..f207007ee391 100644
--- a/drivers/net/wireless/ath/debug.h
+++ b/drivers/net/wireless/ath/debug.h
@@ -70,11 +70,13 @@ enum ATH_DEBUG {
#ifdef CONFIG_ATH_DEBUG
void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)));
+#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
#else
static inline void __attribute__ ((format (printf, 3, 4)))
ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
{
}
+#define ATH_DBG_WARN(foo, arg)
#endif /* CONFIG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index bd21a4d82085..62e3dac8f92a 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -67,7 +67,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
}
EXPORT_SYMBOL(ath_hw_keyreset);
-bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
+static bool ath_hw_keysetmac(struct ath_common *common,
+ u16 entry, const u8 *mac)
{
u32 macHi, macLo;
u32 unicast_flag = AR_KEYTABLE_VALID;
@@ -107,9 +108,9 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
return true;
}
-bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
- const struct ath_keyval *k,
- const u8 *mac)
+static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
+ const struct ath_keyval *k,
+ const u8 *mac)
{
void *ah = common->ah;
u32 key0, key1, key2, key3, key4;