Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller
2009-02-03 12:41:58 -08:00
212 changed files with 17148 additions and 16711 deletions

View File

@@ -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>

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -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)
{

View File

@@ -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;
/*

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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

View 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);
}

View File

@@ -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 &&

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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