mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
@@ -17,8 +17,7 @@
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2007</year>
|
||||
<year>2008</year>
|
||||
<year>2007-2009</year>
|
||||
<holder>Johannes Berg</holder>
|
||||
</copyright>
|
||||
|
||||
@@ -165,8 +164,8 @@ usage should require reading the full document.
|
||||
!Pinclude/net/mac80211.h Frame format
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>Alignment issues</title>
|
||||
<para>TBD</para>
|
||||
<title>Packet alignment</title>
|
||||
!Pnet/mac80211/rx.c Packet alignment
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>Calling into mac80211 from interrupts</title>
|
||||
@@ -223,6 +222,11 @@ usage should require reading the full document.
|
||||
!Finclude/net/mac80211.h ieee80211_key_flags
|
||||
</chapter>
|
||||
|
||||
<chapter id="powersave">
|
||||
<title>Powersave support</title>
|
||||
!Pinclude/net/mac80211.h Powersave support
|
||||
</chapter>
|
||||
|
||||
<chapter id="qos">
|
||||
<title>Multiple queues and QoS support</title>
|
||||
<para>TBD</para>
|
||||
|
||||
@@ -229,7 +229,9 @@ Who: Jan Engelhardt <jengelh@computergmbh.de>
|
||||
---------------------------
|
||||
|
||||
What: b43 support for firmware revision < 410
|
||||
When: July 2008
|
||||
When: The schedule was July 2008, but it was decided that we are going to keep the
|
||||
code as long as there are no major maintanance headaches.
|
||||
So it _could_ be removed _any_ time now, if it conflicts with something new.
|
||||
Why: The support code for the old firmware hurts code readability/maintainability
|
||||
and slightly hurts runtime performance. Bugfixes for the old firmware
|
||||
are not provided by Broadcom anymore.
|
||||
|
||||
@@ -151,6 +151,12 @@ config LIBERTAS_SDIO
|
||||
---help---
|
||||
A driver for Marvell Libertas 8385 and 8686 SDIO devices.
|
||||
|
||||
config LIBERTAS_SPI
|
||||
tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
|
||||
depends on LIBERTAS && SPI && GENERIC_GPIO
|
||||
---help---
|
||||
A driver for Marvell Libertas 8686 SPI devices.
|
||||
|
||||
config LIBERTAS_DEBUG
|
||||
bool "Enable full debugging output in the Libertas module."
|
||||
depends on LIBERTAS
|
||||
@@ -188,127 +194,6 @@ config AIRO
|
||||
|
||||
The driver can be compiled as a module and will be named "airo".
|
||||
|
||||
config HERMES
|
||||
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
|
||||
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
|
||||
select WIRELESS_EXT
|
||||
select FW_LOADER
|
||||
select CRYPTO
|
||||
select CRYPTO_MICHAEL_MIC
|
||||
---help---
|
||||
A driver for 802.11b wireless cards based on the "Hermes" or
|
||||
Intersil HFA384x (Prism 2) MAC controller. This includes the vast
|
||||
majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
|
||||
- except for the Cisco/Aironet cards. Cards supported include the
|
||||
Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
|
||||
Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
|
||||
IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
|
||||
MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
|
||||
IPW2011, and Symbol Spectrum24 High Rate amongst others.
|
||||
|
||||
This option includes the guts of the driver, but in order to
|
||||
actually use a card you will also need to enable support for PCMCIA
|
||||
Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
|
||||
|
||||
You will also very likely also need the Wireless Tools in order to
|
||||
configure your card and that /etc/pcmcia/wireless.opts works :
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
|
||||
|
||||
config HERMES_CACHE_FW_ON_INIT
|
||||
bool "Cache Hermes firmware on driver initialisation"
|
||||
depends on HERMES
|
||||
default y
|
||||
---help---
|
||||
Say Y to cache any firmware required by the Hermes drivers
|
||||
on startup. The firmware will remain cached until the
|
||||
driver is unloaded. The cache uses 64K of RAM.
|
||||
|
||||
Otherwise load the firmware from userspace as required. In
|
||||
this case the driver should be unloaded and restarted
|
||||
whenever the firmware is changed.
|
||||
|
||||
If you are not sure, say Y.
|
||||
|
||||
config APPLE_AIRPORT
|
||||
tristate "Apple Airport support (built-in)"
|
||||
depends on PPC_PMAC && HERMES
|
||||
help
|
||||
Say Y here to support the Airport 802.11b wireless Ethernet hardware
|
||||
built into the Macintosh iBook and other recent PowerPC-based
|
||||
Macintosh machines. This is essentially a Lucent Orinoco card with
|
||||
a non-standard interface.
|
||||
|
||||
This driver does not support the Airport Extreme (802.11b/g). Use
|
||||
the BCM43xx driver for Airport Extreme cards.
|
||||
|
||||
config PLX_HERMES
|
||||
tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
|
||||
depends on PCI && HERMES
|
||||
help
|
||||
Enable support for PCMCIA cards supported by the "Hermes" (aka
|
||||
orinoco) driver when used in PLX9052 based PCI adaptors. These
|
||||
adaptors are not a full PCMCIA controller but act as a more limited
|
||||
PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
|
||||
802.11b PCMCIA cards can be used in desktop machines. The Netgear
|
||||
MA301 is such an adaptor.
|
||||
|
||||
config TMD_HERMES
|
||||
tristate "Hermes in TMD7160 based PCI adaptor support"
|
||||
depends on PCI && HERMES
|
||||
help
|
||||
Enable support for PCMCIA cards supported by the "Hermes" (aka
|
||||
orinoco) driver when used in TMD7160 based PCI adaptors. These
|
||||
adaptors are not a full PCMCIA controller but act as a more limited
|
||||
PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
|
||||
802.11b PCMCIA cards can be used in desktop machines.
|
||||
|
||||
config NORTEL_HERMES
|
||||
tristate "Nortel emobility PCI adaptor support"
|
||||
depends on PCI && HERMES
|
||||
help
|
||||
Enable support for PCMCIA cards supported by the "Hermes" (aka
|
||||
orinoco) driver when used in Nortel emobility PCI adaptors. These
|
||||
adaptors are not full PCMCIA controllers, but act as a more limited
|
||||
PCI <-> PCMCIA bridge.
|
||||
|
||||
config PCI_HERMES
|
||||
tristate "Prism 2.5 PCI 802.11b adaptor support"
|
||||
depends on PCI && HERMES
|
||||
help
|
||||
Enable support for PCI and mini-PCI 802.11b wireless NICs based on
|
||||
the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
|
||||
PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
|
||||
common. Some of the built-in wireless adaptors in laptops are of
|
||||
this variety.
|
||||
|
||||
config PCMCIA_HERMES
|
||||
tristate "Hermes PCMCIA card support"
|
||||
depends on PCMCIA && HERMES
|
||||
---help---
|
||||
A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
|
||||
as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
|
||||
EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
|
||||
others). It should also be usable on various Prism II based cards
|
||||
such as the Linksys, D-Link and Farallon Skyline. It should also
|
||||
work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
|
||||
|
||||
You will very likely need the Wireless Tools in order to
|
||||
configure your card and that /etc/pcmcia/wireless.opts works:
|
||||
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
|
||||
|
||||
config PCMCIA_SPECTRUM
|
||||
tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
|
||||
depends on PCMCIA && HERMES
|
||||
---help---
|
||||
|
||||
This is a driver for 802.11b cards using RAM-loadable Symbol
|
||||
firmware, such as Symbol Wireless Networker LA4100, CompactFlash
|
||||
cards by Socket Communications and Intel PRO/Wireless 2011B.
|
||||
|
||||
This driver requires firmware download on startup. Utilities
|
||||
for downloading Symbol firmware are available at
|
||||
<http://sourceforge.net/projects/orinoco/>
|
||||
|
||||
config ATMEL
|
||||
tristate "Atmel at76c50x chipset 802.11b support"
|
||||
depends on (PCI || PCMCIA) && WLAN_80211
|
||||
@@ -590,5 +475,6 @@ source "drivers/net/wireless/b43/Kconfig"
|
||||
source "drivers/net/wireless/b43legacy/Kconfig"
|
||||
source "drivers/net/wireless/zd1211rw/Kconfig"
|
||||
source "drivers/net/wireless/rt2x00/Kconfig"
|
||||
source "drivers/net/wireless/orinoco/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1206,6 +1206,7 @@ extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
|
||||
/* Beacon control functions */
|
||||
extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
|
||||
extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
|
||||
extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
|
||||
#if 0
|
||||
|
||||
@@ -232,13 +232,14 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
int mc_count, struct dev_mc_list *mclist);
|
||||
static int ath5k_set_key(struct ieee80211_hw *hw,
|
||||
enum set_key_cmd cmd,
|
||||
const u8 *local_addr, const u8 *addr,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
static int ath5k_get_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_low_level_stats *stats);
|
||||
static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_queue_stats *stats);
|
||||
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
||||
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
|
||||
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
||||
static int ath5k_beacon_update(struct ath5k_softc *sc,
|
||||
struct sk_buff *skb);
|
||||
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = {
|
||||
.conf_tx = NULL,
|
||||
.get_tx_stats = ath5k_get_tx_stats,
|
||||
.get_tsf = ath5k_get_tsf,
|
||||
.set_tsf = ath5k_set_tsf,
|
||||
.reset_tsf = ath5k_reset_tsf,
|
||||
.bss_info_changed = ath5k_bss_info_changed,
|
||||
};
|
||||
@@ -347,9 +349,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
|
||||
}
|
||||
|
||||
/* Interrupt handling */
|
||||
static int ath5k_init(struct ath5k_softc *sc, bool is_resume);
|
||||
static int ath5k_init(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_locked(struct ath5k_softc *sc);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
|
||||
static int ath5k_stop_hw(struct ath5k_softc *sc);
|
||||
static irqreturn_t ath5k_intr(int irq, void *dev_id);
|
||||
static void ath5k_tasklet_reset(unsigned long data);
|
||||
|
||||
@@ -653,8 +655,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
|
||||
ath5k_led_off(sc);
|
||||
|
||||
ath5k_stop_hw(sc, true);
|
||||
|
||||
free_irq(pdev->irq, sc);
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@@ -689,14 +689,9 @@ ath5k_pci_resume(struct pci_dev *pdev)
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
err = ath5k_init(sc, true);
|
||||
if (err)
|
||||
goto err_irq;
|
||||
ath5k_led_enable(sc);
|
||||
|
||||
return 0;
|
||||
err_irq:
|
||||
free_irq(pdev->irq, sc);
|
||||
|
||||
err_no_irq:
|
||||
pci_disable_device(pdev);
|
||||
return err;
|
||||
@@ -1098,6 +1093,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
|
||||
* Buffers setup *
|
||||
\***************/
|
||||
|
||||
static
|
||||
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
unsigned int off;
|
||||
|
||||
/*
|
||||
* Allocate buffer with headroom_needed space for the
|
||||
* fake physical layer header at the start.
|
||||
*/
|
||||
skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
|
||||
|
||||
if (!skb) {
|
||||
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
||||
sc->rxbufsize + sc->cachelsz - 1);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Cache-line-align. This is important (for the
|
||||
* 5210 at least) as not doing so causes bogus data
|
||||
* in rx'd frames.
|
||||
*/
|
||||
off = ((unsigned long)skb->data) % sc->cachelsz;
|
||||
if (off != 0)
|
||||
skb_reserve(skb, sc->cachelsz - off);
|
||||
|
||||
*skb_addr = pci_map_single(sc->pdev,
|
||||
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
|
||||
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
|
||||
dev_kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
{
|
||||
@@ -1105,37 +1136,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
struct sk_buff *skb = bf->skb;
|
||||
struct ath5k_desc *ds;
|
||||
|
||||
if (likely(skb == NULL)) {
|
||||
unsigned int off;
|
||||
|
||||
/*
|
||||
* Allocate buffer with headroom_needed space for the
|
||||
* fake physical layer header at the start.
|
||||
*/
|
||||
skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
|
||||
if (unlikely(skb == NULL)) {
|
||||
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
|
||||
sc->rxbufsize + sc->cachelsz - 1);
|
||||
if (!skb) {
|
||||
skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
/*
|
||||
* Cache-line-align. This is important (for the
|
||||
* 5210 at least) as not doing so causes bogus data
|
||||
* in rx'd frames.
|
||||
*/
|
||||
off = ((unsigned long)skb->data) % sc->cachelsz;
|
||||
if (off != 0)
|
||||
skb_reserve(skb, sc->cachelsz - off);
|
||||
|
||||
bf->skb = skb;
|
||||
bf->skbaddr = pci_map_single(sc->pdev,
|
||||
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
|
||||
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
|
||||
dev_kfree_skb(skb);
|
||||
bf->skb = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1178,6 +1183,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
struct ieee80211_rate *rate;
|
||||
unsigned int mrr_rate[3], mrr_tries[3];
|
||||
int i, ret;
|
||||
u16 hw_rate;
|
||||
u16 cts_rate = 0;
|
||||
u16 duration = 0;
|
||||
u8 rc_flags;
|
||||
|
||||
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
|
||||
|
||||
@@ -1185,11 +1194,30 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
rate = ieee80211_get_tx_rate(sc->hw, info);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
flags |= AR5K_TXDESC_NOACK;
|
||||
|
||||
rc_flags = info->control.rates[0].flags;
|
||||
hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ?
|
||||
rate->hw_value_short : rate->hw_value;
|
||||
|
||||
pktlen = skb->len;
|
||||
|
||||
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
flags |= AR5K_TXDESC_RTSENA;
|
||||
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
|
||||
duration = le16_to_cpu(ieee80211_rts_duration(sc->hw,
|
||||
sc->vif, pktlen, info));
|
||||
}
|
||||
if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
flags |= AR5K_TXDESC_CTSENA;
|
||||
cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value;
|
||||
duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw,
|
||||
sc->vif, pktlen, info));
|
||||
}
|
||||
|
||||
if (info->control.hw_key) {
|
||||
keyidx = info->control.hw_key->hw_key_idx;
|
||||
pktlen += info->control.hw_key->icv_len;
|
||||
@@ -1197,8 +1225,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
|
||||
(sc->power_level * 2),
|
||||
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
|
||||
info->control.rates[0].count, keyidx, 0, flags, 0, 0);
|
||||
hw_rate,
|
||||
info->control.rates[0].count, keyidx, 0, flags,
|
||||
cts_rate, duration);
|
||||
if (ret)
|
||||
goto err_unmap;
|
||||
|
||||
@@ -1664,7 +1693,8 @@ ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
struct ieee80211_rx_status rxs = {};
|
||||
struct ath5k_rx_status rs = {};
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb, *next_skb;
|
||||
dma_addr_t next_skb_addr;
|
||||
struct ath5k_softc *sc = (void *)data;
|
||||
struct ath5k_buf *bf, *bf_last;
|
||||
struct ath5k_desc *ds;
|
||||
@@ -1749,10 +1779,17 @@ ath5k_tasklet_rx(unsigned long data)
|
||||
goto next;
|
||||
}
|
||||
accept:
|
||||
next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
|
||||
|
||||
/*
|
||||
* If we can't replace bf->skb with a new skb under memory
|
||||
* pressure, just skip this packet
|
||||
*/
|
||||
if (!next_skb)
|
||||
goto next;
|
||||
|
||||
pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
bf->skb = NULL;
|
||||
|
||||
skb_put(skb, rs.rs_datalen);
|
||||
|
||||
/* The MAC header is padded to have 32-bit boundary if the
|
||||
@@ -1825,6 +1862,9 @@ accept:
|
||||
ath5k_check_ibss_tsf(sc, skb, &rxs);
|
||||
|
||||
__ieee80211_rx(sc->hw, skb, &rxs);
|
||||
|
||||
bf->skb = next_skb;
|
||||
bf->skbaddr = next_skb_addr;
|
||||
next:
|
||||
list_move_tail(&bf->list, &sc->rxbuf);
|
||||
} while (ath5k_rxbuf_setup(sc, bf) == 0);
|
||||
@@ -2207,18 +2247,13 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
||||
\********************/
|
||||
|
||||
static int
|
||||
ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
ath5k_init(struct ath5k_softc *sc)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
|
||||
if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
|
||||
goto out_ok;
|
||||
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
|
||||
|
||||
/*
|
||||
@@ -2250,15 +2285,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
|
||||
ath5k_hw_reset_key(ah, i);
|
||||
|
||||
__set_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
/* Set ack to be sent at low bit-rates */
|
||||
ath5k_hw_set_ack_bitrate_high(ah, false);
|
||||
|
||||
mod_timer(&sc->calib_tim, round_jiffies(jiffies +
|
||||
msecs_to_jiffies(ath5k_calinterval * 1000)));
|
||||
|
||||
out_ok:
|
||||
ret = 0;
|
||||
done:
|
||||
mmiowb();
|
||||
@@ -2313,7 +2345,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
|
||||
* stop is preempted).
|
||||
*/
|
||||
static int
|
||||
ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
|
||||
ath5k_stop_hw(struct ath5k_softc *sc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -2344,8 +2376,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
|
||||
}
|
||||
}
|
||||
ath5k_txbuf_free(sc, sc->bbuf);
|
||||
if (!is_suspend)
|
||||
__clear_bit(ATH_STAT_STARTED, sc->status);
|
||||
|
||||
mmiowb();
|
||||
mutex_unlock(&sc->lock);
|
||||
@@ -2598,6 +2628,17 @@ ath5k_init_leds(struct ath5k_softc *sc)
|
||||
sc->led_pin = 1;
|
||||
sc->led_on = 1; /* active high */
|
||||
}
|
||||
/*
|
||||
* Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and
|
||||
* in emachines notebooks with AMBIT subsystem.
|
||||
*/
|
||||
if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN ||
|
||||
pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) {
|
||||
__set_bit(ATH_STAT_LEDSOFT, sc->status);
|
||||
sc->led_pin = 3;
|
||||
sc->led_on = 0; /* active low */
|
||||
}
|
||||
|
||||
if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
|
||||
goto out;
|
||||
|
||||
@@ -2745,12 +2786,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
|
||||
|
||||
static int ath5k_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
return ath5k_init(hw->priv, false);
|
||||
return ath5k_init(hw->priv);
|
||||
}
|
||||
|
||||
static void ath5k_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
ath5k_stop_hw(hw->priv, false);
|
||||
ath5k_stop_hw(hw->priv);
|
||||
}
|
||||
|
||||
static int ath5k_add_interface(struct ieee80211_hw *hw,
|
||||
@@ -2999,8 +3040,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
static int
|
||||
ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
const u8 *local_addr, const u8 *addr,
|
||||
struct ieee80211_key_conf *key)
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
int ret = 0;
|
||||
@@ -3023,7 +3064,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
|
||||
ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
|
||||
sta ? sta->addr : NULL);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "can't set the key\n");
|
||||
goto unlock;
|
||||
@@ -3082,6 +3124,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
|
||||
return ath5k_hw_get_tsf64(sc->ah);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
|
||||
ath5k_hw_set_tsf64(sc->ah, tsf);
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_reset_tsf(struct ieee80211_hw *hw)
|
||||
{
|
||||
|
||||
@@ -148,8 +148,7 @@ struct ath5k_softc {
|
||||
u8 bssidmask[ETH_ALEN];
|
||||
|
||||
unsigned int led_pin, /* GPIO pin for driving LED */
|
||||
led_on, /* pin setting for LED on */
|
||||
led_off; /* off time for current blink */
|
||||
led_on; /* pin setting for LED on */
|
||||
|
||||
struct tasklet_struct restq; /* reset tasklet */
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
||||
/* Enable 802.11b if a 2GHz capable radio (2111/5112) is
|
||||
* connected */
|
||||
if (AR5K_EEPROM_HDR_11B(ee_header) ||
|
||||
AR5K_EEPROM_HDR_11G(ee_header)) {
|
||||
(AR5K_EEPROM_HDR_11G(ee_header) &&
|
||||
ah->ah_version != AR5K_AR5211)) {
|
||||
/* 2312 */
|
||||
ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
|
||||
ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
|
||||
@@ -94,7 +95,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
|
||||
__set_bit(AR5K_MODE_11B,
|
||||
ah->ah_capabilities.cap_mode);
|
||||
|
||||
if (AR5K_EEPROM_HDR_11G(ee_header))
|
||||
if (AR5K_EEPROM_HDR_11G(ee_header) &&
|
||||
ah->ah_version != AR5K_AR5211)
|
||||
__set_bit(AR5K_MODE_11G,
|
||||
ah->ah_capabilities.cap_mode);
|
||||
}
|
||||
|
||||
@@ -193,43 +193,6 @@ static const struct file_operations fops_registers = {
|
||||
};
|
||||
|
||||
|
||||
/* debugfs: TSF */
|
||||
|
||||
static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "0x%016llx\n",
|
||||
(unsigned long long)ath5k_hw_get_tsf64(sc->ah));
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
|
||||
}
|
||||
|
||||
static ssize_t write_file_tsf(struct file *file,
|
||||
const char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath5k_softc *sc = file->private_data;
|
||||
char buf[20];
|
||||
|
||||
if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
|
||||
return -EFAULT;
|
||||
|
||||
if (strncmp(buf, "reset", 5) == 0) {
|
||||
ath5k_hw_reset_tsf(sc->ah);
|
||||
printk(KERN_INFO "debugfs reset TSF\n");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_tsf = {
|
||||
.read = read_file_tsf,
|
||||
.write = write_file_tsf,
|
||||
.open = ath5k_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
/* debugfs: beacons */
|
||||
|
||||
static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
|
||||
@@ -423,9 +386,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc)
|
||||
sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO,
|
||||
sc->debug.debugfs_phydir, sc, &fops_registers);
|
||||
|
||||
sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO,
|
||||
sc->debug.debugfs_phydir, sc, &fops_tsf);
|
||||
|
||||
sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO,
|
||||
sc->debug.debugfs_phydir, sc, &fops_beacon);
|
||||
|
||||
@@ -444,7 +404,6 @@ ath5k_debug_finish_device(struct ath5k_softc *sc)
|
||||
{
|
||||
debugfs_remove(sc->debug.debugfs_debug);
|
||||
debugfs_remove(sc->debug.debugfs_registers);
|
||||
debugfs_remove(sc->debug.debugfs_tsf);
|
||||
debugfs_remove(sc->debug.debugfs_beacon);
|
||||
debugfs_remove(sc->debug.debugfs_reset);
|
||||
debugfs_remove(sc->debug.debugfs_phydir);
|
||||
|
||||
@@ -72,7 +72,6 @@ struct ath5k_dbg_info {
|
||||
struct dentry *debugfs_phydir;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_registers;
|
||||
struct dentry *debugfs_tsf;
|
||||
struct dentry *debugfs_beacon;
|
||||
struct dentry *debugfs_reset;
|
||||
};
|
||||
|
||||
@@ -137,6 +137,18 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
|
||||
if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
|
||||
|
||||
/* XXX: Don't know which versions include these two */
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
|
||||
|
||||
if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
|
||||
|
||||
if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
|
||||
AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
|
||||
}
|
||||
}
|
||||
|
||||
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
|
||||
@@ -213,7 +225,8 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
|
||||
}
|
||||
|
||||
/*
|
||||
* Read supported modes from eeprom
|
||||
* Read supported modes and some mode-specific calibration data
|
||||
* from eeprom
|
||||
*/
|
||||
static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
||||
unsigned int mode)
|
||||
@@ -315,6 +328,9 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
|
||||
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
|
||||
goto done;
|
||||
|
||||
/* Note: >= v5 have bg freq piers on another location
|
||||
* so these freq piers are ignored for >= v5 (should be 0xff
|
||||
* anyway) */
|
||||
switch(mode) {
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
|
||||
@@ -442,7 +458,7 @@ ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read mode-specific data (except power calibration data) */
|
||||
static int
|
||||
ath5k_eeprom_init_modes(struct ath5k_hw *ah)
|
||||
{
|
||||
@@ -488,6 +504,16 @@ ath5k_eeprom_init_modes(struct ath5k_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Used to match PCDAC steps with power values on RF5111 chips
|
||||
* (eeprom versions < 4). For RF5111 we have 10 pre-defined PCDAC
|
||||
* steps that match with the power values we read from eeprom. On
|
||||
* older eeprom versions (< 3.2) these steps are equaly spaced at
|
||||
* 10% of the pcdac curve -until the curve reaches it's maximum-
|
||||
* (10 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
|
||||
* these 10 steps are spaced in a different way. This function returns
|
||||
* the pcdac steps based on eeprom version and curve min/max so that we
|
||||
* can have pcdac/pwr points.
|
||||
*/
|
||||
static inline void
|
||||
ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
|
||||
{
|
||||
@@ -507,37 +533,48 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
|
||||
*vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100;
|
||||
}
|
||||
|
||||
/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
|
||||
* frequency mask) */
|
||||
static inline int
|
||||
ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
|
||||
struct ath5k_chan_pcal_info *pc, u8 *count)
|
||||
struct ath5k_chan_pcal_info *pc, unsigned int mode)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
int o = *offset;
|
||||
int i = 0;
|
||||
u8 f1, f2;
|
||||
u8 freq1, freq2;
|
||||
int ret;
|
||||
u16 val;
|
||||
|
||||
while(i < max) {
|
||||
AR5K_EEPROM_READ(o++, val);
|
||||
|
||||
f1 = (val >> 8) & 0xff;
|
||||
f2 = val & 0xff;
|
||||
freq1 = (val >> 8) & 0xff;
|
||||
freq2 = val & 0xff;
|
||||
|
||||
if (f1)
|
||||
pc[i++].freq = f1;
|
||||
if (freq1) {
|
||||
pc[i++].freq = ath5k_eeprom_bin2freq(ee,
|
||||
freq1, mode);
|
||||
ee->ee_n_piers[mode]++;
|
||||
}
|
||||
|
||||
if (f2)
|
||||
pc[i++].freq = f2;
|
||||
if (freq2) {
|
||||
pc[i++].freq = ath5k_eeprom_bin2freq(ee,
|
||||
freq2, mode);
|
||||
ee->ee_n_piers[mode]++;
|
||||
}
|
||||
|
||||
if (!f1 || !f2)
|
||||
if (!freq1 || !freq2)
|
||||
break;
|
||||
}
|
||||
|
||||
/* return new offset */
|
||||
*offset = o;
|
||||
*count = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read frequency piers for 802.11a */
|
||||
static int
|
||||
ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
|
||||
{
|
||||
@@ -550,7 +587,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
|
||||
if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
|
||||
ath5k_eeprom_read_freq_list(ah, &offset,
|
||||
AR5K_EEPROM_N_5GHZ_CHAN, pcal,
|
||||
&ee->ee_n_piers[AR5K_EEPROM_MODE_11A]);
|
||||
AR5K_EEPROM_MODE_11A);
|
||||
} else {
|
||||
mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
|
||||
|
||||
@@ -577,23 +614,25 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
|
||||
|
||||
AR5K_EEPROM_READ(offset++, val);
|
||||
pcal[9].freq |= (val >> 10) & 0x3f;
|
||||
ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
|
||||
}
|
||||
|
||||
for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) {
|
||||
pcal[i].freq = ath5k_eeprom_bin2freq(ee,
|
||||
/* Fixed number of piers */
|
||||
ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
|
||||
|
||||
for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
|
||||
pcal[i].freq = ath5k_eeprom_bin2freq(ee,
|
||||
pcal[i].freq, AR5K_EEPROM_MODE_11A);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
|
||||
static inline int
|
||||
ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
struct ath5k_chan_pcal_info *pcal;
|
||||
int i;
|
||||
|
||||
switch(mode) {
|
||||
case AR5K_EEPROM_MODE_11B:
|
||||
@@ -608,23 +647,25 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
|
||||
|
||||
ath5k_eeprom_read_freq_list(ah, &offset,
|
||||
AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
|
||||
&ee->ee_n_piers[mode]);
|
||||
for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) {
|
||||
pcal[i].freq = ath5k_eeprom_bin2freq(ee,
|
||||
pcal[i].freq, mode);
|
||||
}
|
||||
mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read power calibration for RF5111 chips
|
||||
* For RF5111 we have an XPD -eXternal Power Detector- curve
|
||||
* for each calibrated channel. Each curve has PCDAC steps on
|
||||
* x axis and power on y axis and looks like a logarithmic
|
||||
* function. To recreate the curve and pass the power values
|
||||
* on the pcdac table, we read 10 points here and interpolate later.
|
||||
*/
|
||||
static int
|
||||
ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
struct ath5k_chan_pcal_info *pcal;
|
||||
int offset, ret;
|
||||
int i, j;
|
||||
int i;
|
||||
u16 val;
|
||||
|
||||
offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
|
||||
@@ -704,16 +745,22 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
|
||||
|
||||
ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
|
||||
cdata->pcdac_max, cdata->pcdac);
|
||||
|
||||
for (j = 0; j < AR5K_EEPROM_N_PCDAC; j++) {
|
||||
cdata->pwr[j] = (u16)
|
||||
(AR5K_EEPROM_POWER_STEP * cdata->pwr[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read power calibration for RF5112 chips
|
||||
* For RF5112 we have 4 XPD -eXternal Power Detector- curves
|
||||
* for each calibrated channel on 0, -6, -12 and -18dbm but we only
|
||||
* use the higher (3) and the lower (0) curves. Each curve has PCDAC
|
||||
* steps on x axis and power on y axis and looks like a linear
|
||||
* function. To recreate the curve and pass the power values
|
||||
* on the pcdac table, we read 4 points for xpd 0 and 3 points
|
||||
* for xpd 3 here and interpolate later.
|
||||
*
|
||||
* Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
|
||||
*/
|
||||
static int
|
||||
ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
|
||||
{
|
||||
@@ -790,7 +837,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
|
||||
|
||||
/* PCDAC steps
|
||||
* corresponding to the above power
|
||||
* measurements (static) */
|
||||
* measurements (fixed) */
|
||||
chan_pcal_info->pcdac_x3[0] = 20;
|
||||
chan_pcal_info->pcdac_x3[1] = 35;
|
||||
chan_pcal_info->pcdac_x3[2] = 63;
|
||||
@@ -814,6 +861,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For RF2413 power calibration data doesn't start on a fixed location and
|
||||
* if a mode is not supported, it's section is missing -not zeroed-.
|
||||
* So we need to calculate the starting offset for each section by using
|
||||
* these two functions */
|
||||
|
||||
/* Return the size of each section based on the mode and the number of pd
|
||||
* gains available (maximum 4). */
|
||||
static inline unsigned int
|
||||
ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
|
||||
{
|
||||
@@ -826,6 +880,8 @@ ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
|
||||
return sz;
|
||||
}
|
||||
|
||||
/* Return the starting offset for a section based on the modes supported
|
||||
* and each section's size. */
|
||||
static unsigned int
|
||||
ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
|
||||
{
|
||||
@@ -834,11 +890,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
|
||||
switch(mode) {
|
||||
case AR5K_EEPROM_MODE_11G:
|
||||
if (AR5K_EEPROM_HDR_11B(ee->ee_header))
|
||||
offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2;
|
||||
offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) +
|
||||
AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
|
||||
/* fall through */
|
||||
case AR5K_EEPROM_MODE_11B:
|
||||
if (AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||
offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5;
|
||||
offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) +
|
||||
AR5K_EEPROM_N_5GHZ_CHAN / 2;
|
||||
/* fall through */
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
break;
|
||||
@@ -849,6 +907,17 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Read power calibration for RF2413 chips
|
||||
* For RF2413 we have a PDDAC table (Power Detector) instead
|
||||
* of a PCDAC and 4 pd gain curves for each calibrated channel.
|
||||
* Each curve has PDDAC steps on x axis and power on y axis and
|
||||
* looks like an exponential function. To recreate the curves
|
||||
* we read here the points and interpolate later. Note that
|
||||
* in most cases only higher and lower curves are used (like
|
||||
* RF5112) but vendors have the oportunity to include all 4
|
||||
* curves on eeprom. The final curve (higher power) has an extra
|
||||
* point for better accuracy like RF5112.
|
||||
*/
|
||||
static int
|
||||
ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
|
||||
{
|
||||
@@ -868,6 +937,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
|
||||
ee->ee_pd_gains[mode] = pd_gains;
|
||||
|
||||
offset = ath5k_cal_data_offset_2413(ee, mode);
|
||||
ee->ee_n_piers[mode] = 0;
|
||||
switch (mode) {
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||
@@ -1163,6 +1233,20 @@ static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read per channel calibration info from EEPROM
|
||||
*
|
||||
* This info is used to calibrate the baseband power table. Imagine
|
||||
* that for each channel there is a power curve that's hw specific
|
||||
* (depends on amplifier etc) and we try to "correct" this curve using
|
||||
* offests we pass on to phy chip (baseband -> before amplifier) so that
|
||||
* it can use accurate power values when setting tx power (takes amplifier's
|
||||
* performance on each channel into account).
|
||||
*
|
||||
* EEPROM provides us with the offsets for some pre-calibrated channels
|
||||
* and we have to interpolate to create the full table for these channels and
|
||||
* also the table for any channel.
|
||||
*/
|
||||
static int
|
||||
ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
|
||||
{
|
||||
@@ -1193,7 +1277,7 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read conformance test limits */
|
||||
/* Read conformance test limits used for regulatory control */
|
||||
static int
|
||||
ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
|
||||
int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio > AR5K_NUM_GPIO)
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
||||
ath5k_hw_reg_write(ah,
|
||||
@@ -99,7 +99,7 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
|
||||
int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio > AR5K_NUM_GPIO)
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
||||
ath5k_hw_reg_write(ah,
|
||||
@@ -115,7 +115,7 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
|
||||
u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio > AR5K_NUM_GPIO)
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return 0xffffffff;
|
||||
|
||||
/* GPIO input magic */
|
||||
@@ -131,7 +131,7 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
|
||||
u32 data;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (gpio > AR5K_NUM_GPIO)
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return -EINVAL;
|
||||
|
||||
/* GPIO output magic */
|
||||
@@ -154,7 +154,7 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
|
||||
u32 data;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
if (gpio > AR5K_NUM_GPIO)
|
||||
if (gpio >= AR5K_NUM_GPIO)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
||||
@@ -645,6 +645,23 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
|
||||
return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_set_tsf64 - Set a new 64bit TSF
|
||||
*
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @tsf64: The new 64bit TSF
|
||||
*
|
||||
* Sets the new TSF
|
||||
*/
|
||||
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
|
||||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
ath5k_hw_reg_write(ah, 0x00000000, AR5K_TSF_L32);
|
||||
ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
|
||||
ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_reset_tsf - Force a TSF reset
|
||||
*
|
||||
@@ -1026,6 +1043,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key)
|
||||
return AR5K_KEYTABLE_TYPE_40;
|
||||
else if (key->keylen == LEN_WEP104)
|
||||
return AR5K_KEYTABLE_TYPE_104;
|
||||
return -EINVAL;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1041,7 +1061,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
|
||||
__le32 key_v[5] = {};
|
||||
__le32 key0 = 0, key1 = 0;
|
||||
__le32 *rxmic, *txmic;
|
||||
u32 keytype;
|
||||
int keytype;
|
||||
u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
|
||||
bool is_tkip;
|
||||
const u8 *key_ptr;
|
||||
@@ -1139,7 +1159,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
|
||||
|
||||
/* MAC may be NULL if it's a broadcast key. In this case no need to
|
||||
* to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
|
||||
if (unlikely(mac == NULL)) {
|
||||
if (!mac) {
|
||||
low_id = 0xffffffff;
|
||||
high_id = 0xffff | AR5K_KEYTABLE_VALID;
|
||||
} else {
|
||||
|
||||
@@ -148,6 +148,7 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
|
||||
*/
|
||||
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
|
||||
{
|
||||
u32 pending;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
|
||||
|
||||
@@ -159,7 +160,15 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
|
||||
if (ah->ah_version == AR5K_AR5210)
|
||||
return false;
|
||||
|
||||
return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
|
||||
pending = (AR5K_QUEUE_STATUS(queue) & 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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -324,8 +333,18 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
/*
|
||||
* Set misc registers
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
|
||||
AR5K_QUEUE_MISC(queue));
|
||||
/* Enable DCU early termination for this queue */
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
|
||||
AR5K_QCU_MISC_DCU_EARLY);
|
||||
|
||||
/* Enable DCU to wait for next fragment from QCU */
|
||||
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,
|
||||
@@ -341,7 +360,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
AR5K_QCU_MISC_CBR_THRES_ENABLE);
|
||||
}
|
||||
|
||||
if (tq->tqi_ready_time)
|
||||
if (tq->tqi_ready_time &&
|
||||
(tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
|
||||
ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
|
||||
AR5K_QCU_RDYTIMECFG_INTVAL) |
|
||||
AR5K_QCU_RDYTIMECFG_ENABLE,
|
||||
@@ -383,13 +403,6 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
AR5K_DCU_MISC_ARBLOCK_CTL_S) |
|
||||
AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
|
||||
AR5K_DCU_MISC_BCN_ENABLE);
|
||||
|
||||
ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
|
||||
(AR5K_TUNE_SW_BEACON_RESP -
|
||||
AR5K_TUNE_DMA_BEACON_RESP) -
|
||||
AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
|
||||
AR5K_QCU_RDYTIMECFG_ENABLE,
|
||||
AR5K_QUEUE_RDYTIMECFG(queue));
|
||||
break;
|
||||
|
||||
case AR5K_TX_QUEUE_CAB:
|
||||
@@ -398,6 +411,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
AR5K_QCU_MISC_CBREXP_DIS |
|
||||
AR5K_QCU_MISC_CBREXP_BCN_DIS);
|
||||
|
||||
ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
|
||||
(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_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
|
||||
(AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
|
||||
AR5K_DCU_MISC_ARBLOCK_CTL_S));
|
||||
@@ -413,6 +433,8 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Handle frame compression */
|
||||
|
||||
/*
|
||||
* Enable interrupts for this tx queue
|
||||
* in the secondary interrupt mask registers
|
||||
@@ -483,6 +505,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
||||
* 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;
|
||||
|
||||
@@ -11,6 +11,8 @@ ath9k-y += hw.o \
|
||||
xmit.o \
|
||||
rc.o
|
||||
|
||||
ath9k-$(CONFIG_PCI) += pci.o
|
||||
ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
|
||||
ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
|
||||
|
||||
obj-$(CONFIG_ATH9K) += ath9k.o
|
||||
|
||||
187
drivers/net/wireless/ath9k/ahb.c
Normal file
187
drivers/net/wireless/ath9k/ahb.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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 <linux/ath9k_platform.h>
|
||||
#include "core.h"
|
||||
#include "reg.h"
|
||||
#include "hw.h"
|
||||
|
||||
/* return bus cachesize in 4B word units */
|
||||
static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz)
|
||||
{
|
||||
*csz = L1_CACHE_BYTES >> 2;
|
||||
}
|
||||
|
||||
static void ath_ahb_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
iounmap(sc->mem);
|
||||
}
|
||||
|
||||
static bool ath_ahb_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
struct platform_device *pdev = to_platform_device(sc->dev);
|
||||
struct ath9k_platform_data *pdata;
|
||||
|
||||
pdata = (struct ath9k_platform_data *) pdev->dev.platform_data;
|
||||
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
|
||||
"%s: flash read failed, offset %08x is out of range\n",
|
||||
__func__, off);
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = pdata->eeprom_data[off];
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct ath_bus_ops ath_ahb_bus_ops = {
|
||||
.read_cachesize = ath_ahb_read_cachesize,
|
||||
.cleanup = ath_ahb_cleanup,
|
||||
|
||||
.eeprom_read = ath_ahb_eeprom_read,
|
||||
};
|
||||
|
||||
static int ath_ahb_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *mem;
|
||||
struct ath_softc *sc;
|
||||
struct ieee80211_hw *hw;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int ret = 0;
|
||||
struct ath_hal *ah;
|
||||
|
||||
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_iounmap;
|
||||
}
|
||||
|
||||
irq = res->start;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
|
||||
if (hw == NULL) {
|
||||
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
sc = hw->priv;
|
||||
sc->hw = hw;
|
||||
sc->dev = &pdev->dev;
|
||||
sc->mem = mem;
|
||||
sc->bus_ops = &ath_ahb_bus_ops;
|
||||
sc->irq = irq;
|
||||
|
||||
ret = ath_attach(AR5416_AR9100_DEVID, sc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
|
||||
ret = -ENODEV;
|
||||
goto err_free_hw;
|
||||
}
|
||||
|
||||
ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret);
|
||||
ret = -EIO;
|
||||
goto err_detach;
|
||||
}
|
||||
|
||||
ah = sc->sc_ah;
|
||||
printk(KERN_INFO
|
||||
"%s: Atheros AR%s MAC/BB Rev:%x, "
|
||||
"AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
|
||||
wiphy_name(hw->wiphy),
|
||||
ath_mac_bb_name(ah->ah_macVersion),
|
||||
ah->ah_macRev,
|
||||
ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)),
|
||||
ah->ah_phyRev,
|
||||
(unsigned long)mem, irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_detach:
|
||||
ath_detach(sc);
|
||||
err_free_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
err_iounmap:
|
||||
iounmap(mem);
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath_ahb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
|
||||
if (hw) {
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
ath_cleanup(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 = "ath9k",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int ath_ahb_init(void)
|
||||
{
|
||||
return platform_driver_register(&ath_ahb_driver);
|
||||
}
|
||||
|
||||
void ath_ahb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ath_ahb_driver);
|
||||
}
|
||||
@@ -279,9 +279,8 @@ static void ath9k_ani_restart(struct ath_hal *ah)
|
||||
static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
enum wireless_mode mode;
|
||||
int32_t rssi;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
@@ -336,8 +335,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
|
||||
aniState->firstepLevel + 1);
|
||||
return;
|
||||
} else {
|
||||
mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
|
||||
if (conf->channel->band == IEEE80211_BAND_2GHZ) {
|
||||
if (!aniState->ofdmWeakSigDetectOff)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
|
||||
@@ -353,9 +351,8 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
|
||||
static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *chan = ah->ah_curchan;
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct ar5416AniState *aniState;
|
||||
enum wireless_mode mode;
|
||||
int32_t rssi;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
@@ -381,8 +378,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
|
||||
ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
|
||||
aniState->firstepLevel + 1);
|
||||
} else {
|
||||
mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
|
||||
if (conf->channel->band == IEEE80211_BAND_2GHZ) {
|
||||
if (aniState->firstepLevel > 0)
|
||||
ath9k_hw_ani_control(ah,
|
||||
ATH9K_ANI_FIRSTEP_LEVEL, 0);
|
||||
@@ -555,6 +551,9 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah,
|
||||
struct ar5416AniState *aniState;
|
||||
int32_t listenTime;
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
aniState = ahp->ah_curani;
|
||||
ahp->ah_stats.ast_nodestats = *stats;
|
||||
|
||||
@@ -614,9 +613,6 @@ void ath9k_hw_ani_monitor(struct ath_hal *ah,
|
||||
aniState->cckPhyErrCount = cckPhyErrCnt;
|
||||
}
|
||||
|
||||
if (!DO_ANI(ah))
|
||||
return;
|
||||
|
||||
if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
|
||||
if (aniState->ofdmPhyErrCount <= aniState->listenTime *
|
||||
aniState->ofdmTrigLow / 1000 &&
|
||||
|
||||
@@ -198,6 +198,7 @@ enum ath9k_hw_caps {
|
||||
ATH9K_HW_CAP_AUTOSLEEP = BIT(19),
|
||||
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(20),
|
||||
ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT = BIT(21),
|
||||
ATH9K_HW_CAP_BT_COEX = BIT(22)
|
||||
};
|
||||
|
||||
enum ath9k_capability_type {
|
||||
@@ -453,24 +454,15 @@ struct ath9k_11n_rate_series {
|
||||
CHANNEL_HT40MINUS)
|
||||
|
||||
struct ath9k_channel {
|
||||
struct ieee80211_channel *chan;
|
||||
u16 channel;
|
||||
u32 channelFlags;
|
||||
u8 privFlags;
|
||||
int8_t maxRegTxPower;
|
||||
int8_t maxTxPower;
|
||||
int8_t minTxPower;
|
||||
u32 chanmode;
|
||||
int32_t CalValid;
|
||||
bool oneTimeCalsDone;
|
||||
int8_t iCoff;
|
||||
int8_t qCoff;
|
||||
int16_t rawNoiseFloor;
|
||||
int8_t antennaMax;
|
||||
u32 regDmnFlags;
|
||||
u32 conformanceTestLimit[3]; /* 0:11a, 1: 11b, 2:11g */
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
|
||||
@@ -498,7 +490,6 @@ struct ath9k_channel {
|
||||
((_c)->chanmode == CHANNEL_G_HT40MINUS))
|
||||
#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c)))
|
||||
|
||||
#define IS_CHAN_IN_PUBLIC_SAFETY_BAND(_c) ((_c) > 4940 && (_c) < 4990)
|
||||
#define IS_CHAN_A_5MHZ_SPACED(_c) \
|
||||
((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
|
||||
(((_c)->channel % 20) != 0) && \
|
||||
@@ -751,6 +742,7 @@ struct ath9k_node_stats {
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
|
||||
#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
|
||||
|
||||
@@ -787,23 +779,24 @@ struct ath_hal {
|
||||
u16 ah_currentRD;
|
||||
u16 ah_currentRDExt;
|
||||
u16 ah_currentRDInUse;
|
||||
u16 ah_currentRD5G;
|
||||
u16 ah_currentRD2G;
|
||||
char ah_iso[4];
|
||||
char alpha2[2];
|
||||
struct reg_dmn_pair_mapping *regpair;
|
||||
enum ath9k_power_mode ah_power_mode;
|
||||
enum ath9k_power_mode ah_restore_mode;
|
||||
|
||||
struct ath9k_channel ah_channels[150];
|
||||
struct ath9k_channel ah_channels[38];
|
||||
struct ath9k_channel *ah_curchan;
|
||||
u32 ah_nchan;
|
||||
|
||||
bool ah_isPciExpress;
|
||||
u16 ah_txTrigLevel;
|
||||
u16 ah_rfsilent;
|
||||
u32 ah_rfkill_gpio;
|
||||
u32 ah_rfkill_polarity;
|
||||
|
||||
#ifndef ATH_NF_PER_CHAN
|
||||
u32 ah_btactive_gpio;
|
||||
u32 ah_wlanactive_gpio;
|
||||
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
|
||||
#endif
|
||||
|
||||
bool sw_mgmt_crypto;
|
||||
};
|
||||
|
||||
struct chan_centers {
|
||||
@@ -816,8 +809,6 @@ struct ath_rate_table;
|
||||
|
||||
/* Helpers */
|
||||
|
||||
enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan);
|
||||
bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
bool ath9k_get_channel_edges(struct ath_hal *ah,
|
||||
@@ -827,7 +818,6 @@ u16 ath9k_hw_computetxtime(struct ath_hal *ah,
|
||||
struct ath_rate_table *rates,
|
||||
u32 frameLen, u16 rateix,
|
||||
bool shortPreamble);
|
||||
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
|
||||
void ath9k_hw_get_channel_centers(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
struct chan_centers *centers);
|
||||
@@ -843,11 +833,8 @@ void ath9k_hw_rfdetach(struct ath_hal *ah);
|
||||
|
||||
/* HW Reset */
|
||||
|
||||
bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
enum ath9k_ht_macmode macmode,
|
||||
u8 txchainmask, u8 rxchainmask,
|
||||
enum ath9k_ht_extprotspacing extprotspacing,
|
||||
bool bChannelChange, int *status);
|
||||
int ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool bChannelChange);
|
||||
|
||||
/* Key Cache Management */
|
||||
|
||||
@@ -887,7 +874,6 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
|
||||
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
|
||||
void ath9k_enable_rfkill(struct ath_hal *ah);
|
||||
#endif
|
||||
int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
|
||||
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
|
||||
void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
|
||||
bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
|
||||
@@ -912,23 +898,25 @@ void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
|
||||
bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
|
||||
void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
|
||||
u64 ath9k_hw_gettsf64(struct ath_hal *ah);
|
||||
void ath9k_hw_settsf64(struct ath_hal *ah, u64 tsf64);
|
||||
void ath9k_hw_reset_tsf(struct ath_hal *ah);
|
||||
bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
|
||||
bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
|
||||
void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
|
||||
|
||||
/* Regulatory */
|
||||
u16 ath9k_regd_get_rd(struct ath_hal *ah);
|
||||
bool ath9k_is_world_regd(struct ath_hal *ah);
|
||||
const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hal *ah);
|
||||
const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
|
||||
|
||||
bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
|
||||
struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
|
||||
const struct ath9k_channel *c);
|
||||
void ath9k_reg_apply_world_flags(struct wiphy *wiphy, enum reg_set_by setby);
|
||||
void ath9k_reg_apply_radar_flags(struct wiphy *wiphy);
|
||||
|
||||
int ath9k_regd_init(struct ath_hal *ah);
|
||||
bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah);
|
||||
u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
bool ath9k_regd_init_channels(struct ath_hal *ah,
|
||||
u32 maxchans, u32 *nchans, u8 *regclassids,
|
||||
u32 maxregids, u32 *nregids, u16 cc,
|
||||
bool enableOutdoor, bool enableExtendedChannels);
|
||||
int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
|
||||
|
||||
/* ANI */
|
||||
|
||||
@@ -951,8 +939,7 @@ void ath9k_hw_ani_detach(struct ath_hal *ah);
|
||||
|
||||
/* Calibration */
|
||||
|
||||
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool *isCalDone);
|
||||
bool ath9k_hw_reset_calvalid(struct ath_hal *ah);
|
||||
void ath9k_hw_start_nfcal(struct ath_hal *ah);
|
||||
void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
|
||||
int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
@@ -987,9 +974,8 @@ bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
|
||||
int16_t *pTxPowerIndexOffset);
|
||||
bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u8 index, u16 *config);
|
||||
u16 ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan);
|
||||
u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
|
||||
enum ieee80211_band freq_band);
|
||||
u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz);
|
||||
@@ -1053,5 +1039,6 @@ void ath9k_hw_rxena(struct ath_hal *ah);
|
||||
void ath9k_hw_startpcureceive(struct ath_hal *ah);
|
||||
void ath9k_hw_stoppcurecv(struct ath_hal *ah);
|
||||
bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
|
||||
void ath9k_hw_btcoex_enable(struct ath_hal *ah);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -164,9 +164,9 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
bf = avp->av_bcbuf;
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
if (skb) {
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
@@ -188,14 +188,14 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
}
|
||||
|
||||
bf->bf_buf_addr = bf->bf_dmacontext =
|
||||
pci_map_single(sc->pdev, skb->data,
|
||||
dma_map_single(sc->dev, skb->data,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"pci_dma_mapping_error() on beaconing\n");
|
||||
"dma_mapping_error() on beaconing\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
|
||||
* acquires txq lock inside.
|
||||
*/
|
||||
if (sc->sc_nvaps > 1) {
|
||||
ath_tx_draintxq(sc, cabq, false);
|
||||
ath_draintxq(sc, cabq, false);
|
||||
DPRINTF(sc, ATH_DBG_BEACON,
|
||||
"flush previous cabq traffic\n");
|
||||
}
|
||||
@@ -343,9 +343,9 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
bf = avp->av_bcbuf;
|
||||
if (bf->bf_mpdu != NULL) {
|
||||
skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
@@ -402,14 +402,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
|
||||
|
||||
bf->bf_mpdu = skb;
|
||||
bf->bf_buf_addr = bf->bf_dmacontext =
|
||||
pci_map_single(sc->pdev, skb->data,
|
||||
dma_map_single(sc->dev, skb->data,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
DPRINTF(sc, ATH_DBG_CONFIG,
|
||||
"pci_dma_mapping_error() on beacon alloc\n");
|
||||
"dma_mapping_error() on beacon alloc\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -429,9 +429,9 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
|
||||
bf = avp->av_bcbuf;
|
||||
if (bf->bf_mpdu != NULL) {
|
||||
struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
|
||||
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
|
||||
dma_unmap_single(sc->dev, bf->bf_dmacontext,
|
||||
skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
#include "reg.h"
|
||||
#include "phy.h"
|
||||
|
||||
static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
|
||||
|
||||
/* We can tune this as we go by monitoring really low values */
|
||||
#define ATH9K_NF_TOO_LOW -60
|
||||
|
||||
@@ -107,27 +105,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
|
||||
"NF calibrated [ctl] [chain 0] is %d\n", nf);
|
||||
nfarray[0] = nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR9280_PHY_CH1_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR_PHY_CH1_MINCCA_PWR);
|
||||
if (!AR_SREV_9285(ah)) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR9280_PHY_CH1_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
|
||||
AR_PHY_CH1_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 1] is %d\n", nf);
|
||||
nfarray[1] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
|
||||
AR_PHY_CH2_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 2] is %d\n", nf);
|
||||
nfarray[2] = nf;
|
||||
"NF calibrated [ctl] [chain 1] is %d\n", nf);
|
||||
nfarray[1] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
|
||||
AR_PHY_CH2_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ctl] [chain 2] is %d\n", nf);
|
||||
nfarray[2] = nf;
|
||||
}
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
@@ -143,51 +143,45 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
|
||||
"NF calibrated [ext] [chain 0] is %d\n", nf);
|
||||
nfarray[3] = nf;
|
||||
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR9280_PHY_CH1_EXT_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR_PHY_CH1_EXT_MINCCA_PWR);
|
||||
if (!AR_SREV_9285(ah)) {
|
||||
if (AR_SREV_9280_10_OR_LATER(ah))
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR9280_PHY_CH1_EXT_MINCCA_PWR);
|
||||
else
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
|
||||
AR_PHY_CH1_EXT_MINCCA_PWR);
|
||||
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 1] is %d\n", nf);
|
||||
nfarray[4] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
|
||||
AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 2] is %d\n", nf);
|
||||
nfarray[5] = nf;
|
||||
"NF calibrated [ext] [chain 1] is %d\n", nf);
|
||||
nfarray[4] = nf;
|
||||
|
||||
if (!AR_SREV_9280(ah)) {
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
|
||||
AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
if (nf & 0x100)
|
||||
nf = 0 - ((nf ^ 0x1ff) + 1);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"NF calibrated [ext] [chain 2] is %d\n", nf);
|
||||
nfarray[5] = nf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool getNoiseFloorThresh(struct ath_hal *ah,
|
||||
const struct ath9k_channel *chan,
|
||||
enum ieee80211_band band,
|
||||
int16_t *nft)
|
||||
{
|
||||
switch (chan->chanmode) {
|
||||
case CHANNEL_A:
|
||||
case CHANNEL_A_HT20:
|
||||
case CHANNEL_A_HT40PLUS:
|
||||
case CHANNEL_A_HT40MINUS:
|
||||
switch (band) {
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
|
||||
break;
|
||||
case CHANNEL_B:
|
||||
case CHANNEL_G:
|
||||
case CHANNEL_G_HT20:
|
||||
case CHANNEL_G_HT40PLUS:
|
||||
case CHANNEL_G_HT40MINUS:
|
||||
case IEEE80211_BAND_2GHZ:
|
||||
*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
|
||||
break;
|
||||
default:
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"invalid channel flags 0x%x\n", chan->channelFlags);
|
||||
BUG_ON(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -285,27 +279,24 @@ static void ath9k_hw_per_calibration(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
/* Assumes you are talking about the currently configured channel */
|
||||
static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan,
|
||||
enum hal_cal_types calType)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
bool retval = false;
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
|
||||
switch (calType & ahp->ah_suppCals) {
|
||||
case IQ_MISMATCH_CAL:
|
||||
if (!IS_CHAN_B(chan))
|
||||
retval = true;
|
||||
break;
|
||||
case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
|
||||
return true;
|
||||
case ADC_GAIN_CAL:
|
||||
case ADC_DC_CAL:
|
||||
if (!IS_CHAN_B(chan)
|
||||
&& !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
|
||||
retval = true;
|
||||
if (conf->channel->band == IEEE80211_BAND_5GHZ &&
|
||||
conf_is_ht20(conf))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
|
||||
@@ -573,50 +564,40 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
|
||||
AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
|
||||
}
|
||||
|
||||
void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
bool *isCalDone)
|
||||
/* This is done for the currently configured channel */
|
||||
bool ath9k_hw_reset_calvalid(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *ichan =
|
||||
ath9k_regd_check_channel(ah, chan);
|
||||
struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
|
||||
struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
|
||||
|
||||
*isCalDone = true;
|
||||
if (!ah->ah_curchan)
|
||||
return true;
|
||||
|
||||
if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (currCal == NULL)
|
||||
return;
|
||||
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
if (currCal->calState != CAL_DONE) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Calibration state incorrect, %d\n",
|
||||
currCal->calState);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
|
||||
return;
|
||||
if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
|
||||
return true;
|
||||
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"Resetting Cal %d state for channel %u/0x%x\n",
|
||||
currCal->calData->calType, chan->channel,
|
||||
chan->channelFlags);
|
||||
"Resetting Cal %d state for channel %u\n",
|
||||
currCal->calData->calType, conf->channel->center_freq);
|
||||
|
||||
ichan->CalValid &= ~currCal->calData->calType;
|
||||
ah->ah_curchan->CalValid &= ~currCal->calData->calType;
|
||||
currCal->calState = CAL_WAITING;
|
||||
|
||||
*isCalDone = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ath9k_hw_start_nfcal(struct ath_hal *ah)
|
||||
@@ -643,16 +624,14 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
};
|
||||
u8 chainmask;
|
||||
|
||||
if (AR_SREV_9280(ah))
|
||||
if (AR_SREV_9285(ah))
|
||||
chainmask = 0x9;
|
||||
else if (AR_SREV_9280(ah))
|
||||
chainmask = 0x1B;
|
||||
else
|
||||
chainmask = 0x3F;
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
if (chainmask & (1 << i)) {
|
||||
@@ -692,12 +671,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
int16_t nf, nfThresh;
|
||||
int16_t nfarray[NUM_NF_READINGS] = { 0 };
|
||||
struct ath9k_nfcal_hist *h;
|
||||
u8 chainmask;
|
||||
|
||||
if (AR_SREV_9280(ah))
|
||||
chainmask = 0x1B;
|
||||
else
|
||||
chainmask = 0x3F;
|
||||
struct ieee80211_channel *c = chan->chan;
|
||||
|
||||
chan->channelFlags &= (~CHANNEL_CW_INT);
|
||||
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
|
||||
@@ -709,7 +683,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
} else {
|
||||
ath9k_hw_do_getnf(ah, nfarray);
|
||||
nf = nfarray[0];
|
||||
if (getNoiseFloorThresh(ah, chan, &nfThresh)
|
||||
if (getNoiseFloorThresh(ah, c->band, &nfThresh)
|
||||
&& nf > nfThresh) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"noise floor failed detected; "
|
||||
@@ -719,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ATH_NF_PER_CHAN
|
||||
h = chan->nfCalHist;
|
||||
#else
|
||||
h = ah->nfCalHist;
|
||||
#endif
|
||||
|
||||
ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
|
||||
chan->rawNoiseFloor = h[0].privNF;
|
||||
@@ -750,21 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
|
||||
|
||||
s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath9k_channel *ichan;
|
||||
s16 nf;
|
||||
|
||||
ichan = ath9k_regd_check_channel(ah, chan);
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return ATH_DEFAULT_NOISE_FLOOR;
|
||||
}
|
||||
if (ichan->rawNoiseFloor == 0) {
|
||||
enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
|
||||
nf = NOISE_FLOOR[mode];
|
||||
} else
|
||||
nf = ichan->rawNoiseFloor;
|
||||
if (chan->rawNoiseFloor == 0)
|
||||
nf = -96;
|
||||
else
|
||||
nf = chan->rawNoiseFloor;
|
||||
|
||||
if (!ath9k_hw_nf_in_range(ah, nf))
|
||||
nf = ATH_DEFAULT_NOISE_FLOOR;
|
||||
@@ -778,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
*isCalDone = true;
|
||||
|
||||
if (ichan == NULL) {
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
|
||||
"invalid channel %u/0x%x; no mapping\n",
|
||||
chan->channel, chan->channelFlags);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currCal &&
|
||||
(currCal->calState == CAL_RUNNING ||
|
||||
currCal->calState == CAL_WAITING)) {
|
||||
ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
|
||||
ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
|
||||
isCalDone);
|
||||
if (*isCalDone) {
|
||||
ahp->ah_cal_list_curr = currCal = currCal->calNext;
|
||||
@@ -805,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
|
||||
}
|
||||
|
||||
if (longcal) {
|
||||
ath9k_hw_getnf(ah, ichan);
|
||||
ath9k_hw_getnf(ah, chan);
|
||||
ath9k_hw_loadnf(ah, ah->ah_curchan);
|
||||
ath9k_hw_start_nfcal(ah);
|
||||
|
||||
if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
|
||||
chan->channelFlags |= CHANNEL_CW_INT;
|
||||
ichan->channelFlags &= ~CHANNEL_CW_INT;
|
||||
}
|
||||
if (chan->channelFlags & CHANNEL_CW_INT)
|
||||
chan->channelFlags &= ~CHANNEL_CW_INT;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -917,7 +868,6 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_hal_5416 *ahp = AH5416(ah);
|
||||
struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL) |
|
||||
@@ -940,19 +890,19 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
|
||||
|
||||
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
|
||||
if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
|
||||
if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
|
||||
INIT_CAL(&ahp->ah_adcGainCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC Gain Calibration.\n");
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
|
||||
if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
|
||||
INIT_CAL(&ahp->ah_adcDcCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
"enabling ADC DC Calibration.\n");
|
||||
}
|
||||
if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
|
||||
if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
|
||||
INIT_CAL(&ahp->ah_iqCalData);
|
||||
INSERT_CAL(ahp, &ahp->ah_iqCalData);
|
||||
DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
|
||||
@@ -965,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah,
|
||||
ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
|
||||
}
|
||||
|
||||
ichan->CalValid = 0;
|
||||
chan->CalValid = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user