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

This commit is contained in:
David S. Miller
2008-03-11 19:17:18 -07:00
104 changed files with 11003 additions and 3567 deletions
+2 -1
View File
@@ -11,7 +11,8 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
procfs-guide.xml writing_usb_driver.xml networking.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
mac80211.xml
###
# The build process is as follows (targets):
+335
View File
@@ -0,0 +1,335 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="mac80211-developers-guide">
<bookinfo>
<title>The mac80211 subsystem for kernel developers</title>
<authorgroup>
<author>
<firstname>Johannes</firstname>
<surname>Berg</surname>
<affiliation>
<address><email>johannes@sipsolutions.net</email></address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2007</year>
<year>2008</year>
<holder>Johannes Berg</holder>
</copyright>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License version 2 as published by the Free Software Foundation.
</para>
<para>
This documentation is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this documentation; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
<abstract>
!Pinclude/net/mac80211.h Introduction
!Pinclude/net/mac80211.h Warning
</abstract>
</bookinfo>
<toc></toc>
<!--
Generally, this document shall be ordered by increasing complexity.
It is important to note that readers should be able to read only
the first few sections to get a working driver and only advanced
usage should require reading the full document.
-->
<part>
<title>The basic mac80211 driver interface</title>
<partintro>
<para>
You should read and understand the information contained
within this part of the book while implementing a driver.
In some chapters, advanced usage is noted, that may be
skipped at first.
</para>
<para>
This part of the book only covers station and monitor mode
functionality, additional information required to implement
the other modes is covered in the second part of the book.
</para>
</partintro>
<chapter id="basics">
<title>Basic hardware handling</title>
<para>TBD</para>
<para>
This chapter shall contain information on getting a hw
struct allocated and registered with mac80211.
</para>
<para>
Since it is required to allocate rates/modes before registering
a hw struct, this chapter shall also contain information on setting
up the rate/mode structs.
</para>
<para>
Additionally, some discussion about the callbacks and
the general programming model should be in here, including
the definition of ieee80211_ops which will be referred to
a lot.
</para>
<para>
Finally, a discussion of hardware capabilities should be done
with references to other parts of the book.
</para>
<!-- intentionally multiple !F lines to get proper order -->
!Finclude/net/mac80211.h ieee80211_hw
!Finclude/net/mac80211.h ieee80211_hw_flags
!Finclude/net/mac80211.h SET_IEEE80211_DEV
!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
!Finclude/net/mac80211.h ieee80211_ops
!Finclude/net/mac80211.h ieee80211_alloc_hw
!Finclude/net/mac80211.h ieee80211_register_hw
!Finclude/net/mac80211.h ieee80211_get_tx_led_name
!Finclude/net/mac80211.h ieee80211_get_rx_led_name
!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
!Finclude/net/mac80211.h ieee80211_get_radio_led_name
!Finclude/net/mac80211.h ieee80211_unregister_hw
!Finclude/net/mac80211.h ieee80211_free_hw
</chapter>
<chapter id="phy-handling">
<title>PHY configuration</title>
<para>TBD</para>
<para>
This chapter should describe PHY handling including
start/stop callbacks and the various structures used.
</para>
!Finclude/net/mac80211.h ieee80211_conf
!Finclude/net/mac80211.h ieee80211_conf_flags
</chapter>
<chapter id="iface-handling">
<title>Virtual interfaces</title>
<para>TBD</para>
<para>
This chapter should describe virtual interface basics
that are relevant to the driver (VLANs, MGMT etc are not.)
It should explain the use of the add_iface/remove_iface
callbacks as well as the interface configuration callbacks.
</para>
<para>Things related to AP mode should be discussed there.</para>
<para>
Things related to supporting multiple interfaces should be
in the appropriate chapter, a BIG FAT note should be here about
this though and the recommendation to allow only a single
interface in STA mode at first!
</para>
!Finclude/net/mac80211.h ieee80211_if_types
!Finclude/net/mac80211.h ieee80211_if_init_conf
!Finclude/net/mac80211.h ieee80211_if_conf
</chapter>
<chapter id="rx-tx">
<title>Receive and transmit processing</title>
<sect1>
<title>what should be here</title>
<para>TBD</para>
<para>
This should describe the receive and transmit
paths in mac80211/the drivers as well as
transmit status handling.
</para>
</sect1>
<sect1>
<title>Frame format</title>
!Pinclude/net/mac80211.h Frame format
</sect1>
<sect1>
<title>Alignment issues</title>
<para>TBD</para>
</sect1>
<sect1>
<title>Calling into mac80211 from interrupts</title>
!Pinclude/net/mac80211.h Calling mac80211 from interrupts
</sect1>
<sect1>
<title>functions/definitions</title>
!Finclude/net/mac80211.h ieee80211_rx_status
!Finclude/net/mac80211.h mac80211_rx_flags
!Finclude/net/mac80211.h ieee80211_tx_control
!Finclude/net/mac80211.h ieee80211_tx_status_flags
!Finclude/net/mac80211.h ieee80211_rx
!Finclude/net/mac80211.h ieee80211_rx_irqsafe
!Finclude/net/mac80211.h ieee80211_tx_status
!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
!Finclude/net/mac80211.h ieee80211_rts_get
!Finclude/net/mac80211.h ieee80211_rts_duration
!Finclude/net/mac80211.h ieee80211_ctstoself_get
!Finclude/net/mac80211.h ieee80211_ctstoself_duration
!Finclude/net/mac80211.h ieee80211_generic_frame_duration
!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
!Finclude/net/mac80211.h ieee80211_get_hdrlen
!Finclude/net/mac80211.h ieee80211_wake_queue
!Finclude/net/mac80211.h ieee80211_stop_queue
!Finclude/net/mac80211.h ieee80211_start_queues
!Finclude/net/mac80211.h ieee80211_stop_queues
!Finclude/net/mac80211.h ieee80211_wake_queues
</sect1>
</chapter>
<chapter id="filters">
<title>Frame filtering</title>
!Pinclude/net/mac80211.h Frame filtering
!Finclude/net/mac80211.h ieee80211_filter_flags
</chapter>
</part>
<part id="advanced">
<title>Advanced driver interface</title>
<partintro>
<para>
Information contained within this part of the book is
of interest only for advanced interaction of mac80211
with drivers to exploit more hardware capabilities and
improve performance.
</para>
</partintro>
<chapter id="hardware-crypto-offload">
<title>Hardware crypto acceleration</title>
!Pinclude/net/mac80211.h Hardware crypto acceleration
<!-- intentionally multiple !F lines to get proper order -->
!Finclude/net/mac80211.h set_key_cmd
!Finclude/net/mac80211.h ieee80211_key_conf
!Finclude/net/mac80211.h ieee80211_key_alg
!Finclude/net/mac80211.h ieee80211_key_flags
</chapter>
<chapter id="qos">
<title>Multiple queues and QoS support</title>
<para>TBD</para>
!Finclude/net/mac80211.h ieee80211_tx_queue_params
!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data
!Finclude/net/mac80211.h ieee80211_tx_queue
</chapter>
<chapter id="AP">
<title>Access point mode support</title>
<para>TBD</para>
<para>Some parts of the if_conf should be discussed here instead</para>
<para>
Insert notes about VLAN interfaces with hw crypto here or
in the hw crypto chapter.
</para>
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
!Finclude/net/mac80211.h ieee80211_beacon_get
</chapter>
<chapter id="multi-iface">
<title>Supporting multiple virtual interfaces</title>
<para>TBD</para>
<para>
Note: WDS with identical MAC address should almost always be OK
</para>
<para>
Insert notes about having multiple virtual interfaces with
different MAC addresses here, note which configurations are
supported by mac80211, add notes about supporting hw crypto
with it.
</para>
</chapter>
<chapter id="hardware-scan-offload">
<title>Hardware scan offload</title>
<para>TBD</para>
!Finclude/net/mac80211.h ieee80211_scan_completed
</chapter>
</part>
<part id="rate-control">
<title>Rate control interface</title>
<partintro>
<para>TBD</para>
<para>
This part of the book describes the rate control algorithm
interface and how it relates to mac80211 and drivers.
</para>
</partintro>
<chapter id="dummy">
<title>dummy chapter</title>
<para>TBD</para>
</chapter>
</part>
<part id="internal">
<title>Internals</title>
<partintro>
<para>TBD</para>
<para>
This part of the book describes mac80211 internals.
</para>
</partintro>
<chapter id="key-handling">
<title>Key handling</title>
<sect1>
<title>Key handling basics</title>
!Pnet/mac80211/key.c Key handling basics
</sect1>
<sect1>
<title>MORE TBD</title>
<para>TBD</para>
</sect1>
</chapter>
<chapter id="rx-processing">
<title>Receive processing</title>
<para>TBD</para>
</chapter>
<chapter id="tx-processing">
<title>Transmit processing</title>
<para>TBD</para>
</chapter>
<chapter id="sta-info">
<title>Station info handling</title>
<sect1>
<title>Programming information</title>
!Fnet/mac80211/sta_info.h sta_info
!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
</sect1>
<sect1>
<title>STA information lifetime rules</title>
!Pnet/mac80211/sta_info.c STA information lifetime rules
</sect1>
</chapter>
<chapter id="synchronisation">
<title>Synchronisation</title>
<para>TBD</para>
<para>Locking, lots of RCU</para>
</chapter>
</part>
</book>
+27 -26
View File
@@ -140,7 +140,8 @@ enum ath5k_radio {
AR5K_RF5110 = 0,
AR5K_RF5111 = 1,
AR5K_RF5112 = 2,
AR5K_RF5413 = 3,
AR5K_RF2413 = 3,
AR5K_RF5413 = 4,
};
/*
@@ -168,12 +169,15 @@ struct ath5k_srev_name {
#define AR5K_SREV_VER_AR5212 0x50
#define AR5K_SREV_VER_AR5213 0x55
#define AR5K_SREV_VER_AR5213A 0x59
#define AR5K_SREV_VER_AR2424 0xa0
#define AR5K_SREV_VER_AR5424 0xa3
#define AR5K_SREV_VER_AR2413 0x78
#define AR5K_SREV_VER_AR2414 0x79
#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */
#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */
#define AR5K_SREV_VER_AR5413 0xa4
#define AR5K_SREV_VER_AR5414 0xa5
#define AR5K_SREV_VER_AR5416 0xc0 /* ? */
#define AR5K_SREV_VER_AR5418 0xca
#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */
#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */
#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */
#define AR5K_SREV_RAD_5110 0x00
#define AR5K_SREV_RAD_5111 0x10
@@ -183,8 +187,9 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_5112A 0x35
#define AR5K_SREV_RAD_2112 0x40
#define AR5K_SREV_RAD_2112A 0x45
#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */
#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */
#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
/* IEEE defs */
@@ -268,12 +273,13 @@ enum ath5k_driver_mode {
#define SHPREAMBLE_FLAG(_ix) \
(HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
/****************\
TX DEFINITIONS
\****************/
/*
* Tx Descriptor
* TX Status
*/
struct ath5k_tx_status {
u16 ts_seqnum;
@@ -421,7 +427,7 @@ enum ath5k_dmasize {
\****************/
/*
* Rx Descriptor
* RX Status
*/
struct ath5k_rx_status {
u16 rs_datalen;
@@ -452,8 +458,6 @@ struct ath5k_mib_stats {
};
/**************************\
BEACON TIMERS DEFINITIONS
\**************************/
@@ -495,29 +499,23 @@ struct ath5k_beacon_state {
#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
/********************\
COMMON DEFINITIONS
\********************/
/*
* Atheros descriptor
* Atheros hardware descriptor
* This is read and written to by the hardware
*/
struct ath5k_desc {
u32 ds_link;
u32 ds_data;
u32 ds_ctl0;
u32 ds_ctl1;
u32 ds_hw[4];
u32 ds_link; /* physical address of the next descriptor */
u32 ds_data; /* physical address of data buffer (skb) */
union {
struct ath5k_rx_status rx;
struct ath5k_tx_status tx;
} ds_us;
#define ds_rxstat ds_us.rx
#define ds_txstat ds_us.tx
struct ath5k_hw_5210_tx_desc ds_tx5210;
struct ath5k_hw_5212_tx_desc ds_tx5212;
struct ath5k_hw_all_rx_desc ds_rx;
} ud;
} __packed;
#define AR5K_RXDESC_INTREQ 0x0020
@@ -961,6 +959,7 @@ struct ath5k_hw {
u16 ah_phy_revision;
u16 ah_radio_5ghz_revision;
u16 ah_radio_2ghz_revision;
u32 ah_phy_spending;
enum ath5k_version ah_version;
enum ath5k_radio ah_radio;
@@ -1036,8 +1035,10 @@ struct ath5k_hw {
int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
unsigned int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int);
int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
struct ath5k_tx_status *);
int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
struct ath5k_rx_status *);
};
/*
+94 -53
View File
@@ -118,6 +118,8 @@ static struct ath5k_srev_name srev_names[] = {
{ "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
{ "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
{ "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
{ "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 },
{ "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 },
{ "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
{ "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
{ "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
@@ -132,6 +134,7 @@ static struct ath5k_srev_name srev_names[] = {
{ "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
{ "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
{ "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
{ "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 },
{ "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
{ "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
@@ -280,7 +283,8 @@ static int ath5k_rx_start(struct ath5k_softc *sc);
static void ath5k_rx_stop(struct ath5k_softc *sc);
static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
struct ath5k_desc *ds,
struct sk_buff *skb);
struct sk_buff *skb,
struct ath5k_rx_status *rs);
static void ath5k_tasklet_rx(unsigned long data);
/* Tx handling */
static void ath5k_tx_processq(struct ath5k_softc *sc,
@@ -1560,8 +1564,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
*/
spin_lock_bh(&txq->lock);
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
bf->desc));
ath5k_debug_printtxbuf(sc, bf);
ath5k_txbuf_free(sc, bf);
@@ -1686,20 +1689,20 @@ ath5k_rx_stop(struct ath5k_softc *sc)
static unsigned int
ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
struct sk_buff *skb)
struct sk_buff *skb, struct ath5k_rx_status *rs)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
rs->rs_keyix != AR5K_RXKEYIX_INVALID)
return RX_FLAG_DECRYPTED;
/* Apparently when a default key is used to decrypt the packet
the hw does not set the index used to decrypt. In such cases
get the index from the packet. */
if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
skb->len >= hlen + 4) {
keyix = skb->data[hlen + 3] >> 6;
@@ -1712,8 +1715,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
static void
ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
struct ieee80211_rx_status *rxs)
{
u64 tsf, bc_tstamp;
u32 hw_tu;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -1724,16 +1729,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
/*
* Received an IBSS beacon with the same BSSID. Hardware might
* have updated the TSF, check if we need to update timers.
* Received an IBSS beacon with the same BSSID. Hardware *must*
* have updated the local TSF. We have to work around various
* hardware bugs, though...
*/
hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
if (hw_tu >= sc->nexttbtt) {
ath5k_beacon_update_timers(sc,
le64_to_cpu(mgmt->u.beacon.timestamp));
tsf = ath5k_hw_get_tsf64(sc->ah);
bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
hw_tu = TSF_TO_TU(tsf);
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
"beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
bc_tstamp, rxs->mactime,
(rxs->mactime - bc_tstamp), tsf);
/*
* Sometimes the HW will give us a wrong tstamp in the rx
* status, causing the timestamp extension to go wrong.
* (This seems to happen especially with beacon frames bigger
* than 78 byte (incl. FCS))
* But we know that the receive timestamp must be later than the
* timestamp of the beacon since HW must have synced to that.
*
* NOTE: here we assume mactime to be after the frame was
* received, not like mac80211 which defines it at the start.
*/
if (bc_tstamp > rxs->mactime) {
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
"detected HW merge from received beacon\n");
"fixing mactime from %llx to %llx\n",
rxs->mactime, tsf);
rxs->mactime = tsf;
}
/*
* Local TSF might have moved higher than our beacon timers,
* in that case we have to update them to continue sending
* beacons. This also takes care of synchronizing beacon sending
* times with other stations.
*/
if (hw_tu >= sc->nexttbtt)
ath5k_beacon_update_timers(sc, bc_tstamp);
}
}
@@ -1742,12 +1776,11 @@ static void
ath5k_tasklet_rx(unsigned long data)
{
struct ieee80211_rx_status rxs = {};
struct ath5k_rx_status rs = {};
struct sk_buff *skb;
struct ath5k_softc *sc = (void *)data;
struct ath5k_buf *bf;
struct ath5k_desc *ds;
u16 len;
u8 stat;
int ret;
int hdrlen;
int pad;
@@ -1770,7 +1803,7 @@ ath5k_tasklet_rx(unsigned long data)
if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
break;
ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
@@ -1779,16 +1812,15 @@ ath5k_tasklet_rx(unsigned long data)
return;
}
if (unlikely(ds->ds_rxstat.rs_more)) {
if (unlikely(rs.rs_more)) {
ATH5K_WARN(sc, "unsupported jumbo\n");
goto next;
}
stat = ds->ds_rxstat.rs_status;
if (unlikely(stat)) {
if (stat & AR5K_RXERR_PHY)
if (unlikely(rs.rs_status)) {
if (rs.rs_status & AR5K_RXERR_PHY)
goto next;
if (stat & AR5K_RXERR_DECRYPT) {
if (rs.rs_status & AR5K_RXERR_DECRYPT) {
/*
* Decrypt error. If the error occurred
* because there was no hardware key, then
@@ -1799,30 +1831,29 @@ ath5k_tasklet_rx(unsigned long data)
*
* XXX do key cache faulting
*/
if (ds->ds_rxstat.rs_keyix ==
AR5K_RXKEYIX_INVALID &&
!(stat & AR5K_RXERR_CRC))
if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
!(rs.rs_status & AR5K_RXERR_CRC))
goto accept;
}
if (stat & AR5K_RXERR_MIC) {
if (rs.rs_status & AR5K_RXERR_MIC) {
rxs.flag |= RX_FLAG_MMIC_ERROR;
goto accept;
}
/* let crypto-error packets fall through in MNTR */
if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
if ((rs.rs_status &
~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
sc->opmode != IEEE80211_IF_TYPE_MNTR)
goto next;
}
accept:
len = ds->ds_rxstat.rs_datalen;
pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
PCI_DMA_FROMDEVICE);
pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
rs.rs_datalen, PCI_DMA_FROMDEVICE);
pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
PCI_DMA_FROMDEVICE);
bf->skb = NULL;
skb_put(skb, len);
skb_put(skb, rs.rs_datalen);
/*
* the hardware adds a padding to 4 byte boundaries between
@@ -1844,8 +1875,19 @@ accept:
* 15bit only. that means TSF extension has to be done within
* 32768usec (about 32ms). it might be necessary to move this to
* the interrupt handler, like it is done in madwifi.
*
* Unfortunately we don't know when the hardware takes the rx
* timestamp (beginning of phy frame, data frame, end of rx?).
* The only thing we know is that it is hardware specific...
* On AR5213 it seems the rx timestamp is at the end of the
* frame, but i'm not sure.
*
* NOTE: mac80211 defines mactime at the beginning of the first
* data symbol. Since we don't have any time references it's
* impossible to comply to that. This affects IBSS merge only
* right now, so it's not too bad...
*/
rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
rxs.flag |= RX_FLAG_TSFT;
rxs.freq = sc->curchan->center_freq;
@@ -1859,26 +1901,25 @@ accept:
/* noise floor in dBm, from the last noise calibration */
rxs.noise = sc->ah->ah_noise_floor;
/* signal level in dBm */
rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
rxs.ssi = rxs.noise + rs.rs_rssi;
/*
* "signal" is actually displayed as Link Quality by iwconfig
* we provide a percentage based on rssi (assuming max rssi 64)
*/
rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
rxs.signal = rs.rs_rssi * 100 / 64;
rxs.antenna = ds->ds_rxstat.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc,
ds->ds_rxstat.rs_rate);
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
rxs.antenna = rs.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
ath5k_debug_dump_skb(sc, skb, "RX ", 0);
/* check beacons in IBSS mode */
if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
ath5k_check_ibss_hw_merge(sc, skb);
ath5k_check_ibss_tsf(sc, skb, &rxs);
__ieee80211_rx(sc->hw, skb, &rxs);
sc->led_rxrate = ds->ds_rxstat.rs_rate;
sc->led_rxrate = rs.rs_rate;
ath5k_led_event(sc, ATH_LED_RX);
next:
list_move_tail(&bf->list, &sc->rxbuf);
@@ -1897,6 +1938,7 @@ static void
ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
{
struct ieee80211_tx_status txs = {};
struct ath5k_tx_status ts = {};
struct ath5k_buf *bf, *bf0;
struct ath5k_desc *ds;
struct sk_buff *skb;
@@ -1909,7 +1951,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
/* TODO only one segment */
pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
sc->desc_len, PCI_DMA_FROMDEVICE);
ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
if (unlikely(ret == -EINPROGRESS))
break;
else if (unlikely(ret)) {
@@ -1924,17 +1966,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
PCI_DMA_TODEVICE);
txs.control = bf->ctl;
txs.retry_count = ds->ds_txstat.ts_shortretry +
ds->ds_txstat.ts_longretry / 6;
if (unlikely(ds->ds_txstat.ts_status)) {
txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
if (ts.ts_status & AR5K_TXERR_XRETRY)
txs.excessive_retries = 1;
else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
else if (ts.ts_status & AR5K_TXERR_FILT)
txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
} else {
txs.flags |= IEEE80211_TX_STATUS_ACK;
txs.ack_signal = ds->ds_txstat.ts_rssi;
txs.ack_signal = ts.ts_rssi;
}
ieee80211_tx_status(sc->hw, skb, &txs);
@@ -2108,7 +2149,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* beacon timer registers.
*
* This is called in a variety of situations, e.g. when a beacon is received,
* when a HW merge has been detected, but also when an new IBSS is created or
* when a TSF update has been detected, but also when an new IBSS is created or
* when we otherwise know we have to update the timers, but we keep it in this
* function to have it all together in one place.
*/
@@ -2208,7 +2249,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* another AP to associate with.
*
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
* interrupts to detect HW merges only.
* interrupts to detect TSF updates only.
*
* AP mode is missing.
*/
@@ -2228,7 +2269,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
* hardware send the beacons automatically. We have to load it
* only once here.
* We use the SWBA interrupt only to keep track of the beacon
* timers in order to detect HW merges (automatic TSF updates).
* timers in order to detect automatic TSF updates.
*/
ath5k_beaconq_config(sc);
@@ -2441,8 +2482,8 @@ ath5k_intr(int irq, void *dev_id)
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
* transmission time) in order to detect hardware
* merges (TSF updates).
* transmission time) in order to detect wether
* automatic TSF updates happened.
*/
if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
/* XXX: only if VEOL suppported */
+24 -13
View File
@@ -200,7 +200,8 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
{
struct ath5k_softc *sc = file->private_data;
char buf[100];
snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
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);
}
@@ -271,7 +272,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
tsf = ath5k_hw_get_tsf64(sc->ah);
len += snprintf(buf+len, sizeof(buf)-len,
"TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf));
"TSF\t\t0x%016llx\tTU: %08x\n",
(unsigned long long)tsf, TSF_TO_TU(tsf));
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -497,15 +499,18 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc)
}
static inline void
ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
struct ath5k_rx_status *rs)
{
struct ath5k_desc *ds = bf->desc;
struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
ds, (unsigned long long)bf->daddr,
ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
ds->ds_hw[0], ds->ds_hw[1],
!done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
ds->ds_link, ds->ds_data,
rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
!done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
}
void
@@ -513,6 +518,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
{
struct ath5k_desc *ds;
struct ath5k_buf *bf;
struct ath5k_rx_status rs = {};
int status;
if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
@@ -524,9 +530,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
spin_lock_bh(&sc->rxbuflock);
list_for_each_entry(bf, &sc->rxbuf, list) {
ds = bf->desc;
status = ah->ah_proc_rx_desc(ah, ds);
status = ah->ah_proc_rx_desc(ah, ds, &rs);
if (!status)
ath5k_debug_printrxbuf(bf, status == 0);
ath5k_debug_printrxbuf(bf, status == 0, &rs);
}
spin_unlock_bh(&sc->rxbuflock);
}
@@ -550,19 +556,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
}
void
ath5k_debug_printtxbuf(struct ath5k_softc *sc,
struct ath5k_buf *bf, int done)
ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
{
struct ath5k_desc *ds = bf->desc;
struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
struct ath5k_tx_status ts = {};
int done;
if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
return;
done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
"%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
!done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
}
#endif /* ifdef CONFIG_ATH5K_DEBUG */
+2 -4
View File
@@ -160,8 +160,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
struct sk_buff *skb, const char *prefix, int tx);
void
ath5k_debug_printtxbuf(struct ath5k_softc *sc,
struct ath5k_buf *bf, int done);
ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
#else /* no debugging */
@@ -199,8 +198,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc,
struct sk_buff *skb, const char *prefix, int tx) {}
static inline void
ath5k_debug_printtxbuf(struct ath5k_softc *sc,
struct ath5k_buf *bf, int done) {}
ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
#endif /* ifdef CONFIG_ATH5K_DEBUG */
File diff suppressed because it is too large Load Diff
+89 -61
View File
@@ -173,7 +173,10 @@ struct ath5k_eeprom_info {
* (rX: reserved fields possibily used by future versions of the ar5k chipset)
*/
struct ath5k_rx_desc {
/*
* common hardware RX control descriptor
*/
struct ath5k_hw_rx_ctl {
u32 rx_control_0; /* RX control word 0 */
#define AR5K_DESC_RX_CTL0 0x00000000
@@ -185,69 +188,63 @@ struct ath5k_rx_desc {
} __packed;
/*
* 5210/5211 rx status descriptor
* common hardware RX status descriptor
* 5210/11 and 5212 differ only in the flags defined below
*/
struct ath5k_hw_old_rx_status {
struct ath5k_hw_rx_status {
u32 rx_status_0; /* RX status word 0 */
#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
u32 rx_status_1; /* RX status word 1 */
#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004
#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5
#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
} __packed;
/* 5210/5211 */
#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
/* 5212 */
#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
/*
* 5212 rx status descriptor
* common hardware RX error descriptor
*/
struct ath5k_hw_new_rx_status {
u32 rx_status_0; /* RX status word 0 */
#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff
#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000
#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
u32 rx_status_1; /* RX status word 1 */
#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001
#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004
#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010
#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020
#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9
#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
} __packed;
struct ath5k_hw_rx_error {
u32 rx_error_0; /* RX error word 0 */
@@ -268,7 +265,10 @@ struct ath5k_hw_rx_error {
#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
struct ath5k_hw_2w_tx_desc {
/*
* 5210/5211 hardware 2-word TX control descriptor
*/
struct ath5k_hw_2w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */
#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
@@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc {
#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
/*
* 5212 4-word tx control descriptor
* 5212 hardware 4-word TX control descriptor
*/
struct ath5k_hw_4w_tx_desc {
struct ath5k_hw_4w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */
#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
@@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc {
} __packed;
/*
* Common tx status descriptor
* Common TX status descriptor
*/
struct ath5k_hw_tx_status {
u32 tx_status_0; /* TX status word 0 */
@@ -414,6 +414,34 @@ struct ath5k_hw_tx_status {
} __packed;
/*
* 5210/5211 hardware TX descriptor
*/
struct ath5k_hw_5210_tx_desc {
struct ath5k_hw_2w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat;
} __packed;
/*
* 5212 hardware TX descriptor
*/
struct ath5k_hw_5212_tx_desc {
struct ath5k_hw_4w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat;
} __packed;
/*
* common hardware RX descriptor
*/
struct ath5k_hw_all_rx_desc {
struct ath5k_hw_rx_ctl rx_ctl;
union {
struct ath5k_hw_rx_status rx_stat;
struct ath5k_hw_rx_error rx_err;
} u;
} __packed;
/*
* AR5K REGISTER ACCESS
*/
+231 -2
View File
@@ -678,8 +678,8 @@ static const struct ath5k_ini ar5212_ini[] = {
{ AR5K_PHY(644), 0x00806333 },
{ AR5K_PHY(645), 0x00106c10 },
{ AR5K_PHY(646), 0x009c4060 },
/*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
{ AR5K_PHY(647), 0x1483800a },
/* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */
{ AR5K_PHY(648), 0x01831061 },
{ AR5K_PHY(649), 0x00000400 },
/*{ AR5K_PHY(650), 0x000001b5 },*/
@@ -1081,6 +1081,207 @@ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
{ 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
};
/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
* minor tweaking based on dumps from other chips */
static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
{ AR5K_TXCFG,
/* b g gTurbo */
{ 0x00000015, 0x00000015, 0x00000015 } },
{ AR5K_USEC_5211,
{ 0x04e01395, 0x12e013ab, 0x098813cf } },
{ AR5K_PHY(10),
{ 0x05020000, 0x0a020001, 0x0a020001 } },
{ AR5K_PHY(13),
{ 0x00000e00, 0x00000e00, 0x00000e00 } },
{ AR5K_PHY(14),
{ 0x0000000a, 0x0000000a, 0x0000000a } },
{ AR5K_PHY(18),
{ 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
{ AR5K_PHY(20),
{ 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } },
{ AR5K_PHY_SIG,
{ 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } },
{ AR5K_PHY_AGCCOARSE,
{ 0x3137665e, 0x3139605e, 0x3139605e } },
{ AR5K_PHY(27),
{ 0x050cb081, 0x050cb081, 0x050cb081 } },
{ AR5K_PHY_RX_DELAY,
{ 0x0000044c, 0x00000898, 0x000007d0 } },
{ AR5K_PHY_FRAME_CTL_5211,
{ 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
{ AR5K_PHY_CCKTXCTL,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY(642),
{ 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
{ AR5K_PHY_GAIN_2GHZ,
{ 0x0042c140, 0x0042c140, 0x0042c140 } },
{ 0xa21c,
{ 0x1863800a, 0x1883800a, 0x1883800a } },
{ AR5K_DCU_FP,
{ 0x000003e0, 0x000003e0, 0x000003e0 } },
{ 0x8060,
{ 0x0000000f, 0x0000000f, 0x0000000f } },
{ 0x8118,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x811c,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8120,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8124,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8128,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x812c,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8130,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8134,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8138,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x813c,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0x8140,
{ 0x800000a8, 0x800000a8, 0x800000a8 } },
{ 0x8144,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY_AGC,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY(11),
{ 0x0000a000, 0x0000a000, 0x0000a000 } },
{ AR5K_PHY(15),
{ 0x00200400, 0x00200400, 0x00200400 } },
{ AR5K_PHY(19),
{ 0x1284233c, 0x1284233c, 0x1284233c } },
{ AR5K_PHY_SCR,
{ 0x0000001f, 0x0000001f, 0x0000001f } },
{ AR5K_PHY_SLMT,
{ 0x00000080, 0x00000080, 0x00000080 } },
{ AR5K_PHY_SCAL,
{ 0x0000000e, 0x0000000e, 0x0000000e } },
{ AR5K_PHY(86),
{ 0x000000ff, 0x000000ff, 0x000000ff } },
{ AR5K_PHY(96),
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY(97),
{ 0x02800000, 0x02800000, 0x02800000 } },
{ AR5K_PHY(104),
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY(120),
{ 0x00000000, 0x00000000, 0x00000000 } },
{ AR5K_PHY(121),
{ 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
{ AR5K_PHY(122),
{ 0x3c466478, 0x3c466478, 0x3c466478 } },
{ AR5K_PHY(123),
{ 0x000000aa, 0x000000aa, 0x000000aa } },
{ AR5K_PHY_SCLOCK,
{ 0x0000000c, 0x0000000c, 0x0000000c } },
{ AR5K_PHY_SDELAY,
{ 0x000000ff, 0x000000ff, 0x000000ff } },
{ AR5K_PHY_SPENDING,
{ 0x00000014, 0x00000014, 0x00000014 } },
{ 0xa228,
{ 0x000009b5, 0x000009b5, 0x000009b5 } },
{ 0xa23c,
{ 0x93c889af, 0x93c889af, 0x93c889af } },
{ 0xa24c,
{ 0x00000001, 0x00000001, 0x00000001 } },
{ 0xa250,
{ 0x0000a000, 0x0000a000, 0x0000a000 } },
{ 0xa254,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa258,
{ 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
{ 0xa25c,
{ 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
{ 0xa260,
{ 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
{ 0xa264,
{ 0x00418a11, 0x00418a11, 0x00418a11 } },
{ 0xa268,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa26c,
{ 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
{ 0xa270,
{ 0x00820820, 0x00820820, 0x00820820 } },
{ 0xa274,
{ 0x001b7caa, 0x001b7caa, 0x001b7caa } },
{ 0xa278,
{ 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
{ 0xa27c,
{ 0x051701ce, 0x051701ce, 0x051701ce } },
{ 0xa300,
{ 0x18010000, 0x18010000, 0x18010000 } },
{ 0xa304,
{ 0x30032602, 0x30032602, 0x30032602 } },
{ 0xa308,
{ 0x48073e06, 0x48073e06, 0x48073e06 } },
{ 0xa30c,
{ 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
{ 0xa310,
{ 0x641a600f, 0x641a600f, 0x641a600f } },
{ 0xa314,
{ 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
{ 0xa318,
{ 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
{ 0xa31c,
{ 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
{ 0xa320,
{ 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } },
{ 0xa324,
{ 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } },
{ 0xa328,
{ 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } },
{ 0xa32c,
{ 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } },
{ 0xa330,
{ 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } },
{ 0xa334,
{ 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } },
{ 0xa338,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa33c,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa340,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa344,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 0xa348,
{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
{ 0xa34c,
{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
{ 0xa350,
{ 0x3fffffff, 0x3fffffff, 0x3fffffff } },
{ 0xa354,
{ 0x0003ffff, 0x0003ffff, 0x0003ffff } },
{ 0xa358,
{ 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
{ 0xa35c,
{ 0x066c420f, 0x066c420f, 0x066c420f } },
{ 0xa360,
{ 0x0f282207, 0x0f282207, 0x0f282207 } },
{ 0xa364,
{ 0x17601685, 0x17601685, 0x17601685 } },
{ 0xa368,
{ 0x1f801104, 0x1f801104, 0x1f801104 } },
{ 0xa36c,
{ 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
{ 0xa370,
{ 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
{ 0xa374,
{ 0x57c00803, 0x57c00803, 0x57c00803 } },
{ 0xa378,
{ 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
{ 0xa37c,
{ 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
{ 0xa380,
{ 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
{ 0xa384,
{ 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
};
/*
* Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
* RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
@@ -1290,29 +1491,57 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
/* Second set of mode-specific settings */
if (ah->ah_radio == AR5K_RF5111){
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
ar5212_rf5111_ini_mode_end, mode);
/* Baseband gain table */
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5111_ini_bbgain),
rf5111_ini_bbgain, change_channel);
} else if (ah->ah_radio == AR5K_RF5112){
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
ar5212_rf5112_ini_mode_end, mode);
/* Baseband gain table */
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
rf5112_ini_bbgain, change_channel);
} else if (ah->ah_radio == AR5K_RF5413){
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(rf5413_ini_mode_end),
rf5413_ini_mode_end, mode);
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
rf5112_ini_bbgain, change_channel);
} else if (ah->ah_radio == AR5K_RF2413) {
if (mode < 2) {
ATH5K_ERR(ah->ah_sc,
"unsupported channel mode: %d\n", mode);
return -EINVAL;
}
mode = mode - 2;
/* Override a setting from ar5212_ini */
ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(rf2413_ini_mode_end),
rf2413_ini_mode_end, mode);
/* Baseband gain table */
ath5k_hw_ini_registers(ah,
ARRAY_SIZE(rf5112_ini_bbgain),
rf5112_ini_bbgain, change_channel);
}
/* For AR5211 */
} else if (ah->ah_version == AR5K_AR5211) {
+170 -4
View File
@@ -666,6 +666,75 @@ static const struct ath5k_ini_rf rfregs_5413[] = {
{ 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
};
/* RF2413/2414 mode-specific init registers */
static const struct ath5k_ini_rf rfregs_2413[] = {
{ 1, AR5K_RF_BUFFER_CONTROL_4,
{ 0x00000020, 0x00000020, 0x00000020 } },
{ 2, AR5K_RF_BUFFER_CONTROL_3,
{ 0x02001408, 0x02001408, 0x02001408 } },
{ 3, AR5K_RF_BUFFER_CONTROL_6,
{ 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
{ 6, AR5K_RF_BUFFER,
{ 0xf0000000, 0xf0000000, 0xf0000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x03000000, 0x03000000, 0x03000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x40400000, 0x40400000, 0x40400000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x65050000, 0x65050000, 0x65050000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00420000, 0x00420000, 0x00420000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00b50000, 0x00b50000, 0x00b50000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00030000, 0x00030000, 0x00030000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00f70000, 0x00f70000, 0x00f70000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x009d0000, 0x009d0000, 0x009d0000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00220000, 0x00220000, 0x00220000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x04220000, 0x04220000, 0x04220000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00230018, 0x00230018, 0x00230018 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00280050, 0x00280050, 0x00280050 } },
{ 6, AR5K_RF_BUFFER,
{ 0x005000c3, 0x005000c3, 0x005000c3 } },
{ 6, AR5K_RF_BUFFER,
{ 0x0004007f, 0x0004007f, 0x0004007f } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000458, 0x00000458, 0x00000458 } },
{ 6, AR5K_RF_BUFFER,
{ 0x00000000, 0x00000000, 0x00000000 } },
{ 6, AR5K_RF_BUFFER,
{ 0x0000c000, 0x0000c000, 0x0000c000 } },
{ 6, AR5K_RF_BUFFER_CONTROL_5,
{ 0x00400230, 0x00400230, 0x00400230 } },
{ 7, AR5K_RF_BUFFER,
{ 0x00006400, 0x00006400, 0x00006400 } },
{ 7, AR5K_RF_BUFFER,
{ 0x00000800, 0x00000800, 0x00000800 } },
{ 7, AR5K_RF_BUFFER_CONTROL_2,
{ 0x0000000e, 0x0000000e, 0x0000000e } },
};
/* Initial RF Gain settings for RF5112 */
static const struct ath5k_ini_rfgain rfgain_5112[] = {
@@ -805,6 +874,74 @@ static const struct ath5k_ini_rfgain rfgain_5413[] = {
{ AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
};
/* Initial RF Gain settings for RF2413 */
static const struct ath5k_ini_rfgain rfgain_2413[] = {
{ AR5K_RF_GAIN(0), { 0x00000000 } },
{ AR5K_RF_GAIN(1), { 0x00000040 } },
{ AR5K_RF_GAIN(2), { 0x00000080 } },
{ AR5K_RF_GAIN(3), { 0x00000181 } },
{ AR5K_RF_GAIN(4), { 0x000001c1 } },
{ AR5K_RF_GAIN(5), { 0x00000001 } },
{ AR5K_RF_GAIN(6), { 0x00000041 } },
{ AR5K_RF_GAIN(7), { 0x00000081 } },
{ AR5K_RF_GAIN(8), { 0x00000168 } },
{ AR5K_RF_GAIN(9), { 0x000001a8 } },
{ AR5K_RF_GAIN(10), { 0x000001e8 } },
{ AR5K_RF_GAIN(11), { 0x00000028 } },
{ AR5K_RF_GAIN(12), { 0x00000068 } },
{ AR5K_RF_GAIN(13), { 0x00000189 } },
{ AR5K_RF_GAIN(14), { 0x000001c9 } },
{ AR5K_RF_GAIN(15), { 0x00000009 } },
{ AR5K_RF_GAIN(16), { 0x00000049 } },
{ AR5K_RF_GAIN(17), { 0x00000089 } },
{ AR5K_RF_GAIN(18), { 0x00000190 } },
{ AR5K_RF_GAIN(19), { 0x000001d0 } },
{ AR5K_RF_GAIN(20), { 0x00000010 } },
{ AR5K_RF_GAIN(21), { 0x00000050 } },
{ AR5K_RF_GAIN(22), { 0x00000090 } },
{ AR5K_RF_GAIN(23), { 0x00000191 } },
{ AR5K_RF_GAIN(24), { 0x000001d1 } },
{ AR5K_RF_GAIN(25), { 0x00000011 } },
{ AR5K_RF_GAIN(26), { 0x00000051 } },
{ AR5K_RF_GAIN(27), { 0x00000091 } },
{ AR5K_RF_GAIN(28), { 0x00000178 } },
{ AR5K_RF_GAIN(29), { 0x000001b8 } },
{ AR5K_RF_GAIN(30), { 0x000001f8 } },
{ AR5K_RF_GAIN(31), { 0x00000038 } },
{ AR5K_RF_GAIN(32), { 0x00000078 } },
{ AR5K_RF_GAIN(33), { 0x00000199 } },
{ AR5K_RF_GAIN(34), { 0x000001d9 } },
{ AR5K_RF_GAIN(35), { 0x00000019 } },
{ AR5K_RF_GAIN(36), { 0x00000059 } },
{ AR5K_RF_GAIN(37), { 0x00000099 } },
{ AR5K_RF_GAIN(38), { 0x000000d9 } },
{ AR5K_RF_GAIN(39), { 0x000000f9 } },
{ AR5K_RF_GAIN(40), { 0x000000f9 } },
{ AR5K_RF_GAIN(41), { 0x000000f9 } },
{ AR5K_RF_GAIN(42), { 0x000000f9 } },
{ AR5K_RF_GAIN(43), { 0x000000f9 } },
{ AR5K_RF_GAIN(44), { 0x000000f9 } },
{ AR5K_RF_GAIN(45), { 0x000000f9 } },
{ AR5K_RF_GAIN(46), { 0x000000f9 } },
{ AR5K_RF_GAIN(47), { 0x000000f9 } },
{ AR5K_RF_GAIN(48), { 0x000000f9 } },
{ AR5K_RF_GAIN(49), { 0x000000f9 } },
{ AR5K_RF_GAIN(50), { 0x000000f9 } },
{ AR5K_RF_GAIN(51), { 0x000000f9 } },
{ AR5K_RF_GAIN(52), { 0x000000f9 } },
{ AR5K_RF_GAIN(53), { 0x000000f9 } },
{ AR5K_RF_GAIN(54), { 0x000000f9 } },
{ AR5K_RF_GAIN(55), { 0x000000f9 } },
{ AR5K_RF_GAIN(56), { 0x000000f9 } },
{ AR5K_RF_GAIN(57), { 0x000000f9 } },
{ AR5K_RF_GAIN(58), { 0x000000f9 } },
{ AR5K_RF_GAIN(59), { 0x000000f9 } },
{ AR5K_RF_GAIN(60), { 0x000000f9 } },
{ AR5K_RF_GAIN(61), { 0x000000f9 } },
{ AR5K_RF_GAIN(62), { 0x000000f9 } },
{ AR5K_RF_GAIN(63), { 0x000000f9 } },
};
static const struct ath5k_gain_opt rfgain_opt_5112 = {
1,
8,
@@ -955,7 +1092,6 @@ static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
go = &rfgain_opt_5111;
break;
case AR5K_RF5112:
case AR5K_RF5413: /* ??? */
go = &rfgain_opt_5112;
break;
default:
@@ -1226,8 +1362,21 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
rf = ah->ah_rf_banks;
rf_ini = rfregs_5413;
rf_size = ARRAY_SIZE(rfregs_5413);
if (ah->ah_radio == AR5K_RF5413) {
rf_ini = rfregs_5413;
rf_size = ARRAY_SIZE(rfregs_5413);
} else if (ah->ah_radio == AR5K_RF2413) {
rf_ini = rfregs_2413;
rf_size = ARRAY_SIZE(rfregs_2413);
if (mode < 2) {
ATH5K_ERR(ah->ah_sc,
"invalid channel mode: %i\n", mode);
return -EINVAL;
}
mode = mode - 2;
} else {
return -EINVAL;
}
/* Copy values to modify them */
for (i = 0; i < rf_size; i++) {
@@ -1286,6 +1435,10 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
ah->ah_rf_banks_size = sizeof(rfregs_5413);
func = ath5k_hw_rf5413_rfregs;
break;
case AR5K_RF2413:
ah->ah_rf_banks_size = sizeof(rfregs_2413);
func = ath5k_hw_rf5413_rfregs;
break;
default:
return -EINVAL;
}
@@ -1324,6 +1477,11 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
ath5k_rfg = rfgain_5413;
size = ARRAY_SIZE(rfgain_5413);
break;
case AR5K_RF2413:
ath5k_rfg = rfgain_2413;
size = ARRAY_SIZE(rfgain_2413);
freq = 0; /* only 2Ghz */
break;
default:
return -EINVAL;
}
@@ -1398,7 +1556,6 @@ int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
ah->ah_gain.g_active = 1;
break;
case AR5K_RF5112:
case AR5K_RF5413: /* ??? */
ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
ah->ah_gain.g_step =
&rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
@@ -2019,6 +2176,15 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
return -EINVAL;
}
/*
* RF2413 for some reason can't
* transmit anything if we call
* this funtion, so we skip it
* until we fix txpower.
*/
if (ah->ah_radio == AR5K_RF2413)
return 0;
/* Reset TX power values */
memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
ah->ah_txpower.txp_tpc = tpc;
+3 -1
View File
@@ -1923,7 +1923,9 @@ after DFS is enabled */
#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
#define AR5K_PHY_SPENDING 0x99f8
#define AR5K_PHY_SPENDING_RF5111 0x00000018
#define AR5K_PHY_SPENDING_RF5112 0x00000014
#define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */
#define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */
#define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */
/*
* Misc PHY/radio registers [5110 - 5111]
+43 -8
View File
@@ -99,6 +99,8 @@
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
#define B43_MMIO_RNG 0x65A
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
#define B43_MMIO_POWERUP_DELAY 0x6A8
/* SPROM boardflags_lo values */
@@ -587,15 +589,13 @@ struct b43_phy {
/* Data structures for DMA transmission, per 80211 core. */
struct b43_dma {
struct b43_dmaring *tx_ring0;
struct b43_dmaring *tx_ring1;
struct b43_dmaring *tx_ring2;
struct b43_dmaring *tx_ring3;
struct b43_dmaring *tx_ring4;
struct b43_dmaring *tx_ring5;
struct b43_dmaring *tx_ring_AC_BK; /* Background */
struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */
struct b43_dmaring *tx_ring_AC_VI; /* Video */
struct b43_dmaring *tx_ring_AC_VO; /* Voice */
struct b43_dmaring *tx_ring_mcast; /* Multicast */
struct b43_dmaring *rx_ring0;
struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */
struct b43_dmaring *rx_ring;
};
/* Context information for a noise calculation (Link Quality). */
@@ -621,6 +621,35 @@ struct b43_key {
u8 algorithm;
};
/* SHM offsets to the QOS data structures for the 4 different queues. */
#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
(B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1)
#define B43_QOS_VIDEO B43_QOS_PARAMS(2)
#define B43_QOS_VOICE B43_QOS_PARAMS(3)
/* QOS parameter hardware data structure offsets. */
#define B43_NR_QOSPARAMS 22
enum {
B43_QOSPARAM_TXOP = 0,
B43_QOSPARAM_CWMIN,
B43_QOSPARAM_CWMAX,
B43_QOSPARAM_CWCUR,
B43_QOSPARAM_AIFS,
B43_QOSPARAM_BSLOTS,
B43_QOSPARAM_REGGAP,
B43_QOSPARAM_STATUS,
};
/* QOS parameters for a queue. */
struct b43_qos_params {
/* The QOS parameters */
struct ieee80211_tx_queue_params p;
/* Does this need to get uploaded to hardware? */
bool need_hw_update;
};
struct b43_wldev;
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
@@ -673,6 +702,12 @@ struct b43_wl {
struct sk_buff *current_beacon;
bool beacon0_uploaded;
bool beacon1_uploaded;
/* The current QOS parameters for the 4 queues.
* This is protected by the irq_lock. */
struct b43_qos_params qos_params[4];
/* Workqueue for updating QOS parameters in hardware. */
struct work_struct qos_update_work;
};
/* In-memory representation of a cached microcode file. */
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -245,6 +245,9 @@ struct b43_dmaring {
enum b43_dmatype type;
/* Boolean. Is this ring stopped at ieee80211 level? */
bool stopped;
/* The QOS priority assigned to this ring. Only used for TX rings.
* This is the mac80211 "queue" value. */
u8 queue_prio;
/* Lock, only used for TX. */
spinlock_t lock;
struct b43_wldev *dev;
@@ -253,7 +256,13 @@ struct b43_dmaring {
int max_used_slots;
/* Last time we injected a ring overflow. */
unsigned long last_injected_overflow;
#endif /* CONFIG_B43_DEBUG */
/* Statistics: Number of successfully transmitted packets */
u64 nr_succeed_tx_packets;
/* Statistics: Number of failed TX packets */
u64 nr_failed_tx_packets;
/* Statistics: Total number of TX plus all retries. */
u64 nr_total_packet_tries;
#endif /* CONFIG_B43_DEBUG */
};
static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
+191 -5
View File
@@ -78,6 +78,11 @@ static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
int b43_modparam_qos = 1;
module_param_named(qos, b43_modparam_qos, int, 0444);
MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -1589,11 +1594,10 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
/* Check the DMA reason registers for received data. */
if (dma_reason[0] & B43_DMAIRQ_RX_DONE)
b43_dma_rx(dev->dma.rx_ring0);
if (dma_reason[3] & B43_DMAIRQ_RX_DONE)
b43_dma_rx(dev->dma.rx_ring3);
b43_dma_rx(dev->dma.rx_ring);
B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
@@ -2708,10 +2712,178 @@ out:
return NETDEV_TX_OK;
}
/* Locking: wl->irq_lock */
static void b43_qos_params_upload(struct b43_wldev *dev,
const struct ieee80211_tx_queue_params *p,
u16 shm_offset)
{
u16 params[B43_NR_QOSPARAMS];
int cw_min, cw_max, aifs, bslots, tmp;
unsigned int i;
const u16 aCWmin = 0x0001;
const u16 aCWmax = 0x03FF;
/* Calculate the default values for the parameters, if needed. */
switch (shm_offset) {
case B43_QOS_VOICE:
aifs = (p->aifs == -1) ? 2 : p->aifs;
cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min;
cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max;
break;
case B43_QOS_VIDEO:
aifs = (p->aifs == -1) ? 2 : p->aifs;
cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min;
cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max;
break;
case B43_QOS_BESTEFFORT:
aifs = (p->aifs == -1) ? 3 : p->aifs;
cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
break;
case B43_QOS_BACKGROUND:
aifs = (p->aifs == -1) ? 7 : p->aifs;
cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
break;
default:
B43_WARN_ON(1);
return;
}
if (cw_min <= 0)
cw_min = aCWmin;
if (cw_max <= 0)
cw_max = aCWmin;
bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min;
memset(&params, 0, sizeof(params));
params[B43_QOSPARAM_TXOP] = p->txop * 32;
params[B43_QOSPARAM_CWMIN] = cw_min;
params[B43_QOSPARAM_CWMAX] = cw_max;
params[B43_QOSPARAM_CWCUR] = cw_min;
params[B43_QOSPARAM_AIFS] = aifs;
params[B43_QOSPARAM_BSLOTS] = bslots;
params[B43_QOSPARAM_REGGAP] = bslots + aifs;
for (i = 0; i < ARRAY_SIZE(params); i++) {
if (i == B43_QOSPARAM_STATUS) {
tmp = b43_shm_read16(dev, B43_SHM_SHARED,
shm_offset + (i * 2));
/* Mark the parameters as updated. */
tmp |= 0x100;
b43_shm_write16(dev, B43_SHM_SHARED,
shm_offset + (i * 2),
tmp);
} else {
b43_shm_write16(dev, B43_SHM_SHARED,
shm_offset + (i * 2),
params[i]);
}
}
}
/* Update the QOS parameters in hardware. */
static void b43_qos_update(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
struct b43_qos_params *params;
unsigned long flags;
unsigned int i;
/* Mapping of mac80211 queues to b43 SHM offsets. */
static const u16 qos_shm_offsets[] = {
[0] = B43_QOS_VOICE,
[1] = B43_QOS_VIDEO,
[2] = B43_QOS_BESTEFFORT,
[3] = B43_QOS_BACKGROUND,
};
BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
b43_mac_suspend(dev);
spin_lock_irqsave(&wl->irq_lock, flags);
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
params = &(wl->qos_params[i]);
if (params->need_hw_update) {
b43_qos_params_upload(dev, &(params->p),
qos_shm_offsets[i]);
params->need_hw_update = 0;
}
}
spin_unlock_irqrestore(&wl->irq_lock, flags);
b43_mac_enable(dev);
}
static void b43_qos_clear(struct b43_wl *wl)
{
struct b43_qos_params *params;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
params = &(wl->qos_params[i]);
memset(&(params->p), 0, sizeof(params->p));
params->p.aifs = -1;
params->need_hw_update = 1;
}
}
/* Initialize the core's QOS capabilities */
static void b43_qos_init(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
unsigned int i;
/* Upload the current QOS parameters. */
for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
wl->qos_params[i].need_hw_update = 1;
b43_qos_update(dev);
/* Enable QOS support. */
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
b43_write16(dev, B43_MMIO_IFSCTL,
b43_read16(dev, B43_MMIO_IFSCTL)
| B43_MMIO_IFSCTL_USE_EDCF);
}
static void b43_qos_update_work(struct work_struct *work)
{
struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
struct b43_wldev *dev;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
b43_qos_update(dev);
mutex_unlock(&wl->mutex);
}
static int b43_op_conf_tx(struct ieee80211_hw *hw,
int queue,
int _queue,
const struct ieee80211_tx_queue_params *params)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
unsigned int queue = (unsigned int)_queue;
struct b43_qos_params *p;
if (queue >= ARRAY_SIZE(wl->qos_params)) {
/* Queue not available or don't support setting
* params on this queue. Return success to not
* confuse mac80211. */
return 0;
}
spin_lock_irqsave(&wl->irq_lock, flags);
p = &(wl->qos_params[queue]);
memcpy(&(p->p), params, sizeof(p->p));
p->need_hw_update = 1;
spin_unlock_irqrestore(&wl->irq_lock, flags);
queue_work(hw->workqueue, &wl->qos_update_work);
return 0;
}
@@ -3732,6 +3904,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
memset(wl->mac_addr, 0, ETH_ALEN);
wl->filter_flags = 0;
wl->radiotap_enabled = 0;
b43_qos_clear(wl);
/* First register RFkill.
* LEDs that are registered later depend on it. */
@@ -3773,6 +3946,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
struct b43_wldev *dev = wl->current_dev;
b43_rfkill_exit(dev);
cancel_work_sync(&(wl->qos_update_work));
mutex_lock(&wl->mutex);
if (b43_status(dev) >= B43_STAT_STARTED)
@@ -3835,6 +4009,16 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
return 0;
}
static void b43_op_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
const u8 *addr)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
B43_WARN_ON(!vif || wl->vif != vif);
}
static const struct ieee80211_ops b43_hw_ops = {
.tx = b43_op_tx,
.conf_tx = b43_op_conf_tx,
@@ -3851,6 +4035,7 @@ static const struct ieee80211_ops b43_hw_ops = {
.set_retry_limit = b43_op_set_retry_limit,
.set_tim = b43_op_beacon_set_tim,
.beacon_update = b43_op_ibss_beacon_update,
.sta_notify = b43_op_sta_notify,
};
/* Hard-reset the chip. Do not call this directly.
@@ -4122,7 +4307,7 @@ static int b43_wireless_init(struct ssb_device *dev)
hw->max_signal = 100;
hw->max_rssi = -110;
hw->max_noise = -110;
hw->queues = 1; /* FIXME: hardware has more queues */
hw->queues = b43_modparam_qos ? 4 : 1;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
@@ -4138,6 +4323,7 @@ static int b43_wireless_init(struct ssb_device *dev)
spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
INIT_LIST_HEAD(&wl->devlist);
INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
ssb_set_devtypedata(dev, wl);
b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+4
View File
@@ -38,6 +38,10 @@
/* Magic helper macro to pad structures. Ignore those above. It's magic. */
#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
extern int b43_modparam_qos;
/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
static inline u8 b43_freq_to_channel_5ghz(int freq)
{
-27
View File
@@ -705,30 +705,3 @@ void b43_tx_resume(struct b43_wldev *dev)
{
b43_dma_tx_resume(dev);
}
#if 0
static void upload_qos_parms(struct b43_wldev *dev,
const u16 * parms, u16 offset)
{
int i;
for (i = 0; i < B43_NR_QOSPARMS; i++) {
b43_shm_write16(dev, B43_SHM_SHARED,
offset + (i * 2), parms[i]);
}
}
#endif
/* Initialize the QoS parameters */
void b43_qos_init(struct b43_wldev *dev)
{
/* FIXME: This function must probably be called from the mac80211
* config callback. */
return;
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
//FIXME kill magic
b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
/*TODO: We might need some stack support here to get the values. */
}
-12
View File
@@ -302,18 +302,6 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev,
void b43_tx_suspend(struct b43_wldev *dev);
void b43_tx_resume(struct b43_wldev *dev);
#define B43_NR_QOSPARMS 22
enum {
B43_QOSPARM_TXOP = 0,
B43_QOSPARM_CWMIN,
B43_QOSPARM_CWMAX,
B43_QOSPARM_CWCUR,
B43_QOSPARM_AIFS,
B43_QOSPARM_BSLOTS,
B43_QOSPARM_REGGAP,
B43_QOSPARM_STATUS,
};
void b43_qos_init(struct b43_wldev *dev);
/* Helper functions for converting the key-table index from "firmware-format"
* to "raw-format" and back. The firmware API changed for this at some revision.
+5
View File
@@ -1,7 +1,12 @@
config IWLCORE
tristate "Intel Wireless Wifi Core"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
config IWL4965
tristate "Intel Wireless WiFi 4965AGN"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
select IWLCORE
---help---
Select to build the driver supporting the:
+3
View File
@@ -1,3 +1,6 @@
obj-$(CONFIG_IWLCORE) += iwlcore.o
iwlcore-objs = iwl-core.o
obj-$(CONFIG_IWL3945) += iwl3945.o
iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o

Some files were not shown because too many files have changed in this diff Show More