Commit ba73d4c8 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'master' of

parents b8ad0cbc deedf504
......@@ -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 \
# The build process is as follows (targets):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"" []>
<book id="mac80211-developers-guide">
<title>The mac80211 subsystem for kernel developers</title>
<holder>Johannes Berg</holder>
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.
This documentation is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
See the GNU General Public License for more details.
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
For more details see the file COPYING in the source
distribution of Linux.
!Pinclude/net/mac80211.h Introduction
!Pinclude/net/mac80211.h Warning
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.
<title>The basic mac80211 driver interface</title>
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.
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.
<chapter id="basics">
<title>Basic hardware handling</title>
This chapter shall contain information on getting a hw
struct allocated and registered with mac80211.
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.
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.
Finally, a discussion of hardware capabilities should be done
with references to other parts of the book.
<!-- 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 id="phy-handling">
<title>PHY configuration</title>
This chapter should describe PHY handling including
start/stop callbacks and the various structures used.
!Finclude/net/mac80211.h ieee80211_conf
!Finclude/net/mac80211.h ieee80211_conf_flags
<chapter id="iface-handling">
<title>Virtual interfaces</title>
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>Things related to AP mode should be discussed there.</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!
!Finclude/net/mac80211.h ieee80211_if_types
!Finclude/net/mac80211.h ieee80211_if_init_conf
!Finclude/net/mac80211.h ieee80211_if_conf
<chapter id="rx-tx">
<title>Receive and transmit processing</title>
<title>what should be here</title>
This should describe the receive and transmit
paths in mac80211/the drivers as well as
transmit status handling.
<title>Frame format</title>
!Pinclude/net/mac80211.h Frame format
<title>Alignment issues</title>
<title>Calling into mac80211 from interrupts</title>
!Pinclude/net/mac80211.h Calling mac80211 from interrupts
!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
<chapter id="filters">
<title>Frame filtering</title>
!Pinclude/net/mac80211.h Frame filtering
!Finclude/net/mac80211.h ieee80211_filter_flags
<part id="advanced">
<title>Advanced driver interface</title>
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.
<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 id="qos">
<title>Multiple queues and QoS support</title>
!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 id="AP">
<title>Access point mode support</title>
<para>Some parts of the if_conf should be discussed here instead</para>
Insert notes about VLAN interfaces with hw crypto here or
in the hw crypto chapter.
!Finclude/net/mac80211.h ieee80211_get_buffered_bc
!Finclude/net/mac80211.h ieee80211_beacon_get
<chapter id="multi-iface">
<title>Supporting multiple virtual interfaces</title>
Note: WDS with identical MAC address should almost always be OK
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.
<chapter id="hardware-scan-offload">
<title>Hardware scan offload</title>
!Finclude/net/mac80211.h ieee80211_scan_completed
<part id="rate-control">
<title>Rate control interface</title>
This part of the book describes the rate control algorithm
interface and how it relates to mac80211 and drivers.
<chapter id="dummy">
<title>dummy chapter</title>
<part id="internal">
This part of the book describes mac80211 internals.
<chapter id="key-handling">
<title>Key handling</title>
<title>Key handling basics</title>
!Pnet/mac80211/key.c Key handling basics
<title>MORE TBD</title>
<chapter id="rx-processing">
<title>Receive processing</title>
<chapter id="tx-processing">
<title>Transmit processing</title>
<chapter id="sta-info">
<title>Station info handling</title>
<title>Programming information</title>
!Fnet/mac80211/sta_info.h sta_info
!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
<title>STA information lifetime rules</title>
!Pnet/mac80211/sta_info.c STA information lifetime rules
<chapter id="synchronisation">
<para>Locking, lots of RCU</para>
......@@ -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) \
* 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 {
......@@ -495,29 +499,23 @@ struct ath5k_beacon_state {
#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
* 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 },
{ "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 },
{ "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)
list_for_each_entry_safe(bf, bf0, &txq->q, list) {
ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
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)
/* 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) {
tsf = ath5k_hw_get_tsf64(sc->ah);
bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
hw_tu = TSF_TO_TU(tsf);
"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) {
"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 */
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))
else if (unlikely(ret)) {
......@@ -1779,16 +1812,15 @@ ath5k_tasklet_rx(unsigned long data)
if (unlikely(ds->ds_rxstat.rs_more)) {
if (unlikely(rs.rs_more)) {
ATH5K_WARN(sc, "unsupported jumbo\n");
goto next;