You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.26
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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>
|
||||
@@ -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 *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
+250
-191
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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. */
|
||||
|
||||
+178
-208
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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(¶ms, 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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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. */
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user