Commit 1725d409 authored by David S. Miller's avatar David S. Miller
parents b3ff29d2 b8abde45
......@@ -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
This diff is collapsed.
......@@ -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,14 +1093,10 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
* Buffers setup *
\***************/
static int
ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
static
struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
{
struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb = bf->skb;
struct ath5k_desc *ds;
if (likely(skb == NULL)) {
struct sk_buff *skb;
unsigned int off;
/*
......@@ -1113,10 +1104,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
* fake physical layer header at the start.
*/
skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
if (unlikely(skb == NULL)) {
if (!skb) {
ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
sc->rxbufsize + sc->cachelsz - 1);
return -ENOMEM;
return NULL;
}
/*
* Cache-line-align. This is important (for the
......@@ -1127,15 +1119,28 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
if (off != 0)
skb_reserve(skb, sc->cachelsz - off);
bf->skb = skb;
bf->skbaddr = pci_map_single(sc->pdev,
*skb_addr = pci_map_single(sc->pdev,
skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
dev_kfree_skb(skb);
bf->skb = NULL;
return -ENOMEM;
return NULL;
}
return skb;
}
static int
ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
{
struct ath5k_hw *ah = sc->ah;
struct sk_buff *skb = bf->skb;
struct ath5k_desc *ds;
if (!skb) {
skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
if (!skb)
return -ENOMEM;
bf->skb = skb;
}
/*
......@@ -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 @@ ath5k_tasklet_rx(unsigned long data)
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,7 +3040,7 @@ 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_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
struct ath5k_softc *sc = hw->priv;
......@@ -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;
};
......
This diff is collapsed.
......@@ -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
/*
* 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,6 +105,7 @@ 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_9285(ah)) {
if (AR_SREV_9280_10_OR_LATER(ah))
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
AR9280_PHY_CH1_MINCCA_PWR);
......@@ -129,6 +128,7 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
"NF calibrated [ctl] [chain 2] is %d\n", nf);
nfarray[2] = nf;
}
}
if (AR_SREV_9280_10_OR_LATER(ah))
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
......@@ -143,6 +143,7 @@ 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_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);
......@@ -165,29 +166,22 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah,
"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;
}
......
......@@ -18,7 +18,7 @@
#define CORE_H
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <net/mac80211.h>
#include <linux/leds.h>
#include <linux/rfkill.h>
......@@ -187,7 +187,6 @@ struct ath_config {
#define ATH_TXBUF_RESET(_bf) do { \
(_bf)->bf_status = 0; \
(_bf)->bf_lastbf = NULL; \
(_bf)->bf_lastfrm = NULL; \
(_bf)->bf_next = NULL; \
memset(&((_bf)->bf_state), 0, \
sizeof(struct ath_buf_state)); \
......@@ -245,10 +244,8 @@ struct ath_buf_state {
*/
struct ath_buf {
struct list_head list;
struct list_head *last;
struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or
an aggregate) */
struct ath_buf *bf_lastfrm; /* last buf of this frame */
struct ath_buf *bf_next; /* next subframe in the aggregate */
void *bf_mpdu; /* enclosing frame structure */
struct ath_desc *bf_desc; /* virtual addr of desc */
......@@ -261,13 +258,7 @@ struct ath_buf {
};
#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0)
/* hw processing complete, desc processed by hal */
#define ATH_BUFSTATUS_DONE 0x00000001
/* hw processing complete, desc hold for hw */
#define ATH_BUFSTATUS_STALE 0x00000002
/* Rx-only: OS is done with this packet and it's ok to queued it to hw */
#define ATH_BUFSTATUS_FREE 0x00000004
/* DMA state for tx/rx descriptors */
......@@ -360,7 +351,6 @@ struct ath_txq {
u32 *axq_link; /* link ptr in last TX desc */
struct list_head axq_q; /* transmit queue */
spinlock_t axq_lock;
unsigned long axq_lockflags; /* intr state when must cli */
u32 axq_depth; /* queue depth */
u8 axq_aggr_depth; /* aggregates queued */
u32 axq_totalqueued; /* total ever queued */
......@@ -485,28 +475,22 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype);
void ath_draintxq(struct ath_softc *sc, bool retry_tx);
void ath_tx_draintxq(struct ath_softc *sc,
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
void ath_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_tx_cleanup(struct ath_softc *sc);
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
u32 ath_txq_depth(struct ath_softc *sc, int qnum);
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno);
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn);
int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
......@@ -692,14 +676,22 @@ enum PROT_MODE {
#define SC_OP_RFKILL_REGISTERED BIT(11)
#define SC_OP_RFKILL_SW_BLOCKED BIT(12)
#define SC_OP_RFKILL_HW_BLOCKED BIT(13)
#define SC_OP_WAIT_FOR_BEACON BIT(14)
struct ath_bus_ops {
void (*read_cachesize)(struct ath_softc *sc, int *csz);
void (*cleanup)(struct ath_softc *sc);
bool (*eeprom_read)(struct ath_hal *ah, u32 off, u16 *data);
};
struct ath_softc {
struct ieee80211_hw *hw;
struct pci_dev *pdev;
struct device *dev;
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
struct ath_hal *sc_ah;
void __iomem *mem;
int irq;
spinlock_t sc_resetlock;
struct mutex mutex;
......@@ -718,7 +710,7 @@ struct ath_softc {
u32 sc_keymax;
DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);
u8 sc_splitmic;
u8 sc_protrix;
atomic_t ps_usecount;
enum ath9k_int sc_imask;
enum PROT_MODE sc_protmode;
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
......@@ -732,7 +724,6 @@ struct ath_softc {
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
struct ath_rate_table *cur_rate_table;
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
struct ath_led radio_led;
struct ath_led assoc_led;
......@@ -744,6 +735,7 @@ struct ath_softc {
#ifdef CONFIG_ATH9K_DEBUG
struct ath9k_debug sc_debug;
#endif
struct ath_bus_ops *bus_ops;
};
int ath_reset(struct ath_softc *sc, bool retry_tx);
......@@ -751,4 +743,55 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *);
static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
{
sc->bus_ops->read_cachesize(sc, csz);
}
static inline void ath_bus_cleanup(struct ath_softc *sc)
{
sc->bus_ops->cleanup(sc);
}
extern struct ieee80211_ops ath9k_ops;
irqreturn_t ath_isr(int irq, void *dev);
void ath_cleanup(struct ath_softc *sc);
int ath_attach(u16 devid, struct ath_softc *sc);
void ath_detach(struct ath_softc *sc);
const char *ath_mac_bb_name(u32 mac_bb_version);
const char *ath_rf_name(u16 rf_version);
#ifdef CONFIG_PCI
int ath_pci_init(void);
void ath_pci_exit(void);
#else
static inline int ath_pci_init(void) { return 0; };
static inline void ath_pci_exit(void) {};
#endif
#ifdef CONFIG_ATHEROS_AR71XX
int ath_ahb_init(void);
void ath_ahb_exit(void);
#else
static inline int ath_ahb_init(void) { return 0; };
static inline void ath_ahb_exit(void) {};
#endif
static inline void ath9k_ps_wakeup(struct ath_softc *sc)
{
if (atomic_inc_return(&sc->ps_usecount) == 1)
if (sc->sc_ah->ah_power_mode != ATH9K_PM_AWAKE) {
sc->sc_ah->ah_restore_mode = sc->sc_ah->ah_power_mode;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
}
}
static inline void ath9k_ps_restore(struct ath_softc *sc)
{
if (atomic_dec_and_test(&sc->ps_usecount))
if (sc->hw->conf.flags & IEEE80211_CONF_PS)
ath9k_hw_setpower(sc->sc_ah,
sc->sc_ah->ah_restore_mode);
}
#endif /* CORE_H */
......@@ -222,6 +222,7 @@ static const struct file_operations fops_interrupt = {
.owner = THIS_MODULE
};
int ath9k_init_debug(struct ath_softc *sc)
{
sc->sc_debug.debug_mask = ath9k_debug;
......
......@@ -91,53 +91,11 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
return false;
}
static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
{
(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
if (!ath9k_hw_wait(ah,
AR_EEPROM_STATUS_DATA,
AR_EEPROM_STATUS_DATA_BUSY |
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
return false;
}
*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
AR_EEPROM_STATUS_DATA_VAL);
return true;
}
static int ath9k_hw_flash_map(struct ath_hal *ah)
{
struct ath_hal_5416 *ahp = AH5416(ah);
ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
if (!ahp->ah_cal_mem) {
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
"cannot remap eeprom region \n");
return -EIO;
}
return 0;
}
static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data)
{
struct ath_hal_5416 *ahp = AH5416(ah);
*data = ioread16(ahp->ah_cal_mem + off);
return true;
}
static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data)
{
if (ath9k_hw_use_flash(ah))
return ath9k_hw_flash_read(ah, off, data);
else
return ath9k_hw_eeprom_read(ah, off, data);
struct ath_softc *sc = ah->ah_sc;
return sc->bus_ops->eeprom_read(ah, off, data);
}
static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
......@@ -2121,19 +2079,19 @@ void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
struct ath9k_channel *chan)
{
#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK)
struct modal_eep_header *pModal;
struct ath_hal_5416 *ahp = AH5416(ah);
struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
int i, regChainOffset;
u8 txRxAttenLocal;
u16 ant_config;
pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
REG_WRITE(ah, AR_PHY_SWITCH_COM,
ath9k_hw_get_eeprom_antenna_cfg(ah, chan));
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
if (AR_SREV_9280(ah)) {
......@@ -2163,9 +2121,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
if ((eep->baseEepHeader.version &
AR5416_EEP_VER_MINOR_MASK) >=
AR5416_EEP_MINOR_VER_3) {
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
txRxAttenLocal = pModal->txRxAttenCh[i];
if (AR_SREV_9280_10_OR_LATER(ah)) {
REG_RMW_FIELD(ah,
......@@ -2332,8 +2288,7 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
pModal->thresh62);
}
if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
AR5416_EEP_MINOR_VER_2) {
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
AR_PHY_TX_END_DATA_START,
pModal->txFrameToDataStart);
......@@ -2341,15 +2296,29 @@ static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
pModal->txFrameToPaOn);
}
if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
AR5416_EEP_MINOR_VER_3) {
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
if (IS_CHAN_HT40(chan))
REG_RMW_FIELD(ah, AR_PHY_SETTLING,
AR_PHY_SETTLING_SWITCH,
pModal->swSettleHt40);
}
if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
if (IS_CHAN_HT20(chan))
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
eep->baseEepHeader.dacLpMode);
else if (eep->baseEepHeader.dacHiPwrMode_5G)
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
else
REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
eep->baseEepHeader.dacLpMode);
REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
pModal->miscBits >> 2);
}
return true;
#undef AR5416_VER_MASK
}
static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
......@@ -2360,7 +2329,6 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
int regChainOffset;
u8 txRxAttenLocal;
u16 ant_config = 0;
u8 ob[5], db1[5], db2[5];
u8 ant_div_control1, ant_div_control2;
u32 regVal;
......@@ -2370,8 +2338,8 @@ static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
txRxAttenLocal = 23;
ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
REG_WRITE(ah, AR_PHY_SWITCH_COM,
ath9k_hw_get_eeprom_antenna_cfg(ah, chan));
regChainOffset = 0;
REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
......@@ -2554,70 +2522,39 @@ bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
return ath9k_eeprom_set_board_values[ahp->ah_eep_map](ah, chan);
}
static int ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
struct ath9k_channel *chan,
u8 index, u16 *config)
static u16 ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
struct ath9k_channel *chan)
{
struct ath_hal_5416 *ahp = AH5416(ah);
struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
struct modal_eep_header *pModal =
&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
struct base_eep_header *pBase = &eep->baseEepHeader;
switch (index) {
case 0:
*config = pModal->antCtrlCommon & 0xFFFF;
return 0;
case 1:
if (pBase->version >= 0x0E0D) {
if (pModal->useAnt1) {
*config =
((pModal->antCtrlCommon & 0xFFFF0000) >> 16);
return 0;
}
}
break;
default:
break;
}
return -EINVAL;
return pModal->antCtrlCommon & 0xFFFF;
}
static int ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
struct ath9k_channel *chan,
u8 index, u16 *config)
static u16 ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
struct ath9k_channel *chan)
{
struct ath_hal_5416 *ahp = AH5416(ah);
struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader;
switch (index) {
case 0:
*config = pModal->antCtrlCommon & 0xFFFF;
return 0;
default:
break;
}
return -EINVAL;
return pModal->antCtrlCommon & 0xFFFF;
}
static int (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *,
struct ath9k_channel *,
u8, u16 *) = {
static u16 (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *,
struct ath9k_channel *) = {
ath9k_hw_get_def_eeprom_antenna_cfg,
ath9k_hw_get_4k_eeprom_antenna_cfg
};
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)
{
struct ath_hal_5416 *ahp = AH5416(ah);
return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan,
index, config);
return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan);
}
static u8 ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
......@@ -2739,6 +2676,7 @@ static u32 ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
enum eeprom_param param)
{
#define AR5416_VER_MASK (pBase->version & AR5416_EEP_VER_MINOR_MASK)
struct ath_hal_5416 *ahp = AH5416(ah);
struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
struct modal_eep_header *pModal = eep->modalHeader;
......@@ -2774,7 +2712,7 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
case EEP_DB_2:
return pModal[1].db;
case EEP_MINOR_REV:
return pBase->version & AR5416_EEP_VER_MINOR_MASK;
return AR5416_VER_MASK;
case EEP_TX_MASK:
return pBase->txMask;
case EEP_RX_MASK:
......@@ -2783,10 +2721,15 @@ static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
return pBase->rxGainType;
case EEP_TXGAIN_TYPE:
return pBase->txGainType;
case EEP_DAC_HPWR_5G:
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
return pBase->dacHiPwrMode_5G;
else
return 0;
default:
return 0;
}
#undef AR5416_VER_MASK
}
static u32 (*ath9k_get_eeprom[])(struct ath_hal *, enum eeprom_param) = {
......@@ -2807,9 +2750,6 @@ int ath9k_hw_eeprom_attach(struct ath_hal *ah)
int status;
struct ath_hal_5416 *ahp = AH5416(ah);
if (ath9k_hw_use_flash(ah))
ath9k_hw_flash_map(ah);
if (AR_SREV_9285(ah))
ahp->ah_eep_map = EEP_MAP_4KBITS;
else
......
This diff is collapsed.
......@@ -20,6 +20,14 @@
#include <linux/if_ether.h>
#include <linux/delay.h>
extern const struct hal_percal_data iq_cal_multi_sample;
extern const struct hal_percal_data iq_cal_single_sample;
extern const struct hal_percal_data adc_gain_cal_multi_sample;
extern const struct hal_percal_data adc_gain_cal_single_sample;
extern const struct hal_percal_data adc_dc_cal_multi_sample;
extern const struct hal_percal_data adc_dc_cal_single_sample;
extern const struct hal_percal_data adc_init_dc_cal;
struct ar5416_desc {
u32 ds_link;
u32 ds_data;
......@@ -418,6 +426,7 @@ struct ar5416Stats {
#define AR5416_EEP_MINOR_VER_16 0x10
#define AR5416_EEP_MINOR_VER_17 0x11
#define AR5416_EEP_MINOR_VER_19 0x13
#define AR5416_EEP_MINOR_VER_20 0x14
#define AR5416_NUM_5G_CAL_PIERS 8
#define AR5416_NUM_2G_CAL_PIERS 4
......@@ -480,6 +489,7 @@ enum eeprom_param {
EEP_RX_MASK,
EEP_RXGAIN_TYPE,
EEP_TXGAIN_TYPE,
EEP_DAC_HPWR_5G,
};
enum ar5416_rates {
......@@ -518,9 +528,13 @@ struct base_eep_header {
u8 pwdclkind;
u8 futureBase_1[2];
u8 rxGainType;
u8 futureBase_2[3];
u8 dacHiPwrMode_5G;
u8 futureBase_2;
u8 dacLpMode;
u8 txGainType;
u8 futureBase_3[25];
u8 rcChainMask;
u8 desiredScaleCCK;
u8 futureBase_3[23];
} __packed;
struct base_eep_header_4k {
......@@ -587,7 +601,7 @@ struct modal_eep_header {
force_xpaon:1,
local_bias:1,
femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1;
u8 futureModalar9280;
u8 miscBits;
u16 xpaBiasLvlFreq[3];
u8 futureModal[6];
......@@ -830,7 +844,6 @@ struct ath_hal_5416 {
bool ah_chipFullSleep;
u32 ah_atimWindow;
u16 ah_antennaSwitchSwap;
enum ath9k_power_mode ah_powerMode;
enum ath9k_ant_setting ah_diversityControl;
/* Calibration */
......
This diff is collapsed.
......@@ -107,14 +107,32 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
{
#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
#define ATH9K_TIME_QUANTUM 100 /* usec */
struct ath_hal_5416 *ahp = AH5416(ah);
struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
struct ath9k_tx_queue_info *qi;
u32 tsfLow, j, wait;
u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
if (q >= pCap->total_queues) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
return false;
}
qi = &ahp->ah_txq[q];
if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
return false;
}
REG_WRITE(ah, AR_Q_TXD, 1 << q);
for (wait = 1000; wait != 0; wait--) {
for (wait = wait_time; wait != 0; wait--) {
if (ath9k_hw_numtxpending(ah, q) == 0)
break;
udelay(100);
udelay(ATH9K_TIME_QUANTUM);
}
if (ath9k_hw_numtxpending(ah, q)) {
......@@ -144,8 +162,7 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
udelay(200);
REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
wait = 1000;
wait = wait_time;
while (ath9k_hw_numtxpending(ah, q)) {
if ((--wait) == 0) {
DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
......@@ -153,15 +170,17 @@ bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
"msec after killing last frame\n");
break;
}
udelay(100);
udelay(ATH9K_TIME_QUANTUM);
}
REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
}
REG_WRITE(ah, AR_Q_TXD, 0);
return wait != 0;
#undef ATH9K_TX_STOP_DMA_TIMEOUT
#undef ATH9K_TIME_QUANTUM
}
bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
......
This diff is collapsed.
/*
* Copyright (c) 2008 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/nl80211.h>
#include <linux/pci.h>
#include "core.h"
#include "reg.h"
#include "hw.h"
static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
{ 0 }
};
/* return bus cachesize in 4B word units */
static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
{
u8 u8tmp;
pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE,
(u8 *)&u8tmp);
*csz = (int)u8tmp;
/*
* This check was put in to avoid "unplesant" consequences if
* the bootrom has not fully initialized all PCI devices.
* Sometimes the cache line size register is not set
*/
if (*csz == 0)
*csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
}
static void ath_pci_cleanup(struct ath_softc *sc)
{
struct pci_dev *pdev = to_pci_dev(sc->dev);
pci_iounmap(pdev, sc->mem);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
}
static bool ath_pci_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
{
(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
if (!ath9k_hw_wait(ah,
AR_EEPROM_STATUS_DATA,
AR_EEPROM_STATUS_DATA_BUSY |
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
return false;
}
*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
AR_EEPROM_STATUS_DATA_VAL);
return true;
}
static struct ath_bus_ops ath_pci_bus_ops = {
.read_cachesize = ath_pci_read_cachesize,
.cleanup = ath_pci_cleanup,
.eeprom_read = ath_pci_eeprom_read,
};
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
void __iomem *mem;
struct ath_softc *sc;
struct ieee80211_hw *hw;
u8 csz;
u32 val;
int ret = 0;
struct ath_hal *ah;
if (pci_enable_device(pdev))
return -EIO;
ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
goto bad;
}
ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (ret) {
printk(KERN_ERR "ath9k: 32-bit DMA consistent "
"DMA enable failed\n");
goto bad;
}
/*
* Cache line size is used to size and align various
* structures used to communicate with the hardware.
*/
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
if (csz == 0) {
/*
* Linux 2.4.18 (at least) writes the cache line size
* register as a 16-bit wide register which is wrong.
* We must have this setup properly for rx buffer
* DMA to work so force a reasonable value here if it
* comes up zero.
*/
csz = L1_CACHE_BYTES / sizeof(u32);
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
}
/*
* The default setting of latency timer yields poor results,
* set it to the value used by other systems. It may be worth
* tweaking this setting more.
*/
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
pci_set_master(pdev);
/*
* Disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state.
*/
pci_read_config_dword(pdev, 0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
ret = pci_request_region(pdev, 0, "ath9k");
if (ret) {
dev_err(&pdev->dev, "PCI memory region reserve error\n");
ret = -ENODEV;
goto bad;
}
mem = pci_iomap(pdev, 0, 0);
if (!mem) {
printk(KERN_ERR "PCI memory map error\n") ;
ret = -EIO;
goto bad1;
}
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
if (hw == NULL) {
printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n");
goto bad2;
}
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
sc = hw->priv;
sc->hw = hw;
sc->dev = &pdev->dev;
sc->mem = mem;
sc->bus_ops = &ath_pci_bus_ops;
if (ath_attach(id->device, sc) != 0) {
ret = -ENODEV;
goto bad3;
}
/* setup interrupt service routine */
if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) {
printk(KERN_ERR "%s: request_irq failed\n",
wiphy_name(hw->wiphy));
ret = -EIO;
goto bad4;
}
sc->irq = pdev->irq;
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, pdev->irq);
return 0;
bad4:
ath_detach(sc);
bad3:
ieee80211_free_hw(hw);
bad2:
pci_iounmap(pdev, mem);
bad1:
pci_release_region(pdev, 0);
bad:
pci_disable_device(pdev);
return ret;
}
static void ath_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
ath_cleanup(sc);
}
#ifdef CONFIG_PM
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
static int ath_pci_resume(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
u32 val;
int err;
err = pci_enable_device(pdev);
if (err)
return err;
pci_restore_state(pdev);
/*
* Suspend/Resume resets the PCI configuration space, so we have to
* re-disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state
*/
pci_read_config_dword(pdev, 0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
/* Enable LED */
ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/*
* check the h/w rfkill state on resume
* and start the rfkill poll timer
*/
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
queue_delayed_work(sc->hw->workqueue,
&sc->rf_kill.rfkill_poll, 0);
#endif
return 0;
}
#endif /* CONFIG_PM */
MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
static struct pci_driver ath_pci_driver = {
.name = "ath9k",
.id_table = ath_pci_id_table,
.probe = ath_pci_probe,
.remove = ath_pci_remove,
#ifdef CONFIG_PM
.suspend = ath_pci_suspend,
.resume = ath_pci_resume,
#endif /* CONFIG_PM */
};
int __init ath_pci_init(void)
{
return pci_register_driver(&ath_pci_driver);
}
void ath_pci_exit(void)
{
pci_unregister_driver(&ath_pci_driver);
}
......@@ -19,7 +19,6 @@
static struct ath_rate_table ar5416_11na_ratetable = {
42,
{0},
{
{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
......@@ -158,7 +157,6 @@ static struct ath_rate_table ar5416_11na_ratetable = {
static struct ath_rate_table ar5416_11ng_ratetable = {
46,
{0},
{
{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
......@@ -306,7 +304,6 @@ static struct ath_rate_table ar5416_11ng_ratetable = {
static struct ath_rate_table ar5416_11a_ratetable = {
8,
{0},
{
{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, (0x80|12),
......@@ -340,7 +337,6 @@ static struct ath_rate_table ar5416_11a_ratetable = {
static struct ath_rate_table ar5416_11g_ratetable = {
12,
{0},
{
{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
......@@ -386,7 +382,6 @@ static struct ath_rate_table ar5416_11g_ratetable = {
static struct ath_rate_table ar5416_11b_ratetable = {
4,
{0},
{
{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, (0x80|2),
......@@ -875,7 +870,7 @@ static void ath_rc_ratefind(struct ath_softc *sc,
* above conditions.
*/
if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
(sc->hw->conf.ht.enabled)) {
(conf_is_ht(&sc->hw->conf))) {
u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
if (i == 4 &&
......@@ -1363,9 +1358,13 @@ static void ath_rc_init(struct ath_softc *sc,
}
if (sta->ht_cap.ht_supported) {
ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG;
if (sc->sc_ah->ah_caps.tx_chainmask != 1)
ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
ath_rc_priv->ht_cap |= WLAN_RC_SGI_FLAG;
}
/* Initial rate table size. Will change depending
......@@ -1511,7 +1510,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
tx_info, &is_probe, false);
/* Check if aggregation has to be enabled for this tid */
if (hw->conf.ht.enabled) {
if (conf_is_ht(&hw->conf)) {
if (ieee80211_is_data_qos(fc)) {
u8 *qc, tid;
struct ath_node *an;
......@@ -1607,16 +1606,8 @@ static void ath_setup_rate_table(struct ath_softc *sc,
{
int i;
for (i = 0; i < 256; i++)
rate_table->rateCodeToIndex[i] = (u8)-1;
for (i = 0; i < rate_table->rate_cnt; i++) {
u8 code = rate_table->info[i].ratecode;
u8 cix = rate_table->info[i].ctrl_rate;
u8 sh = rate_table->info[i].short_preamble;
rate_table->rateCodeToIndex[code] = i;
rate_table->rateCodeToIndex[code | sh] = i;
rate_table->info[i].lpAckDuration =
ath9k_hw_computetxtime(sc->sc_ah, rate_table,
......
......@@ -90,7 +90,6 @@ struct ath_softc;
*/
struct ath_rate_table {
int rate_cnt;
u8 rateCodeToIndex[256];
struct {
int valid;
int valid_single_stream;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2204,9 +2204,6 @@ static int atmel_get_frag(struct net_device *dev,
return 0;
}
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
static int atmel_set_freq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *fwrq,
......@@ -2216,16 +2213,12 @@ static int atmel_set_freq(struct net_device *dev,
int rc = -EINPROGRESS; /* Call commit handler */
/* If setting by frequency, convert to a channel */
if ((fwrq->e == 1) &&
(fwrq->m >= (int) 241200000) &&
(fwrq->m <= (int) 248700000)) {
if (fwrq->e == 1) {
int f = fwrq->m / 100000;
int c = 0;
while ((c < 14) && (f != frequency_list[c]))
c++;
/* Hack to fall through... */
fwrq->e = 0;
fwrq->m = c + 1;
fwrq->m = ieee80211_freq_to_dsss_chan(f);
}
/* Setting by channel number */
if ((fwrq->m > 1000) || (fwrq->e > 0))
......@@ -2384,8 +2377,11 @@ static int atmel_get_range(struct net_device *dev,
if (range->num_channels != 0) {
for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
range->freq[k].i = i; /* List index */
range->freq[k].m = frequency_list[i - 1] * 100000;
range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
/* Values in MHz -> * 10^5 * 10 */
range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) *
100000);
range->freq[k++].e = 1;
}
range->num_frequency = k;
}
......
......@@ -110,10 +110,18 @@ config B43_DEBUG
bool "Broadcom 43xx debugging"
depends on B43
---help---
Broadcom 43xx debugging messages.
Broadcom 43xx debugging.
Say Y, if you want to find out why the driver does not
work for you.
This adds additional runtime sanity checks and statistics to the driver.
These checks and statistics might me expensive and hurt runtime performance
of your system.
This also adds the b43 debugfs interface.
Do not enable this, unless you are debugging the driver.
Say N, if you are a distributor or user building a release kernel
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
config B43_FORCE_PIO
bool "Force usage of PIO instead of DMA"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment