2003-06-23 17:01:19 +00:00
|
|
|
/*-
|
2009-01-08 17:12:47 +00:00
|
|
|
* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
|
2003-06-23 17:01:19 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer,
|
|
|
|
* without modification.
|
|
|
|
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
|
|
|
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
|
|
|
* redistribution must be conditioned upon including a substantially
|
|
|
|
* similar Disclaimer requirement for further binary redistribution.
|
|
|
|
*
|
|
|
|
* NO WARRANTY
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
|
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
|
|
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
|
|
|
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
|
|
|
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
|
|
* THE POSSIBILITY OF SUCH DAMAGES.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Driver for the Atheros Wireless LAN controller.
|
2003-06-30 04:51:11 +00:00
|
|
|
*
|
|
|
|
* This software is derived from work of Atsushi Onoe; his contribution
|
|
|
|
* is greatly appreciated.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "opt_inet.h"
|
2006-04-03 18:14:02 +00:00
|
|
|
#include "opt_ath.h"
|
2011-10-18 02:43:59 +00:00
|
|
|
/*
|
|
|
|
* This is needed for register operations which are performed
|
|
|
|
* by the driver - eg, calls to ath_hal_gettsf32().
|
2012-03-16 23:12:40 +00:00
|
|
|
*
|
|
|
|
* It's also required for any AH_DEBUG checks in here, eg the
|
|
|
|
* module dependencies.
|
2011-10-18 02:43:59 +00:00
|
|
|
*/
|
|
|
|
#include "opt_ah.h"
|
2009-03-30 19:23:49 +00:00
|
|
|
#include "opt_wlan.h"
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
#include <sys/param.h>
|
2010-02-19 18:23:45 +00:00
|
|
|
#include <sys/systm.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <sys/sysctl.h>
|
2010-02-19 18:23:45 +00:00
|
|
|
#include <sys/mbuf.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/callout.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/endian.h>
|
2006-02-09 21:48:51 +00:00
|
|
|
#include <sys/kthread.h>
|
|
|
|
#include <sys/taskqueue.h>
|
2009-02-13 05:38:03 +00:00
|
|
|
#include <sys/priv.h>
|
2011-03-31 08:07:13 +00:00
|
|
|
#include <sys/module.h>
|
2011-11-08 19:02:59 +00:00
|
|
|
#include <sys/ktr.h>
|
2011-11-09 22:39:44 +00:00
|
|
|
#include <sys/smp.h> /* for mp_ncpus */
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
#include <machine/bus.h>
|
2010-02-19 18:23:45 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_media.h>
|
2005-06-10 16:49:24 +00:00
|
|
|
#include <net/if_types.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <net/if_arp.h>
|
|
|
|
#include <net/ethernet.h>
|
|
|
|
#include <net/if_llc.h>
|
|
|
|
|
|
|
|
#include <net80211/ieee80211_var.h>
|
2009-01-28 18:00:22 +00:00
|
|
|
#include <net80211/ieee80211_regdomain.h>
|
2009-03-30 21:53:27 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
|
|
|
#include <net80211/ieee80211_superg.h>
|
|
|
|
#endif
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
#include <net80211/ieee80211_tdma.h>
|
|
|
|
#endif
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
|
|
|
|
#ifdef INET
|
2010-02-19 18:23:45 +00:00
|
|
|
#include <netinet/in.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
#include <netinet/if_ether.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <dev/ath/if_athvar.h>
|
2008-12-01 16:53:01 +00:00
|
|
|
#include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */
|
2011-01-20 04:57:26 +00:00
|
|
|
#include <dev/ath/ath_hal/ah_diagcodes.h>
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-01-29 05:08:21 +00:00
|
|
|
#include <dev/ath/if_ath_debug.h>
|
2011-01-29 11:35:23 +00:00
|
|
|
#include <dev/ath/if_ath_misc.h>
|
2012-05-20 02:05:10 +00:00
|
|
|
#include <dev/ath/if_ath_tsf.h>
|
2011-01-29 11:35:23 +00:00
|
|
|
#include <dev/ath/if_ath_tx.h>
|
2011-03-02 16:03:19 +00:00
|
|
|
#include <dev/ath/if_ath_sysctl.h>
|
2011-12-26 05:37:09 +00:00
|
|
|
#include <dev/ath/if_ath_led.h>
|
2011-03-02 17:19:54 +00:00
|
|
|
#include <dev/ath/if_ath_keycache.h>
|
2012-05-20 02:05:10 +00:00
|
|
|
#include <dev/ath/if_ath_rx.h>
|
2012-07-03 06:59:12 +00:00
|
|
|
#include <dev/ath/if_ath_rx_edma.h>
|
2012-07-23 03:52:18 +00:00
|
|
|
#include <dev/ath/if_ath_tx_edma.h>
|
2012-05-20 02:49:42 +00:00
|
|
|
#include <dev/ath/if_ath_beacon.h>
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
#include <dev/ath/if_ath_btcoex.h>
|
2013-01-02 03:59:02 +00:00
|
|
|
#include <dev/ath/if_ath_spectral.h>
|
2013-06-12 14:52:57 +00:00
|
|
|
#include <dev/ath/if_ath_lna_div.h>
|
2011-06-01 20:09:49 +00:00
|
|
|
#include <dev/ath/if_athdfs.h>
|
2011-01-29 05:08:21 +00:00
|
|
|
|
2006-02-09 21:28:11 +00:00
|
|
|
#ifdef ATH_TX99_DIAG
|
|
|
|
#include <dev/ath/ath_tx99/ath_tx99.h>
|
|
|
|
#endif
|
|
|
|
|
2012-11-07 16:34:09 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
2012-11-07 06:29:45 +00:00
|
|
|
#include <dev/ath/if_ath_alq.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only enable this if you're working on PS-POLL support.
|
|
|
|
*/
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
#define ATH_SW_PSQ
|
2012-11-07 06:29:45 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
|
|
|
* ATH_BCBUF determines the number of vap's that can transmit
|
|
|
|
* beacons and also (currently) the number of vap's that can
|
|
|
|
* have unique mac addresses/bssid. When staggering beacons
|
|
|
|
* 4 is probably a good max as otherwise the beacons become
|
|
|
|
* very closely spaced and there is limited time for cab q traffic
|
|
|
|
* to go out. You can burst beacons instead but that is not good
|
|
|
|
* for stations in power save and at some point you really want
|
|
|
|
* another radio (and channel).
|
|
|
|
*
|
|
|
|
* The limit on the number of mac addresses is tied to our use of
|
|
|
|
* the U/L bit and tracking addresses in a byte; it would be
|
|
|
|
* worthwhile to allow more for applications like proxy sta.
|
|
|
|
*/
|
|
|
|
CTASSERT(ATH_BCBUF <= 8);
|
|
|
|
|
|
|
|
static struct ieee80211vap *ath_vap_create(struct ieee80211com *,
|
2011-12-17 10:23:17 +00:00
|
|
|
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
|
|
|
|
const uint8_t [IEEE80211_ADDR_LEN],
|
|
|
|
const uint8_t [IEEE80211_ADDR_LEN]);
|
2008-04-20 20:35:46 +00:00
|
|
|
static void ath_vap_delete(struct ieee80211vap *);
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_init(void *);
|
2004-12-08 17:34:36 +00:00
|
|
|
static void ath_stop_locked(struct ifnet *);
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_stop(struct ifnet *);
|
2008-04-20 20:35:46 +00:00
|
|
|
static int ath_reset_vap(struct ieee80211vap *, u_long);
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
static int ath_transmit(struct ifnet *ifp, struct mbuf *m);
|
|
|
|
static void ath_qflush(struct ifnet *ifp);
|
2003-06-23 17:01:19 +00:00
|
|
|
static int ath_media_change(struct ifnet *);
|
2009-03-09 23:10:19 +00:00
|
|
|
static void ath_watchdog(void *);
|
2003-06-23 17:01:19 +00:00
|
|
|
static int ath_ioctl(struct ifnet *, u_long, caddr_t);
|
|
|
|
static void ath_fatal_proc(void *, int);
|
2008-04-20 20:35:46 +00:00
|
|
|
static void ath_bmiss_vap(struct ieee80211vap *);
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_bmiss_proc(void *, int);
|
2008-04-20 20:35:46 +00:00
|
|
|
static void ath_key_update_begin(struct ieee80211vap *);
|
|
|
|
static void ath_key_update_end(struct ieee80211vap *);
|
|
|
|
static void ath_update_mcast(struct ifnet *);
|
|
|
|
static void ath_update_promisc(struct ifnet *);
|
2004-12-08 17:34:36 +00:00
|
|
|
static void ath_updateslot(struct ifnet *);
|
|
|
|
static void ath_bstuck_proc(void *, int);
|
2012-02-25 19:12:54 +00:00
|
|
|
static void ath_reset_proc(void *, int);
|
2003-06-23 17:01:19 +00:00
|
|
|
static int ath_desc_alloc(struct ath_softc *);
|
|
|
|
static void ath_desc_free(struct ath_softc *);
|
2008-06-07 18:38:02 +00:00
|
|
|
static struct ieee80211_node *ath_node_alloc(struct ieee80211vap *,
|
|
|
|
const uint8_t [IEEE80211_ADDR_LEN]);
|
2011-11-08 18:48:26 +00:00
|
|
|
static void ath_node_cleanup(struct ieee80211_node *);
|
2004-12-08 17:34:36 +00:00
|
|
|
static void ath_node_free(struct ieee80211_node *);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
static void ath_node_getsignal(const struct ieee80211_node *,
|
|
|
|
int8_t *, int8_t *);
|
2006-06-26 03:10:45 +00:00
|
|
|
static void ath_txq_init(struct ath_softc *sc, struct ath_txq *, int);
|
2004-12-08 17:34:36 +00:00
|
|
|
static struct ath_txq *ath_txq_setup(struct ath_softc*, int qtype, int subtype);
|
|
|
|
static int ath_tx_setup(struct ath_softc *, int, int);
|
|
|
|
static void ath_tx_cleanupq(struct ath_softc *, struct ath_txq *);
|
|
|
|
static void ath_tx_cleanup(struct ath_softc *);
|
2012-08-12 00:37:29 +00:00
|
|
|
static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
|
int dosched);
|
2004-12-08 17:34:36 +00:00
|
|
|
static void ath_tx_proc_q0(void *, int);
|
|
|
|
static void ath_tx_proc_q0123(void *, int);
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_tx_proc(void *, int);
|
2012-03-29 17:39:18 +00:00
|
|
|
static void ath_txq_sched_tasklet(void *, int);
|
2003-06-23 17:01:19 +00:00
|
|
|
static int ath_chan_set(struct ath_softc *, struct ieee80211_channel *);
|
2004-12-08 17:34:36 +00:00
|
|
|
static void ath_chan_change(struct ath_softc *, struct ieee80211_channel *);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
static void ath_scan_start(struct ieee80211com *);
|
|
|
|
static void ath_scan_end(struct ieee80211com *);
|
|
|
|
static void ath_set_channel(struct ieee80211com *);
|
2012-04-10 06:25:11 +00:00
|
|
|
#ifdef ATH_ENABLE_11N
|
2012-03-25 03:14:31 +00:00
|
|
|
static void ath_update_chw(struct ieee80211com *);
|
2012-04-10 06:25:11 +00:00
|
|
|
#endif /* ATH_ENABLE_11N */
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_calibrate(void *);
|
2008-04-20 20:35:46 +00:00
|
|
|
static int ath_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
2005-06-06 16:39:21 +00:00
|
|
|
static void ath_setup_stationkey(struct ieee80211_node *);
|
2005-07-22 17:57:16 +00:00
|
|
|
static void ath_newassoc(struct ieee80211_node *, int);
|
2008-04-20 20:35:46 +00:00
|
|
|
static int ath_setregdomain(struct ieee80211com *,
|
|
|
|
struct ieee80211_regdomain *, int,
|
|
|
|
struct ieee80211_channel []);
|
2009-01-27 23:19:36 +00:00
|
|
|
static void ath_getradiocaps(struct ieee80211com *, int, int *,
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211_channel []);
|
|
|
|
static int ath_getchannels(struct ath_softc *);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
static int ath_rate_setup(struct ath_softc *, u_int mode);
|
2003-06-23 17:01:19 +00:00
|
|
|
static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
static void ath_announce(struct ath_softc *);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
static void ath_dfs_tasklet(void *, int);
|
2012-10-03 23:23:45 +00:00
|
|
|
static void ath_node_powersave(struct ieee80211_node *, int);
|
2012-10-28 21:13:12 +00:00
|
|
|
static int ath_node_set_tim(struct ieee80211_node *, int);
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
static void ath_node_recv_pspoll(struct ieee80211_node *, struct mbuf *);
|
2011-06-01 20:09:49 +00:00
|
|
|
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2012-05-20 02:49:42 +00:00
|
|
|
#include <dev/ath/if_ath_tdma.h>
|
|
|
|
#endif
|
2009-01-08 17:12:47 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
SYSCTL_DECL(_hw_ath);
|
|
|
|
|
|
|
|
/* XXX validate sysctl values */
|
2008-12-07 19:26:34 +00:00
|
|
|
static int ath_longcalinterval = 30; /* long cals every 30 secs */
|
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, longcal, CTLFLAG_RW, &ath_longcalinterval,
|
|
|
|
0, "long chip calibration interval (secs)");
|
|
|
|
static int ath_shortcalinterval = 100; /* short cals every 100 ms */
|
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, shortcal, CTLFLAG_RW, &ath_shortcalinterval,
|
|
|
|
0, "short chip calibration interval (msecs)");
|
|
|
|
static int ath_resetcalinterval = 20*60; /* reset cal state 20 mins */
|
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, resetcal, CTLFLAG_RW, &ath_resetcalinterval,
|
|
|
|
0, "reset chip calibration results (secs)");
|
2011-01-21 05:21:00 +00:00
|
|
|
static int ath_anicalinterval = 100; /* ANI calibration - 100 msec */
|
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval,
|
|
|
|
0, "ANI calibration (msecs)");
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-09 08:37:59 +00:00
|
|
|
int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */
|
2006-12-27 19:07:09 +00:00
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf,
|
2006-02-09 21:03:25 +00:00
|
|
|
0, "rx buffers allocated");
|
|
|
|
TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf);
|
2012-07-09 08:37:59 +00:00
|
|
|
int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */
|
2006-12-27 19:07:09 +00:00
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf,
|
2006-02-09 21:03:25 +00:00
|
|
|
0, "tx buffers allocated");
|
|
|
|
TUNABLE_INT("hw.ath.txbuf", &ath_txbuf);
|
2012-07-09 08:37:59 +00:00
|
|
|
int ath_txbuf_mgmt = ATH_MGMT_TXBUF; /* # mgmt tx buffers to allocate */
|
2012-06-13 06:57:55 +00:00
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RW, &ath_txbuf_mgmt,
|
|
|
|
0, "tx (mgmt) buffers allocated");
|
|
|
|
TUNABLE_INT("hw.ath.txbuf_mgmt", &ath_txbuf_mgmt);
|
2006-02-09 21:03:25 +00:00
|
|
|
|
2012-05-20 02:49:42 +00:00
|
|
|
int ath_bstuck_threshold = 4; /* max missed beacons */
|
2009-02-10 19:26:42 +00:00
|
|
|
SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold,
|
|
|
|
0, "max missed beacon xmits before chip reset");
|
|
|
|
|
2011-11-08 17:08:12 +00:00
|
|
|
MALLOC_DEFINE(M_ATHDEV, "athdev", "ath driver dma buffers");
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-07-31 03:09:48 +00:00
|
|
|
void
|
|
|
|
ath_legacy_attach_comp_func(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Special case certain configurations. Note the
|
|
|
|
* CAB queue is handled by these specially so don't
|
|
|
|
* include them when checking the txq setup mask.
|
|
|
|
*/
|
|
|
|
switch (sc->sc_txqsetup &~ (1<<sc->sc_cabq->axq_qnum)) {
|
|
|
|
case 0x01:
|
|
|
|
TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0, sc);
|
|
|
|
break;
|
|
|
|
case 0x0f:
|
|
|
|
TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc_q0123, sc);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TASK_INIT(&sc->sc_txtask, 0, ath_tx_proc, sc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-09 15:43:38 +00:00
|
|
|
#define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20)
|
|
|
|
#define HAL_MODE_HT40 \
|
|
|
|
(HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \
|
|
|
|
HAL_MODE_11NA_HT40PLUS | HAL_MODE_11NA_HT40MINUS)
|
2003-06-23 17:01:19 +00:00
|
|
|
int
|
|
|
|
ath_attach(u_int16_t devid, struct ath_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ath_hal *ah = NULL;
|
2003-06-23 17:01:19 +00:00
|
|
|
HAL_STATUS status;
|
2004-12-08 17:34:36 +00:00
|
|
|
int error = 0, i;
|
2008-10-27 18:30:33 +00:00
|
|
|
u_int wmodes;
|
2009-03-29 17:59:14 +00:00
|
|
|
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
2012-02-10 10:01:09 +00:00
|
|
|
int rx_chainmask, tx_chainmask;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-10-28 18:46:06 +00:00
|
|
|
CURVNET_SET(vnet0);
|
2008-04-20 20:35:46 +00:00
|
|
|
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
2005-06-10 16:49:24 +00:00
|
|
|
if (ifp == NULL) {
|
|
|
|
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
|
|
|
error = ENOSPC;
|
2012-11-16 19:57:16 +00:00
|
|
|
CURVNET_RESTORE();
|
2005-06-10 16:49:24 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
ic = ifp->if_l2com;
|
2005-06-10 16:49:24 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/* set these up early for if_printf use */
|
2003-10-31 18:32:15 +00:00
|
|
|
if_initname(ifp, device_get_name(sc->sc_dev),
|
2004-12-08 17:34:36 +00:00
|
|
|
device_get_unit(sc->sc_dev));
|
2012-10-28 18:46:06 +00:00
|
|
|
CURVNET_RESTORE();
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-12-26 05:26:35 +00:00
|
|
|
ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh,
|
|
|
|
sc->sc_eepromdata, &status);
|
2003-06-23 17:01:19 +00:00
|
|
|
if (ah == NULL) {
|
|
|
|
if_printf(ifp, "unable to attach hardware; HAL status %u\n",
|
|
|
|
status);
|
|
|
|
error = ENXIO;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
sc->sc_ah = ah;
|
2003-08-13 21:29:35 +00:00
|
|
|
sc->sc_invalid = 0; /* ready to go, enable interrupt handling */
|
2008-10-27 17:19:39 +00:00
|
|
|
#ifdef ATH_DEBUG
|
|
|
|
sc->sc_debug = ath_debug;
|
|
|
|
#endif
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-03 06:59:12 +00:00
|
|
|
/*
|
|
|
|
* Setup the DMA/EDMA functions based on the current
|
|
|
|
* hardware support.
|
|
|
|
*
|
|
|
|
* This is required before the descriptors are allocated.
|
|
|
|
*/
|
2012-07-09 08:37:59 +00:00
|
|
|
if (ath_hal_hasedma(sc->sc_ah)) {
|
|
|
|
sc->sc_isedma = 1;
|
2012-07-03 06:59:12 +00:00
|
|
|
ath_recv_setup_edma(sc);
|
2012-07-23 03:52:18 +00:00
|
|
|
ath_xmit_setup_edma(sc);
|
|
|
|
} else {
|
2012-07-03 06:59:12 +00:00
|
|
|
ath_recv_setup_legacy(sc);
|
2012-07-23 03:52:18 +00:00
|
|
|
ath_xmit_setup_legacy(sc);
|
|
|
|
}
|
2012-07-03 06:59:12 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Check if the MAC has multi-rate retry support.
|
|
|
|
* We do this by trying to setup a fake extended
|
|
|
|
* descriptor. MAC's that don't have support will
|
|
|
|
* return false w/o doing anything. MAC's that do
|
|
|
|
* support it will return true w/o doing anything.
|
|
|
|
*/
|
|
|
|
sc->sc_mrretry = ath_hal_setupxtxdesc(ah, NULL, 0,0, 0,0, 0,0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the device has hardware counters for PHY
|
|
|
|
* errors. If so we need to enable the MIB interrupt
|
|
|
|
* so we can act on stat triggers.
|
|
|
|
*/
|
|
|
|
if (ath_hal_hwphycounters(ah))
|
|
|
|
sc->sc_needmib = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the hardware key cache size.
|
|
|
|
*/
|
|
|
|
sc->sc_keymax = ath_hal_keycachesize(ah);
|
2005-06-06 16:39:21 +00:00
|
|
|
if (sc->sc_keymax > ATH_KEYMAX) {
|
|
|
|
if_printf(ifp, "Warning, using only %u of %u key cache slots\n",
|
|
|
|
ATH_KEYMAX, sc->sc_keymax);
|
|
|
|
sc->sc_keymax = ATH_KEYMAX;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Reset the key cache since some parts do not
|
|
|
|
* reset the contents on initial power up.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < sc->sc_keymax; i++)
|
|
|
|
ath_hal_keyreset(ah, i);
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
2008-04-20 20:35:46 +00:00
|
|
|
* Collect the default channel list.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
error = ath_getchannels(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup rate tables for all potential media types.
|
|
|
|
*/
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_11A);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_11B);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_11G);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_TURBO_A);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_TURBO_G);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_STURBO_A);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_11NA);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_11NG);
|
2007-01-15 01:15:57 +00:00
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_HALF);
|
|
|
|
ath_rate_setup(sc, IEEE80211_MODE_QUARTER);
|
2006-12-27 19:07:09 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/* NB: setup here so ath_rate_update is happy */
|
|
|
|
ath_setcurmode(sc, IEEE80211_MODE_11A);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
2012-07-23 03:52:18 +00:00
|
|
|
* Allocate TX descriptors and populate the lists.
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
error = ath_desc_alloc(sc);
|
|
|
|
if (error != 0) {
|
2012-07-23 03:52:18 +00:00
|
|
|
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
|
|
|
|
error);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
error = ath_txdma_setup(sc);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
|
|
|
|
error);
|
2003-06-23 17:01:19 +00:00
|
|
|
goto bad;
|
|
|
|
}
|
2012-07-09 08:37:59 +00:00
|
|
|
|
2012-07-23 03:52:18 +00:00
|
|
|
/*
|
|
|
|
* Allocate RX descriptors and populate the lists.
|
|
|
|
*/
|
2012-07-09 08:37:59 +00:00
|
|
|
error = ath_rxdma_setup(sc);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "failed to allocate RX descriptors: %d\n",
|
|
|
|
error);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
2009-03-09 23:10:19 +00:00
|
|
|
callout_init_mtx(&sc->sc_cal_ch, &sc->sc_mtx, 0);
|
|
|
|
callout_init_mtx(&sc->sc_wd_ch, &sc->sc_mtx, 0);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2003-10-14 22:51:45 +00:00
|
|
|
ATH_TXBUF_LOCK_INIT(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2006-02-09 21:48:51 +00:00
|
|
|
sc->sc_tq = taskqueue_create("ath_taskq", M_NOWAIT,
|
|
|
|
taskqueue_thread_enqueue, &sc->sc_tq);
|
|
|
|
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
|
|
|
|
"%s taskq", ifp->if_xname);
|
|
|
|
|
2012-07-03 06:59:12 +00:00
|
|
|
TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
|
2006-02-10 19:07:08 +00:00
|
|
|
TASK_INIT(&sc->sc_bstucktask,0, ath_bstuck_proc, sc);
|
2012-02-25 19:12:54 +00:00
|
|
|
TASK_INIT(&sc->sc_resettask,0, ath_reset_proc, sc);
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
TASK_INIT(&sc->sc_txqtask, 0, ath_txq_sched_tasklet, sc);
|
|
|
|
TASK_INIT(&sc->sc_fataltask, 0, ath_fatal_proc, sc);
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* Allocate hardware transmit queues: one queue for
|
|
|
|
* beacon frames and one data queue for each QoS
|
2010-02-19 18:23:45 +00:00
|
|
|
* priority. Note that the hal handles resetting
|
2004-12-08 17:34:36 +00:00
|
|
|
* these queues at the needed time.
|
|
|
|
*
|
|
|
|
* XXX PS-Poll
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2012-08-11 23:26:19 +00:00
|
|
|
sc->sc_bhalq = ath_beaconq_setup(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
if (sc->sc_bhalq == (u_int) -1) {
|
|
|
|
if_printf(ifp, "unable to setup a beacon xmit queue!\n");
|
2004-12-08 17:34:36 +00:00
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0);
|
|
|
|
if (sc->sc_cabq == NULL) {
|
|
|
|
if_printf(ifp, "unable to setup CAB xmit queue!\n");
|
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
/* NB: insure BK queue is the lowest priority h/w queue */
|
|
|
|
if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) {
|
|
|
|
if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
|
|
|
|
ieee80211_wme_acnames[WME_AC_BK]);
|
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
if (!ath_tx_setup(sc, WME_AC_BE, HAL_WME_AC_BE) ||
|
|
|
|
!ath_tx_setup(sc, WME_AC_VI, HAL_WME_AC_VI) ||
|
|
|
|
!ath_tx_setup(sc, WME_AC_VO, HAL_WME_AC_VO)) {
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* Not enough hardware tx queues to properly do WME;
|
|
|
|
* just punt and assign them all to the same h/w queue.
|
|
|
|
* We could do a better job of this if, for example,
|
|
|
|
* we allocate queues when we switch from station to
|
|
|
|
* AP mode.
|
|
|
|
*/
|
|
|
|
if (sc->sc_ac2q[WME_AC_VI] != NULL)
|
|
|
|
ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_VI]);
|
|
|
|
if (sc->sc_ac2q[WME_AC_BE] != NULL)
|
|
|
|
ath_tx_cleanupq(sc, sc->sc_ac2q[WME_AC_BE]);
|
|
|
|
sc->sc_ac2q[WME_AC_BE] = sc->sc_ac2q[WME_AC_BK];
|
|
|
|
sc->sc_ac2q[WME_AC_VI] = sc->sc_ac2q[WME_AC_BK];
|
|
|
|
sc->sc_ac2q[WME_AC_VO] = sc->sc_ac2q[WME_AC_BK];
|
|
|
|
}
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
/*
|
2012-07-31 03:09:48 +00:00
|
|
|
* Attach the TX completion function.
|
|
|
|
*
|
|
|
|
* The non-EDMA chips may have some special case optimisations;
|
|
|
|
* this method gives everyone a chance to attach cleanly.
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
2012-07-31 03:09:48 +00:00
|
|
|
sc->sc_tx.xmit_attach_comp_func(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup rate control. Some rate control modules
|
|
|
|
* call back to change the anntena state so expose
|
|
|
|
* the necessary entry points.
|
|
|
|
* XXX maybe belongs in struct ath_ratectrl?
|
|
|
|
*/
|
|
|
|
sc->sc_setdefantenna = ath_setdefantenna;
|
|
|
|
sc->sc_rc = ath_rate_attach(sc);
|
|
|
|
if (sc->sc_rc == NULL) {
|
|
|
|
error = EIO;
|
2004-04-02 23:47:39 +00:00
|
|
|
goto bad2;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
/* Attach DFS module */
|
|
|
|
if (! ath_dfs_attach(sc)) {
|
2011-12-26 05:26:35 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: unable to attach DFS\n", __func__);
|
2011-06-01 20:09:49 +00:00
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
|
2013-01-02 03:59:02 +00:00
|
|
|
/* Attach spectral module */
|
|
|
|
if (ath_spectral_attach(sc) < 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: unable to attach spectral\n", __func__);
|
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
/* Attach bluetooth coexistence module */
|
|
|
|
if (ath_btcoex_attach(sc) < 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: unable to attach bluetooth coexistence\n", __func__);
|
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
|
2013-06-12 14:52:57 +00:00
|
|
|
/* Attach LNA diversity module */
|
|
|
|
if (ath_lna_div_attach(sc) < 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: unable to attach LNA diversity\n", __func__);
|
|
|
|
error = EIO;
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
/* Start DFS processing tasklet */
|
|
|
|
TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc);
|
|
|
|
|
Flesh out configurable hardware based LED blinking.
The hardware (MAC) LED blinking involves a few things:
* Selecting which GPIO pins map to the MAC "power" and "network" lines;
* Configuring the MAC LED state (associated, scanning, idle);
* Configuring the MAC LED blinking type and speed.
The AR5416 HAL configures the normal blinking setup - ie, blink rate based
on TX/RX throughput. The default AR5212 HAL doesn't program in any
specific blinking type, but the default of 0 is the same.
This code introduces a few things:
* The hardware led override is configured via sysctl 'hardled';
* The MAC network and power LED GPIO lines can be set, or left at -1
if needed. This is intended to allow only one of the hardware MUX
entries to be configured (eg for PCIe cards which only have one LED
exposed.)
TODO:
* For AR2417, the software LED blinking involves software blinking the
Network LED. For the AR5416 and later, this can just be configured
as a GPIO output line. I'll chase that up with a subsequent commit.
* Add another software LED blink for "Link", separate from "activity",
which blinks based on the association state. This would make my
D-Link DWA-552 have consistent and useful LED behaviour (as they're
marked "Link" and "Activity."
* Don't expose the hardware LED override unless it's an AR5416 or later,
as the previous generation hardware doesn't have this multiplexing
setup.
2011-12-26 07:47:05 +00:00
|
|
|
/* Configure LED state */
|
2005-01-18 19:03:04 +00:00
|
|
|
sc->sc_blinking = 0;
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_ledstate = 1;
|
2005-01-18 19:03:04 +00:00
|
|
|
sc->sc_ledon = 0; /* low true */
|
|
|
|
sc->sc_ledidle = (2700*hz)/1000; /* 2.7sec */
|
|
|
|
callout_init(&sc->sc_ledtimer, CALLOUT_MPSAFE);
|
Flesh out configurable hardware based LED blinking.
The hardware (MAC) LED blinking involves a few things:
* Selecting which GPIO pins map to the MAC "power" and "network" lines;
* Configuring the MAC LED state (associated, scanning, idle);
* Configuring the MAC LED blinking type and speed.
The AR5416 HAL configures the normal blinking setup - ie, blink rate based
on TX/RX throughput. The default AR5212 HAL doesn't program in any
specific blinking type, but the default of 0 is the same.
This code introduces a few things:
* The hardware led override is configured via sysctl 'hardled';
* The MAC network and power LED GPIO lines can be set, or left at -1
if needed. This is intended to allow only one of the hardware MUX
entries to be configured (eg for PCIe cards which only have one LED
exposed.)
TODO:
* For AR2417, the software LED blinking involves software blinking the
Network LED. For the AR5416 and later, this can just be configured
as a GPIO output line. I'll chase that up with a subsequent commit.
* Add another software LED blink for "Link", separate from "activity",
which blinks based on the association state. This would make my
D-Link DWA-552 have consistent and useful LED behaviour (as they're
marked "Link" and "Activity."
* Don't expose the hardware LED override unless it's an AR5416 or later,
as the previous generation hardware doesn't have this multiplexing
setup.
2011-12-26 07:47:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Don't setup hardware-based blinking.
|
|
|
|
*
|
|
|
|
* Although some NICs may have this configured in the
|
|
|
|
* default reset register values, the user may wish
|
|
|
|
* to alter which pins have which function.
|
|
|
|
*
|
|
|
|
* The reference driver attaches the MAC network LED to GPIO1 and
|
|
|
|
* the MAC power LED to GPIO2. However, the DWA-552 cardbus
|
|
|
|
* NIC has these reversed.
|
|
|
|
*/
|
|
|
|
sc->sc_hardled = (1 == 0);
|
|
|
|
sc->sc_led_net_pin = -1;
|
|
|
|
sc->sc_led_pwr_pin = -1;
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Auto-enable soft led processing for IBM cards and for
|
|
|
|
* 5211 minipci cards. Users can also manually enable/disable
|
|
|
|
* support with a sysctl.
|
|
|
|
*/
|
|
|
|
sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID);
|
2011-12-26 05:46:22 +00:00
|
|
|
ath_led_config(sc);
|
2011-12-26 06:25:12 +00:00
|
|
|
ath_hal_setledstate(ah, HAL_LED_INIT);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
ifp->if_softc = sc;
|
|
|
|
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
ifp->if_transmit = ath_transmit;
|
|
|
|
ifp->if_qflush = ath_qflush;
|
2003-06-23 17:01:19 +00:00
|
|
|
ifp->if_ioctl = ath_ioctl;
|
|
|
|
ifp->if_init = ath_init;
|
2010-05-03 07:32:50 +00:00
|
|
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
|
|
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
2004-08-01 23:58:04 +00:00
|
|
|
IFQ_SET_READY(&ifp->if_snd);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
ic->ic_ifp = ifp;
|
2003-06-23 17:01:19 +00:00
|
|
|
/* XXX not right but it's not used anywhere important */
|
|
|
|
ic->ic_phytype = IEEE80211_T_OFDM;
|
|
|
|
ic->ic_opmode = IEEE80211_M_STA;
|
2004-12-08 17:34:36 +00:00
|
|
|
ic->ic_caps =
|
2008-05-12 00:15:30 +00:00
|
|
|
IEEE80211_C_STA /* station mode */
|
|
|
|
| IEEE80211_C_IBSS /* ibss, nee adhoc, mode */
|
2003-10-17 21:55:53 +00:00
|
|
|
| IEEE80211_C_HOSTAP /* hostap mode */
|
|
|
|
| IEEE80211_C_MONITOR /* monitor mode */
|
2006-02-09 21:42:53 +00:00
|
|
|
| IEEE80211_C_AHDEMO /* adhoc demo mode */
|
2008-04-20 20:35:46 +00:00
|
|
|
| IEEE80211_C_WDS /* 4-address traffic works */
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
| IEEE80211_C_MBSS /* mesh point link mode */
|
2003-10-17 21:55:53 +00:00
|
|
|
| IEEE80211_C_SHPREAMBLE /* short preamble supported */
|
2004-12-08 17:34:36 +00:00
|
|
|
| IEEE80211_C_SHSLOT /* short slot time supported */
|
|
|
|
| IEEE80211_C_WPA /* capable of WPA1+WPA2 */
|
2012-06-14 04:14:06 +00:00
|
|
|
#ifndef ATH_ENABLE_11N
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
| IEEE80211_C_BGSCAN /* capable of bg scanning */
|
2012-06-14 04:14:06 +00:00
|
|
|
#endif
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
| IEEE80211_C_TXFRAG /* handle tx frags */
|
2011-06-26 13:43:15 +00:00
|
|
|
#ifdef ATH_ENABLE_DFS
|
2011-12-26 05:26:35 +00:00
|
|
|
| IEEE80211_C_DFS /* Enable radar detection */
|
2011-06-26 13:43:15 +00:00
|
|
|
#endif
|
2004-04-02 23:37:00 +00:00
|
|
|
;
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Query the hal to figure out h/w crypto support.
|
|
|
|
*/
|
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_WEP))
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_OCB))
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_AES_OCB;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_AES_CCM))
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_AES_CCM;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_CKIP))
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_CKIP;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_TKIP)) {
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIP;
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Check if h/w does the MIC and/or whether the
|
|
|
|
* separate key cache entries are required to
|
|
|
|
* handle both tx+rx MIC keys.
|
|
|
|
*/
|
|
|
|
if (ath_hal_ciphersupported(ah, HAL_CIPHER_MIC))
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIPMIC;
|
2006-09-18 16:26:19 +00:00
|
|
|
/*
|
|
|
|
* If the h/w supports storing tx+rx MIC keys
|
|
|
|
* in one cache slot automatically enable use.
|
|
|
|
*/
|
|
|
|
if (ath_hal_hastkipsplit(ah) ||
|
|
|
|
!ath_hal_settkipsplit(ah, AH_FALSE))
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_splitmic = 1;
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
|
|
|
* If the h/w can do TKIP MIC together with WME then
|
|
|
|
* we use it; otherwise we force the MIC to be done
|
|
|
|
* in software by the net80211 layer.
|
|
|
|
*/
|
|
|
|
if (ath_hal_haswmetkipmic(ah))
|
|
|
|
sc->sc_wmetkipmic = 1;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2005-06-06 16:39:21 +00:00
|
|
|
sc->sc_hasclrkey = ath_hal_ciphersupported(ah, HAL_CIPHER_CLR);
|
2010-02-08 20:23:20 +00:00
|
|
|
/*
|
2010-02-10 11:12:39 +00:00
|
|
|
* Check for multicast key search support.
|
2010-02-08 20:23:20 +00:00
|
|
|
*/
|
|
|
|
if (ath_hal_hasmcastkeysearch(sc->sc_ah) &&
|
|
|
|
!ath_hal_getmcastkeysearch(sc->sc_ah)) {
|
|
|
|
ath_hal_setmcastkeysearch(sc->sc_ah, 1);
|
|
|
|
}
|
2005-06-06 16:39:21 +00:00
|
|
|
sc->sc_mcastkey = ath_hal_getmcastkeysearch(ah);
|
2006-09-18 16:26:19 +00:00
|
|
|
/*
|
|
|
|
* Mark key cache slots associated with global keys
|
|
|
|
* as in use. If we knew TKIP was not to be used we
|
|
|
|
* could leave the +32, +64, and +32+64 slots free.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
|
|
|
|
setbit(sc->sc_keymap, i);
|
|
|
|
setbit(sc->sc_keymap, i+64);
|
|
|
|
if (sc->sc_splitmic) {
|
|
|
|
setbit(sc->sc_keymap, i+32);
|
|
|
|
setbit(sc->sc_keymap, i+32+64);
|
|
|
|
}
|
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* TPC support can be done either with a global cap or
|
|
|
|
* per-packet support. The latter is not available on
|
|
|
|
* all parts. We're a bit pedantic here as all parts
|
|
|
|
* support a global cap.
|
|
|
|
*/
|
2005-07-24 05:11:39 +00:00
|
|
|
if (ath_hal_hastpc(ah) || ath_hal_hastxpowlimit(ah))
|
2004-12-08 17:34:36 +00:00
|
|
|
ic->ic_caps |= IEEE80211_C_TXPMGT;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Mark WME capability only if we have sufficient
|
|
|
|
* hardware queues to do proper priority scheduling.
|
|
|
|
*/
|
|
|
|
if (sc->sc_ac2q[WME_AC_BE] != sc->sc_ac2q[WME_AC_BK])
|
|
|
|
ic->ic_caps |= IEEE80211_C_WME;
|
|
|
|
/*
|
2005-06-06 16:39:21 +00:00
|
|
|
* Check for misc other capabilities.
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
|
|
|
if (ath_hal_hasbursting(ah))
|
|
|
|
ic->ic_caps |= IEEE80211_C_BURST;
|
2008-04-20 20:35:46 +00:00
|
|
|
sc->sc_hasbmask = ath_hal_hasbssidmask(ah);
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah);
|
2008-04-20 20:35:46 +00:00
|
|
|
sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
|
2011-04-04 14:52:31 +00:00
|
|
|
sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah);
|
2011-09-08 01:23:05 +00:00
|
|
|
sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah);
|
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
2013-05-21 18:02:54 +00:00
|
|
|
sc->sc_hasenforcetxop = ath_hal_hasenforcetxop(ah);
|
2013-06-05 00:45:19 +00:00
|
|
|
sc->sc_rx_lnamixer = ath_hal_hasrxlnamixer(ah);
|
2013-06-12 14:52:57 +00:00
|
|
|
sc->sc_hasdivcomb = ath_hal_hasdivantcomb(ah);
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (ath_hal_hasfastframes(ah))
|
|
|
|
ic->ic_caps |= IEEE80211_C_FF;
|
2009-01-28 18:00:22 +00:00
|
|
|
wmodes = ath_hal_getwirelessmodes(ah);
|
2008-10-27 18:30:33 +00:00
|
|
|
if (wmodes & (HAL_MODE_108G|HAL_MODE_TURBO))
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ic->ic_caps |= IEEE80211_C_TURBOP;
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (ath_hal_macversion(ah) > 0x78) {
|
|
|
|
ic->ic_caps |= IEEE80211_C_TDMA; /* capable of TDMA */
|
|
|
|
ic->ic_tdma_update = ath_tdma_update;
|
|
|
|
}
|
|
|
|
#endif
|
2011-02-09 15:43:38 +00:00
|
|
|
|
2012-03-10 04:14:04 +00:00
|
|
|
/*
|
|
|
|
* TODO: enforce that at least this many frames are available
|
|
|
|
* in the txbuf list before allowing data frames (raw or
|
|
|
|
* otherwise) to be transmitted.
|
|
|
|
*/
|
|
|
|
sc->sc_txq_data_minfree = 10;
|
|
|
|
/*
|
|
|
|
* Leave this as default to maintain legacy behaviour.
|
|
|
|
* Shortening the cabq/mcastq may end up causing some
|
|
|
|
* undesirable behaviour.
|
|
|
|
*/
|
|
|
|
sc->sc_txq_mcastq_maxdepth = ath_txbuf;
|
|
|
|
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
/*
|
|
|
|
* How deep can the node software TX queue get whilst it's asleep.
|
|
|
|
*/
|
|
|
|
sc->sc_txq_node_psq_maxdepth = 16;
|
|
|
|
|
2013-05-07 07:52:18 +00:00
|
|
|
/*
|
|
|
|
* Default the maximum queue depth for a given node
|
|
|
|
* to 1/4'th the TX buffers, or 64, whichever
|
|
|
|
* is larger.
|
|
|
|
*/
|
|
|
|
sc->sc_txq_node_maxdepth = MAX(64, ath_txbuf / 4);
|
|
|
|
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
/* Enable CABQ by default */
|
|
|
|
sc->sc_cabq_enable = 1;
|
|
|
|
|
2012-02-10 10:01:09 +00:00
|
|
|
/*
|
|
|
|
* Allow the TX and RX chainmasks to be overridden by
|
|
|
|
* environment variables and/or device.hints.
|
|
|
|
*
|
|
|
|
* This must be done early - before the hardware is
|
|
|
|
* calibrated or before the 802.11n stream calculation
|
|
|
|
* is done.
|
|
|
|
*/
|
|
|
|
if (resource_int_value(device_get_name(sc->sc_dev),
|
|
|
|
device_get_unit(sc->sc_dev), "rx_chainmask",
|
|
|
|
&rx_chainmask) == 0) {
|
|
|
|
device_printf(sc->sc_dev, "Setting RX chainmask to 0x%x\n",
|
|
|
|
rx_chainmask);
|
|
|
|
(void) ath_hal_setrxchainmask(sc->sc_ah, rx_chainmask);
|
|
|
|
}
|
|
|
|
if (resource_int_value(device_get_name(sc->sc_dev),
|
|
|
|
device_get_unit(sc->sc_dev), "tx_chainmask",
|
|
|
|
&tx_chainmask) == 0) {
|
|
|
|
device_printf(sc->sc_dev, "Setting TX chainmask to 0x%x\n",
|
|
|
|
tx_chainmask);
|
2012-02-10 10:09:16 +00:00
|
|
|
(void) ath_hal_settxchainmask(sc->sc_ah, tx_chainmask);
|
2012-02-10 10:01:09 +00:00
|
|
|
}
|
|
|
|
|
2013-04-19 21:49:11 +00:00
|
|
|
/*
|
|
|
|
* Query the TX/RX chainmask configuration.
|
|
|
|
*
|
|
|
|
* This is only relevant for 11n devices.
|
|
|
|
*/
|
|
|
|
ath_hal_getrxchainmask(ah, &sc->sc_rxchainmask);
|
|
|
|
ath_hal_gettxchainmask(ah, &sc->sc_txchainmask);
|
|
|
|
|
2012-07-31 23:54:15 +00:00
|
|
|
/*
|
|
|
|
* Disable MRR with protected frames by default.
|
|
|
|
* Only 802.11n series NICs can handle this.
|
|
|
|
*/
|
|
|
|
sc->sc_mrrprot = 0; /* XXX should be a capability */
|
|
|
|
|
2012-11-03 22:12:35 +00:00
|
|
|
/*
|
|
|
|
* Query the enterprise mode information the HAL.
|
|
|
|
*/
|
|
|
|
if (ath_hal_getcapability(ah, HAL_CAP_ENTERPRISE_MODE, 0,
|
|
|
|
&sc->sc_ent_cfg) == HAL_OK)
|
|
|
|
sc->sc_use_ent = 1;
|
|
|
|
|
2011-03-27 08:47:55 +00:00
|
|
|
#ifdef ATH_ENABLE_11N
|
2011-02-09 15:43:38 +00:00
|
|
|
/*
|
|
|
|
* Query HT capabilities
|
|
|
|
*/
|
|
|
|
if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, NULL) == HAL_OK &&
|
|
|
|
(wmodes & (HAL_MODE_HT20 | HAL_MODE_HT40))) {
|
2013-04-19 06:59:10 +00:00
|
|
|
uint32_t rxs, txs;
|
2011-02-09 15:43:38 +00:00
|
|
|
|
|
|
|
device_printf(sc->sc_dev, "[HT] enabling HT modes\n");
|
2012-07-31 23:54:15 +00:00
|
|
|
|
|
|
|
sc->sc_mrrprot = 1; /* XXX should be a capability */
|
|
|
|
|
2011-12-26 05:26:35 +00:00
|
|
|
ic->ic_htcaps = IEEE80211_HTC_HT /* HT operation */
|
|
|
|
| IEEE80211_HTC_AMPDU /* A-MPDU tx/rx */
|
|
|
|
| IEEE80211_HTC_AMSDU /* A-MSDU tx/rx */
|
|
|
|
| IEEE80211_HTCAP_MAXAMSDU_3839
|
|
|
|
/* max A-MSDU length */
|
|
|
|
| IEEE80211_HTCAP_SMPS_OFF; /* SM power save off */
|
2011-02-09 15:43:38 +00:00
|
|
|
;
|
|
|
|
|
2011-05-29 00:17:13 +00:00
|
|
|
/*
|
|
|
|
* Enable short-GI for HT20 only if the hardware
|
|
|
|
* advertises support.
|
|
|
|
* Notably, anything earlier than the AR9287 doesn't.
|
|
|
|
*/
|
|
|
|
if ((ath_hal_getcapability(ah,
|
|
|
|
HAL_CAP_HT20_SGI, 0, NULL) == HAL_OK) &&
|
|
|
|
(wmodes & HAL_MODE_HT20)) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"[HT] enabling short-GI in 20MHz mode\n");
|
|
|
|
ic->ic_htcaps |= IEEE80211_HTCAP_SHORTGI20;
|
|
|
|
}
|
|
|
|
|
2011-02-09 15:43:38 +00:00
|
|
|
if (wmodes & HAL_MODE_HT40)
|
|
|
|
ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40
|
|
|
|
| IEEE80211_HTCAP_SHORTGI40;
|
|
|
|
|
|
|
|
/*
|
2011-12-26 05:26:35 +00:00
|
|
|
* TX/RX streams need to be taken into account when
|
|
|
|
* negotiating which MCS rates it'll receive and
|
2011-02-09 15:43:38 +00:00
|
|
|
* what MCS rates are available for TX.
|
|
|
|
*/
|
2012-01-31 22:27:35 +00:00
|
|
|
(void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 0, &txs);
|
|
|
|
(void) ath_hal_getcapability(ah, HAL_CAP_STREAMS, 1, &rxs);
|
2011-02-09 15:43:38 +00:00
|
|
|
ic->ic_txstream = txs;
|
|
|
|
ic->ic_rxstream = rxs;
|
|
|
|
|
2013-02-27 00:25:44 +00:00
|
|
|
/*
|
|
|
|
* Setup TX and RX STBC based on what the HAL allows and
|
|
|
|
* the currently configured chainmask set.
|
|
|
|
* Ie - don't enable STBC TX if only one chain is enabled.
|
|
|
|
* STBC RX is fine on a single RX chain; it just won't
|
|
|
|
* provide any real benefit.
|
|
|
|
*/
|
|
|
|
if (ath_hal_getcapability(ah, HAL_CAP_RX_STBC, 0,
|
|
|
|
NULL) == HAL_OK) {
|
|
|
|
sc->sc_rx_stbc = 1;
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"[HT] 1 stream STBC receive enabled\n");
|
|
|
|
ic->ic_htcaps |= IEEE80211_HTCAP_RXSTBC_1STREAM;
|
|
|
|
}
|
|
|
|
if (txs > 1 && ath_hal_getcapability(ah, HAL_CAP_TX_STBC, 0,
|
|
|
|
NULL) == HAL_OK) {
|
|
|
|
sc->sc_tx_stbc = 1;
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"[HT] 1 stream STBC transmit enabled\n");
|
|
|
|
ic->ic_htcaps |= IEEE80211_HTCAP_TXSTBC;
|
|
|
|
}
|
|
|
|
|
2012-04-07 02:51:53 +00:00
|
|
|
(void) ath_hal_getcapability(ah, HAL_CAP_RTS_AGGR_LIMIT, 1,
|
|
|
|
&sc->sc_rts_aggr_limit);
|
|
|
|
if (sc->sc_rts_aggr_limit != (64 * 1024))
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"[HT] RTS aggregates limited to %d KiB\n",
|
|
|
|
sc->sc_rts_aggr_limit / 1024);
|
|
|
|
|
2011-12-26 05:26:35 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"[HT] %d RX streams; %d TX streams\n", rxs, txs);
|
2011-02-09 15:43:38 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-06-24 08:28:06 +00:00
|
|
|
/*
|
|
|
|
* Initial aggregation settings.
|
|
|
|
*/
|
2013-05-21 18:13:57 +00:00
|
|
|
sc->sc_hwq_limit_aggr = ATH_AGGR_MIN_QDEPTH;
|
|
|
|
sc->sc_hwq_limit_nonaggr = ATH_NONAGGR_MIN_QDEPTH;
|
2012-06-24 08:28:06 +00:00
|
|
|
sc->sc_tid_hwq_lo = ATH_AGGR_SCHED_LOW;
|
|
|
|
sc->sc_tid_hwq_hi = ATH_AGGR_SCHED_HIGH;
|
2013-02-21 06:18:40 +00:00
|
|
|
sc->sc_aggr_limit = ATH_AGGR_MAXSIZE;
|
2013-02-21 06:38:49 +00:00
|
|
|
sc->sc_delim_min_pad = 0;
|
2012-06-24 08:28:06 +00:00
|
|
|
|
2011-11-09 22:39:44 +00:00
|
|
|
/*
|
|
|
|
* Check if the hardware requires PCI register serialisation.
|
|
|
|
* Some of the Owl based MACs require this.
|
|
|
|
*/
|
|
|
|
if (mp_ncpus > 1 &&
|
|
|
|
ath_hal_getcapability(ah, HAL_CAP_SERIALISE_WAR,
|
|
|
|
0, NULL) == HAL_OK) {
|
|
|
|
sc->sc_ah->ah_config.ah_serialise_reg_war = 1;
|
2011-12-26 05:26:35 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"Enabling register serialisation\n");
|
2011-11-09 22:39:44 +00:00
|
|
|
}
|
|
|
|
|
2013-03-19 19:32:28 +00:00
|
|
|
/*
|
|
|
|
* Initialise the deferred completed RX buffer list.
|
|
|
|
*/
|
2013-04-16 20:21:02 +00:00
|
|
|
TAILQ_INIT(&sc->sc_rx_rxlist[HAL_RX_QUEUE_HP]);
|
|
|
|
TAILQ_INIT(&sc->sc_rx_rxlist[HAL_RX_QUEUE_LP]);
|
2013-03-19 19:32:28 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Indicate we need the 802.11 header padded to a
|
|
|
|
* 32-bit boundary for 4-address and QoS frames.
|
|
|
|
*/
|
|
|
|
ic->ic_flags |= IEEE80211_F_DATAPAD;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Query the hal about antenna support.
|
|
|
|
*/
|
|
|
|
sc->sc_defant = ath_hal_getdefantenna(ah);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not all chips have the VEOL support we want to
|
|
|
|
* use with IBSS beacons; check here for it.
|
|
|
|
*/
|
|
|
|
sc->sc_hasveol = ath_hal_hasveol(ah);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
/* get mac address from hardware */
|
2009-03-29 17:59:14 +00:00
|
|
|
ath_hal_getmac(ah, macaddr);
|
2008-04-20 20:35:46 +00:00
|
|
|
if (sc->sc_hasbmask)
|
|
|
|
ath_hal_getbssidmask(ah, sc->sc_hwbssidmask);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
/* NB: used to size node table key mapping array */
|
|
|
|
ic->ic_max_keyix = sc->sc_keymax;
|
2003-06-23 17:01:19 +00:00
|
|
|
/* call MI attach routine. */
|
2009-03-29 17:59:14 +00:00
|
|
|
ieee80211_ifattach(ic, macaddr);
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_setregdomain = ath_setregdomain;
|
|
|
|
ic->ic_getradiocaps = ath_getradiocaps;
|
|
|
|
sc->sc_opmode = HAL_M_STA;
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/* override default methods */
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_newassoc = ath_newassoc;
|
|
|
|
ic->ic_updateslot = ath_updateslot;
|
|
|
|
ic->ic_wme.wme_update = ath_wme_update;
|
|
|
|
ic->ic_vap_create = ath_vap_create;
|
|
|
|
ic->ic_vap_delete = ath_vap_delete;
|
|
|
|
ic->ic_raw_xmit = ath_raw_xmit;
|
|
|
|
ic->ic_update_mcast = ath_update_mcast;
|
|
|
|
ic->ic_update_promisc = ath_update_promisc;
|
2003-06-23 17:01:19 +00:00
|
|
|
ic->ic_node_alloc = ath_node_alloc;
|
2004-04-03 00:06:23 +00:00
|
|
|
sc->sc_node_free = ic->ic_node_free;
|
2003-06-23 17:01:19 +00:00
|
|
|
ic->ic_node_free = ath_node_free;
|
2011-11-08 18:48:26 +00:00
|
|
|
sc->sc_node_cleanup = ic->ic_node_cleanup;
|
|
|
|
ic->ic_node_cleanup = ath_node_cleanup;
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ic->ic_node_getsignal = ath_node_getsignal;
|
|
|
|
ic->ic_scan_start = ath_scan_start;
|
|
|
|
ic->ic_scan_end = ath_scan_end;
|
|
|
|
ic->ic_set_channel = ath_set_channel;
|
2012-04-10 06:25:11 +00:00
|
|
|
#ifdef ATH_ENABLE_11N
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
/* 802.11n specific - but just override anyway */
|
|
|
|
sc->sc_addba_request = ic->ic_addba_request;
|
|
|
|
sc->sc_addba_response = ic->ic_addba_response;
|
|
|
|
sc->sc_addba_stop = ic->ic_addba_stop;
|
|
|
|
sc->sc_bar_response = ic->ic_bar_response;
|
|
|
|
sc->sc_addba_response_timeout = ic->ic_addba_response_timeout;
|
|
|
|
|
|
|
|
ic->ic_addba_request = ath_addba_request;
|
|
|
|
ic->ic_addba_response = ath_addba_response;
|
|
|
|
ic->ic_addba_response_timeout = ath_addba_response_timeout;
|
|
|
|
ic->ic_addba_stop = ath_addba_stop;
|
|
|
|
ic->ic_bar_response = ath_bar_response;
|
|
|
|
|
2012-04-10 06:25:11 +00:00
|
|
|
ic->ic_update_chw = ath_update_chw;
|
|
|
|
#endif /* ATH_ENABLE_11N */
|
|
|
|
|
2012-06-24 07:01:49 +00:00
|
|
|
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
|
|
|
|
/*
|
|
|
|
* There's one vendor bitmap entry in the RX radiotap
|
|
|
|
* header; make sure that's taken into account.
|
|
|
|
*/
|
|
|
|
ieee80211_radiotap_attachv(ic,
|
|
|
|
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), 0,
|
|
|
|
ATH_TX_RADIOTAP_PRESENT,
|
|
|
|
&sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), 1,
|
|
|
|
ATH_RX_RADIOTAP_PRESENT);
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* No vendor bitmap/extensions are present.
|
|
|
|
*/
|
2009-05-20 20:00:40 +00:00
|
|
|
ieee80211_radiotap_attach(ic,
|
|
|
|
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
|
|
|
|
ATH_TX_RADIOTAP_PRESENT,
|
|
|
|
&sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
|
|
|
|
ATH_RX_RADIOTAP_PRESENT);
|
2012-06-24 07:01:49 +00:00
|
|
|
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
|
2009-05-20 20:00:40 +00:00
|
|
|
|
2012-11-07 06:29:45 +00:00
|
|
|
/*
|
|
|
|
* Setup the ALQ logging if required
|
|
|
|
*/
|
2012-11-07 16:34:09 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
2012-11-07 06:29:45 +00:00
|
|
|
if_ath_alq_init(&sc->sc_alq, device_get_nameunit(sc->sc_dev));
|
2012-11-16 19:57:16 +00:00
|
|
|
if_ath_alq_setcfg(&sc->sc_alq,
|
|
|
|
sc->sc_ah->ah_macVersion,
|
|
|
|
sc->sc_ah->ah_macRev,
|
|
|
|
sc->sc_ah->ah_phyRev,
|
|
|
|
sc->sc_ah->ah_magic);
|
2012-11-07 06:29:45 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-23 05:34:29 +00:00
|
|
|
/*
|
|
|
|
* Setup dynamic sysctl's now that country code and
|
|
|
|
* regdomain are available from the hal.
|
|
|
|
*/
|
|
|
|
ath_sysctlattach(sc);
|
2010-08-14 14:18:02 +00:00
|
|
|
ath_sysctl_stats_attach(sc);
|
2011-06-23 02:38:36 +00:00
|
|
|
ath_sysctl_hal_attach(sc);
|
2003-09-05 22:22:49 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
if (bootverbose)
|
|
|
|
ieee80211_announce(ic);
|
|
|
|
ath_announce(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
return 0;
|
2004-04-02 23:47:39 +00:00
|
|
|
bad2:
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_tx_cleanup(sc);
|
2004-04-02 23:47:39 +00:00
|
|
|
ath_desc_free(sc);
|
2012-07-23 03:52:18 +00:00
|
|
|
ath_txdma_teardown(sc);
|
2012-07-09 08:37:59 +00:00
|
|
|
ath_rxdma_teardown(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
bad:
|
|
|
|
if (ah)
|
|
|
|
ath_hal_detach(ah);
|
2012-11-28 07:12:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* To work around scoping issues with CURVNET_SET/CURVNET_RESTORE..
|
|
|
|
*/
|
|
|
|
if (ifp != NULL && ifp->if_vnet) {
|
2012-10-28 18:46:06 +00:00
|
|
|
CURVNET_SET(ifp->if_vnet);
|
2005-06-10 16:49:24 +00:00
|
|
|
if_free(ifp);
|
2012-10-28 18:46:06 +00:00
|
|
|
CURVNET_RESTORE();
|
2012-11-28 07:12:08 +00:00
|
|
|
} else if (ifp != NULL)
|
|
|
|
if_free(ifp);
|
2003-06-23 17:01:19 +00:00
|
|
|
sc->sc_invalid = 1;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ath_detach(struct ath_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2010-02-19 18:23:45 +00:00
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* NB: the order of these is important:
|
2008-05-28 23:55:11 +00:00
|
|
|
* o stop the chip so no more interrupts will fire
|
2004-12-08 17:34:36 +00:00
|
|
|
* o call the 802.11 layer before detaching the hal to
|
|
|
|
* insure callbacks into the driver to delete global
|
|
|
|
* key cache entries can be handled
|
2008-05-28 23:55:11 +00:00
|
|
|
* o free the taskqueue which drains any pending tasks
|
2004-12-08 17:34:36 +00:00
|
|
|
* o reclaim the tx queue data structures after calling
|
|
|
|
* the 802.11 layer as we'll get called back to reclaim
|
|
|
|
* node state and potentially want to use them
|
|
|
|
* o to cleanup the tx queues the hal is called, so detach
|
|
|
|
* it last
|
|
|
|
* Other than that, it's straightforward...
|
|
|
|
*/
|
2008-05-28 23:55:11 +00:00
|
|
|
ath_stop(ifp);
|
2008-04-20 20:35:46 +00:00
|
|
|
ieee80211_ifdetach(ifp->if_l2com);
|
2008-05-28 23:55:11 +00:00
|
|
|
taskqueue_free(sc->sc_tq);
|
2006-02-09 21:28:11 +00:00
|
|
|
#ifdef ATH_TX99_DIAG
|
|
|
|
if (sc->sc_tx99 != NULL)
|
|
|
|
sc->sc_tx99->detach(sc->sc_tx99);
|
|
|
|
#endif
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_rate_detach(sc->sc_rc);
|
2012-11-07 16:34:09 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
2012-11-07 06:29:45 +00:00
|
|
|
if_ath_alq_tidyup(&sc->sc_alq);
|
|
|
|
#endif
|
2013-06-12 14:52:57 +00:00
|
|
|
ath_lna_div_detach(sc);
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
ath_btcoex_detach(sc);
|
2013-01-02 03:59:02 +00:00
|
|
|
ath_spectral_detach(sc);
|
2011-06-01 20:09:49 +00:00
|
|
|
ath_dfs_detach(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_desc_free(sc);
|
2012-07-28 04:40:52 +00:00
|
|
|
ath_txdma_teardown(sc);
|
2012-07-09 08:37:59 +00:00
|
|
|
ath_rxdma_teardown(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_tx_cleanup(sc);
|
2008-05-28 23:55:11 +00:00
|
|
|
ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */
|
2012-10-28 18:46:06 +00:00
|
|
|
|
|
|
|
CURVNET_SET(ifp->if_vnet);
|
2005-09-16 10:09:23 +00:00
|
|
|
if_free(ifp);
|
2012-10-28 18:46:06 +00:00
|
|
|
CURVNET_RESTORE();
|
2003-10-14 22:51:45 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
|
|
|
* MAC address handling for multiple BSS on the same radio.
|
|
|
|
* The first vap uses the MAC address from the EEPROM. For
|
|
|
|
* subsequent vap's we set the U/L bit (bit 1) in the MAC
|
|
|
|
* address and use the next six bits as an index.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
assign_address(struct ath_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN], int clone)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (clone && sc->sc_hasbmask) {
|
|
|
|
/* NB: we only do this if h/w supports multiple bssid */
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
if ((sc->sc_bssidmask & (1<<i)) == 0)
|
|
|
|
break;
|
|
|
|
if (i != 0)
|
|
|
|
mac[0] |= (i << 2)|0x2;
|
|
|
|
} else
|
|
|
|
i = 0;
|
|
|
|
sc->sc_bssidmask |= 1<<i;
|
|
|
|
sc->sc_hwbssidmask[0] &= ~mac[0];
|
|
|
|
if (i == 0)
|
|
|
|
sc->sc_nbssid0++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reclaim_address(struct ath_softc *sc, const uint8_t mac[IEEE80211_ADDR_LEN])
|
|
|
|
{
|
|
|
|
int i = mac[0] >> 2;
|
|
|
|
uint8_t mask;
|
|
|
|
|
|
|
|
if (i != 0 || --sc->sc_nbssid0 == 0) {
|
|
|
|
sc->sc_bssidmask &= ~(1<<i);
|
|
|
|
/* recalculate bssid mask from remaining addresses */
|
|
|
|
mask = 0xff;
|
|
|
|
for (i = 1; i < 8; i++)
|
|
|
|
if (sc->sc_bssidmask & (1<<i))
|
|
|
|
mask &= ~((i<<2)|0x2);
|
|
|
|
sc->sc_hwbssidmask[0] |= mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Assign a beacon xmit slot. We try to space out
|
|
|
|
* assignments so when beacons are staggered the
|
|
|
|
* traffic coming out of the cab q has maximal time
|
|
|
|
* to go out before the next beacon is scheduled.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
assign_bslot(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
u_int slot, free;
|
|
|
|
|
|
|
|
free = 0;
|
|
|
|
for (slot = 0; slot < ATH_BCBUF; slot++)
|
|
|
|
if (sc->sc_bslot[slot] == NULL) {
|
|
|
|
if (sc->sc_bslot[(slot+1)%ATH_BCBUF] == NULL &&
|
|
|
|
sc->sc_bslot[(slot-1)%ATH_BCBUF] == NULL)
|
|
|
|
return slot;
|
|
|
|
free = slot;
|
|
|
|
/* NB: keep looking for a double slot */
|
|
|
|
}
|
|
|
|
return free;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211vap *
|
2011-12-17 10:23:17 +00:00
|
|
|
ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
|
|
|
enum ieee80211_opmode opmode, int flags,
|
|
|
|
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
|
|
|
const uint8_t mac0[IEEE80211_ADDR_LEN])
|
2008-04-20 20:35:46 +00:00
|
|
|
{
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_vap *avp;
|
|
|
|
struct ieee80211vap *vap;
|
|
|
|
uint8_t mac[IEEE80211_ADDR_LEN];
|
2011-12-17 10:23:17 +00:00
|
|
|
int needbeacon, error;
|
|
|
|
enum ieee80211_opmode ic_opmode;
|
2008-04-20 20:35:46 +00:00
|
|
|
|
|
|
|
avp = (struct ath_vap *) malloc(sizeof(struct ath_vap),
|
|
|
|
M_80211_VAP, M_WAITOK | M_ZERO);
|
|
|
|
needbeacon = 0;
|
|
|
|
IEEE80211_ADDR_COPY(mac, mac0);
|
|
|
|
|
|
|
|
ATH_LOCK(sc);
|
2009-05-06 23:49:55 +00:00
|
|
|
ic_opmode = opmode; /* default to opmode of new vap */
|
2008-04-20 20:35:46 +00:00
|
|
|
switch (opmode) {
|
|
|
|
case IEEE80211_M_STA:
|
2009-05-06 23:49:55 +00:00
|
|
|
if (sc->sc_nstavaps != 0) { /* XXX only 1 for now */
|
2008-04-20 20:35:46 +00:00
|
|
|
device_printf(sc->sc_dev, "only 1 sta vap supported\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (sc->sc_nvaps) {
|
|
|
|
/*
|
2009-05-06 23:49:55 +00:00
|
|
|
* With multiple vaps we must fall back
|
|
|
|
* to s/w beacon miss handling.
|
2008-04-20 20:35:46 +00:00
|
|
|
*/
|
|
|
|
flags |= IEEE80211_CLONE_NOBEACONS;
|
|
|
|
}
|
2009-05-06 23:49:55 +00:00
|
|
|
if (flags & IEEE80211_CLONE_NOBEACONS) {
|
|
|
|
/*
|
|
|
|
* Station mode w/o beacons are implemented w/ AP mode.
|
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
ic_opmode = IEEE80211_M_HOSTAP;
|
2009-05-06 23:49:55 +00:00
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
break;
|
|
|
|
case IEEE80211_M_IBSS:
|
|
|
|
if (sc->sc_nvaps != 0) { /* XXX only 1 for now */
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"only 1 ibss vap supported\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
needbeacon = 1;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_AHDEMO:
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (flags & IEEE80211_CLONE_TDMA) {
|
2009-05-06 23:49:55 +00:00
|
|
|
if (sc->sc_nvaps != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"only 1 tdma vap supported\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
2009-01-08 17:12:47 +00:00
|
|
|
needbeacon = 1;
|
|
|
|
flags |= IEEE80211_CLONE_NOBEACONS;
|
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
/* fall thru... */
|
2009-01-08 17:12:47 +00:00
|
|
|
#endif
|
2008-04-20 20:35:46 +00:00
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
if (sc->sc_nvaps != 0 && ic->ic_opmode != opmode) {
|
2009-05-06 23:49:55 +00:00
|
|
|
/*
|
|
|
|
* Adopt existing mode. Adding a monitor or ahdemo
|
|
|
|
* vap to an existing configuration is of dubious
|
|
|
|
* value but should be ok.
|
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
/* XXX not right for monitor mode */
|
|
|
|
ic_opmode = ic->ic_opmode;
|
2009-05-06 23:49:55 +00:00
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
break;
|
|
|
|
case IEEE80211_M_HOSTAP:
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
case IEEE80211_M_MBSS:
|
2008-04-20 20:35:46 +00:00
|
|
|
needbeacon = 1;
|
2009-05-06 23:49:55 +00:00
|
|
|
break;
|
2008-04-20 20:35:46 +00:00
|
|
|
case IEEE80211_M_WDS:
|
2009-05-06 23:49:55 +00:00
|
|
|
if (sc->sc_nvaps != 0 && ic->ic_opmode == IEEE80211_M_STA) {
|
2008-04-20 20:35:46 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"wds not supported in sta mode\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
2009-05-06 23:49:55 +00:00
|
|
|
/*
|
|
|
|
* Silently remove any request for a unique
|
|
|
|
* bssid; WDS vap's always share the local
|
|
|
|
* mac address.
|
|
|
|
*/
|
|
|
|
flags &= ~IEEE80211_CLONE_BSSID;
|
|
|
|
if (sc->sc_nvaps == 0)
|
|
|
|
ic_opmode = IEEE80211_M_HOSTAP;
|
|
|
|
else
|
|
|
|
ic_opmode = ic->ic_opmode;
|
2009-07-11 16:02:06 +00:00
|
|
|
break;
|
2008-04-20 20:35:46 +00:00
|
|
|
default:
|
|
|
|
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Check that a beacon buffer is available; the code below assumes it.
|
|
|
|
*/
|
2011-11-08 17:08:12 +00:00
|
|
|
if (needbeacon & TAILQ_EMPTY(&sc->sc_bbuf)) {
|
2008-04-20 20:35:46 +00:00
|
|
|
device_printf(sc->sc_dev, "no beacon buffer available\n");
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* STA, AHDEMO? */
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) {
|
2008-04-20 20:35:46 +00:00
|
|
|
assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID);
|
|
|
|
ath_hal_setbssidmask(sc->sc_ah, sc->sc_hwbssidmask);
|
|
|
|
}
|
|
|
|
|
|
|
|
vap = &avp->av_vap;
|
|
|
|
/* XXX can't hold mutex across if_alloc */
|
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
|
|
|
|
bssid, mac);
|
|
|
|
ATH_LOCK(sc);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev, "%s: error %d creating vap\n",
|
|
|
|
__func__, error);
|
|
|
|
goto bad2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* h/w crypto support */
|
|
|
|
vap->iv_key_alloc = ath_key_alloc;
|
|
|
|
vap->iv_key_delete = ath_key_delete;
|
|
|
|
vap->iv_key_set = ath_key_set;
|
|
|
|
vap->iv_key_update_begin = ath_key_update_begin;
|
|
|
|
vap->iv_key_update_end = ath_key_update_end;
|
|
|
|
|
|
|
|
/* override various methods */
|
|
|
|
avp->av_recv_mgmt = vap->iv_recv_mgmt;
|
|
|
|
vap->iv_recv_mgmt = ath_recv_mgmt;
|
|
|
|
vap->iv_reset = ath_reset_vap;
|
|
|
|
vap->iv_update_beacon = ath_beacon_update;
|
|
|
|
avp->av_newstate = vap->iv_newstate;
|
|
|
|
vap->iv_newstate = ath_newstate;
|
|
|
|
avp->av_bmiss = vap->iv_bmiss;
|
|
|
|
vap->iv_bmiss = ath_bmiss_vap;
|
|
|
|
|
2012-10-03 23:23:45 +00:00
|
|
|
avp->av_node_ps = vap->iv_node_ps;
|
|
|
|
vap->iv_node_ps = ath_node_powersave;
|
|
|
|
|
2012-10-28 21:13:12 +00:00
|
|
|
avp->av_set_tim = vap->iv_set_tim;
|
|
|
|
vap->iv_set_tim = ath_node_set_tim;
|
|
|
|
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
avp->av_recv_pspoll = vap->iv_recv_pspoll;
|
|
|
|
vap->iv_recv_pspoll = ath_node_recv_pspoll;
|
|
|
|
|
2011-05-30 14:57:00 +00:00
|
|
|
/* Set default parameters */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Anything earlier than some AR9300 series MACs don't
|
|
|
|
* support a smaller MPDU density.
|
|
|
|
*/
|
|
|
|
vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_8;
|
|
|
|
/*
|
|
|
|
* All NICs can handle the maximum size, however
|
|
|
|
* AR5416 based MACs can only TX aggregates w/ RTS
|
|
|
|
* protection when the total aggregate size is <= 8k.
|
|
|
|
* However, for now that's enforced by the TX path.
|
|
|
|
*/
|
|
|
|
vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
avp->av_bslot = -1;
|
|
|
|
if (needbeacon) {
|
|
|
|
/*
|
|
|
|
* Allocate beacon state and setup the q for buffered
|
|
|
|
* multicast frames. We know a beacon buffer is
|
|
|
|
* available because we checked above.
|
|
|
|
*/
|
2011-11-08 17:08:12 +00:00
|
|
|
avp->av_bcbuf = TAILQ_FIRST(&sc->sc_bbuf);
|
|
|
|
TAILQ_REMOVE(&sc->sc_bbuf, avp->av_bcbuf, bf_list);
|
2008-04-20 20:35:46 +00:00
|
|
|
if (opmode != IEEE80211_M_IBSS || !sc->sc_hasveol) {
|
|
|
|
/*
|
|
|
|
* Assign the vap to a beacon xmit slot. As above
|
|
|
|
* this cannot fail to find a free one.
|
|
|
|
*/
|
|
|
|
avp->av_bslot = assign_bslot(sc);
|
|
|
|
KASSERT(sc->sc_bslot[avp->av_bslot] == NULL,
|
|
|
|
("beacon slot %u not empty", avp->av_bslot));
|
|
|
|
sc->sc_bslot[avp->av_bslot] = vap;
|
|
|
|
sc->sc_nbcnvaps++;
|
|
|
|
}
|
|
|
|
if (sc->sc_hastsfadd && sc->sc_nbcnvaps > 0) {
|
|
|
|
/*
|
|
|
|
* Multple vaps are to transmit beacons and we
|
|
|
|
* have h/w support for TSF adjusting; enable
|
|
|
|
* use of staggered beacons.
|
|
|
|
*/
|
|
|
|
sc->sc_stagbeacons = 1;
|
|
|
|
}
|
|
|
|
ath_txq_init(sc, &avp->av_mcastq, ATH_TXQ_SWQ);
|
|
|
|
}
|
|
|
|
|
|
|
|
ic->ic_opmode = ic_opmode;
|
|
|
|
if (opmode != IEEE80211_M_WDS) {
|
|
|
|
sc->sc_nvaps++;
|
|
|
|
if (opmode == IEEE80211_M_STA)
|
|
|
|
sc->sc_nstavaps++;
|
2009-07-21 19:01:04 +00:00
|
|
|
if (opmode == IEEE80211_M_MBSS)
|
|
|
|
sc->sc_nmeshvaps++;
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
switch (ic_opmode) {
|
|
|
|
case IEEE80211_M_IBSS:
|
|
|
|
sc->sc_opmode = HAL_M_IBSS;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_STA:
|
|
|
|
sc->sc_opmode = HAL_M_STA;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_AHDEMO:
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (vap->iv_caps & IEEE80211_C_TDMA) {
|
|
|
|
sc->sc_tdma = 1;
|
|
|
|
/* NB: disable tsf adjust */
|
|
|
|
sc->sc_stagbeacons = 0;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* NB: adhoc demo mode is a pseudo mode; to the hal it's
|
|
|
|
* just ap mode.
|
|
|
|
*/
|
|
|
|
/* fall thru... */
|
|
|
|
#endif
|
2008-04-20 20:35:46 +00:00
|
|
|
case IEEE80211_M_HOSTAP:
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
case IEEE80211_M_MBSS:
|
2008-04-20 20:35:46 +00:00
|
|
|
sc->sc_opmode = HAL_M_HOSTAP;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
sc->sc_opmode = HAL_M_MONITOR;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* XXX should not happen */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (sc->sc_hastsfadd) {
|
|
|
|
/*
|
|
|
|
* Configure whether or not TSF adjust should be done.
|
|
|
|
*/
|
|
|
|
ath_hal_settsfadjust(sc->sc_ah, sc->sc_stagbeacons);
|
|
|
|
}
|
2009-01-08 17:12:47 +00:00
|
|
|
if (flags & IEEE80211_CLONE_NOBEACONS) {
|
|
|
|
/*
|
|
|
|
* Enable s/w beacon miss handling.
|
|
|
|
*/
|
|
|
|
sc->sc_swbmiss = 1;
|
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
|
|
|
|
/* complete setup */
|
|
|
|
ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
|
|
|
|
return vap;
|
|
|
|
bad2:
|
|
|
|
reclaim_address(sc, mac);
|
|
|
|
ath_hal_setbssidmask(sc->sc_ah, sc->sc_hwbssidmask);
|
|
|
|
bad:
|
|
|
|
free(avp, M_80211_VAP);
|
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_vap_delete(struct ieee80211vap *vap)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = vap->iv_ic;
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
struct ath_vap *avp = ATH_VAP(vap);
|
|
|
|
|
2011-11-08 19:02:59 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
|
2008-04-20 20:35:46 +00:00
|
|
|
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
|
|
|
/*
|
|
|
|
* Quiesce the hardware while we remove the vap. In
|
|
|
|
* particular we need to reclaim all references to
|
|
|
|
* the vap state by any frames pending on the tx queues.
|
|
|
|
*/
|
|
|
|
ath_hal_intrset(ah, 0); /* disable interrupts */
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */
|
|
|
|
/* XXX Do all frames from all vaps/nodes need draining here? */
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
ath_stoprecv(sc, 1); /* stop recv side */
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ieee80211_vap_detach(vap);
|
2011-11-08 19:18:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX Danger Will Robinson! Danger!
|
|
|
|
*
|
|
|
|
* Because ieee80211_vap_detach() can queue a frame (the station
|
|
|
|
* diassociate message?) after we've drained the TXQ and
|
|
|
|
* flushed the software TXQ, we will end up with a frame queued
|
|
|
|
* to a node whose vap is about to be freed.
|
|
|
|
*
|
|
|
|
* To work around this, flush the hardware/software again.
|
|
|
|
* This may be racy - the ath task may be running and the packet
|
|
|
|
* may be being scheduled between sw->hw txq. Tsk.
|
|
|
|
*
|
|
|
|
* TODO: figure out why a new node gets allocated somewhere around
|
|
|
|
* here (after the ath_tx_swq() call; and after an ath_stop_locked()
|
|
|
|
* call!)
|
|
|
|
*/
|
|
|
|
|
|
|
|
ath_draintxq(sc, ATH_RESET_DEFAULT);
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
ATH_LOCK(sc);
|
|
|
|
/*
|
|
|
|
* Reclaim beacon state. Note this must be done before
|
|
|
|
* the vap instance is reclaimed as we may have a reference
|
|
|
|
* to it in the buffer for the beacon frame.
|
|
|
|
*/
|
|
|
|
if (avp->av_bcbuf != NULL) {
|
|
|
|
if (avp->av_bslot != -1) {
|
|
|
|
sc->sc_bslot[avp->av_bslot] = NULL;
|
|
|
|
sc->sc_nbcnvaps--;
|
|
|
|
}
|
|
|
|
ath_beacon_return(sc, avp->av_bcbuf);
|
|
|
|
avp->av_bcbuf = NULL;
|
|
|
|
if (sc->sc_nbcnvaps == 0) {
|
|
|
|
sc->sc_stagbeacons = 0;
|
|
|
|
if (sc->sc_hastsfadd)
|
|
|
|
ath_hal_settsfadjust(sc->sc_ah, 0);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Reclaim any pending mcast frames for the vap.
|
|
|
|
*/
|
|
|
|
ath_tx_draintxq(sc, &avp->av_mcastq);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Update bookkeeping.
|
|
|
|
*/
|
|
|
|
if (vap->iv_opmode == IEEE80211_M_STA) {
|
|
|
|
sc->sc_nstavaps--;
|
|
|
|
if (sc->sc_nstavaps == 0 && sc->sc_swbmiss)
|
|
|
|
sc->sc_swbmiss = 0;
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
} else if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
|
|
|
vap->iv_opmode == IEEE80211_M_MBSS) {
|
2008-04-20 20:35:46 +00:00
|
|
|
reclaim_address(sc, vap->iv_myaddr);
|
|
|
|
ath_hal_setbssidmask(ah, sc->sc_hwbssidmask);
|
2009-07-21 19:01:04 +00:00
|
|
|
if (vap->iv_opmode == IEEE80211_M_MBSS)
|
|
|
|
sc->sc_nmeshvaps--;
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
if (vap->iv_opmode != IEEE80211_M_WDS)
|
|
|
|
sc->sc_nvaps--;
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
/* TDMA operation ceases when the last vap is destroyed */
|
|
|
|
if (sc->sc_tdma && sc->sc_nvaps == 0) {
|
|
|
|
sc->sc_tdma = 0;
|
|
|
|
sc->sc_swbmiss = 0;
|
|
|
|
}
|
|
|
|
#endif
|
2008-04-20 20:35:46 +00:00
|
|
|
free(avp, M_80211_VAP);
|
|
|
|
|
|
|
|
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
|
|
|
/*
|
|
|
|
* Restart rx+tx machines if still running (RUNNING will
|
|
|
|
* be reset if we just destroyed the last vap).
|
|
|
|
*/
|
|
|
|
if (ath_startrecv(sc) != 0)
|
|
|
|
if_printf(ifp, "%s: unable to restart recv logic\n",
|
|
|
|
__func__);
|
2009-06-02 21:11:26 +00:00
|
|
|
if (sc->sc_beacons) { /* restart beacons */
|
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
|
|
|
if (sc->sc_tdma)
|
|
|
|
ath_tdma_config(sc, NULL);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
ath_beacon_config(sc, NULL);
|
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
|
|
|
}
|
2011-11-08 19:18:34 +00:00
|
|
|
ATH_UNLOCK(sc);
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
void
|
|
|
|
ath_suspend(struct ath_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2008-05-29 00:10:48 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2008-05-29 00:10:48 +00:00
|
|
|
sc->sc_resume_up = (ifp->if_flags & IFF_UP) != 0;
|
2012-06-17 03:08:33 +00:00
|
|
|
|
|
|
|
ieee80211_suspend_all(ic);
|
2008-05-29 00:10:48 +00:00
|
|
|
/*
|
|
|
|
* NB: don't worry about putting the chip in low power
|
|
|
|
* mode; pci will power off our socket on suspend and
|
2010-01-03 23:31:58 +00:00
|
|
|
* CardBus detaches the device.
|
2008-05-29 00:10:48 +00:00
|
|
|
*/
|
2012-05-25 02:07:59 +00:00
|
|
|
|
2012-05-25 05:01:27 +00:00
|
|
|
/*
|
|
|
|
* XXX ensure none of the taskqueues are running
|
|
|
|
* XXX ensure sc_invalid is 1
|
|
|
|
* XXX ensure the calibration callout is disabled
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Disable the PCIe PHY, complete with workarounds */
|
|
|
|
ath_hal_enablepcie(sc->sc_ah, 1, 1);
|
2008-05-29 00:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset the key cache since some parts do not reset the
|
|
|
|
* contents on resume. First we clear all entries, then
|
|
|
|
* re-load keys that the 802.11 layer assumes are setup
|
|
|
|
* in h/w.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_reset_keycache(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < sc->sc_keymax; i++)
|
|
|
|
ath_hal_keyreset(ah, i);
|
|
|
|
ieee80211_crypto_reload_keys(ic);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2013-02-25 22:45:02 +00:00
|
|
|
/*
|
|
|
|
* Fetch the current chainmask configuration based on the current
|
|
|
|
* operating channel and options.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_update_chainmasks(struct ath_softc *sc, struct ieee80211_channel *chan)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set TX chainmask to the currently configured chainmask;
|
|
|
|
* the TX chainmask depends upon the current operating mode.
|
|
|
|
*/
|
|
|
|
sc->sc_cur_rxchainmask = sc->sc_rxchainmask;
|
|
|
|
if (IEEE80211_IS_CHAN_HT(chan)) {
|
|
|
|
sc->sc_cur_txchainmask = sc->sc_txchainmask;
|
|
|
|
} else {
|
|
|
|
sc->sc_cur_txchainmask = 1;
|
|
|
|
}
|
2013-04-19 08:06:45 +00:00
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET,
|
|
|
|
"%s: TX chainmask is now 0x%x, RX is now 0x%x\n",
|
|
|
|
__func__,
|
|
|
|
sc->sc_cur_txchainmask,
|
|
|
|
sc->sc_cur_rxchainmask);
|
2013-02-25 22:45:02 +00:00
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
void
|
|
|
|
ath_resume(struct ath_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2008-05-29 00:10:48 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
HAL_STATUS status;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-05-25 02:07:59 +00:00
|
|
|
/* Re-enable PCIe, re-enable the PCIe bus */
|
2012-05-25 05:01:27 +00:00
|
|
|
ath_hal_enablepcie(ah, 0, 0);
|
2012-05-25 02:07:59 +00:00
|
|
|
|
2008-05-29 00:10:48 +00:00
|
|
|
/*
|
|
|
|
* Must reset the chip before we reload the
|
|
|
|
* keycache as we were powered down on suspend.
|
|
|
|
*/
|
2013-02-25 22:45:02 +00:00
|
|
|
ath_update_chainmasks(sc,
|
|
|
|
sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan);
|
|
|
|
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
|
|
|
sc->sc_cur_rxchainmask);
|
2009-02-10 19:25:11 +00:00
|
|
|
ath_hal_reset(ah, sc->sc_opmode,
|
|
|
|
sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan,
|
|
|
|
AH_FALSE, &status);
|
2008-05-29 00:10:48 +00:00
|
|
|
ath_reset_keycache(sc);
|
2011-06-04 04:14:59 +00:00
|
|
|
|
|
|
|
/* Let DFS at it in case it's a DFS channel */
|
|
|
|
ath_dfs_radar_enable(sc, ic->ic_curchan);
|
|
|
|
|
2013-01-02 03:59:02 +00:00
|
|
|
/* Let spectral at in case spectral is enabled */
|
|
|
|
ath_spectral_enable(sc, ic->ic_curchan);
|
|
|
|
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
/*
|
|
|
|
* Let bluetooth coexistence at in case it's needed for this channel
|
|
|
|
*/
|
|
|
|
ath_btcoex_enable(sc, ic->ic_curchan);
|
|
|
|
|
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
2013-05-21 18:02:54 +00:00
|
|
|
/*
|
|
|
|
* If we're doing TDMA, enforce the TXOP limitation for chips that
|
|
|
|
* support it.
|
|
|
|
*/
|
|
|
|
if (sc->sc_hasenforcetxop && sc->sc_tdma)
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 1);
|
|
|
|
else
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 0);
|
|
|
|
|
2011-12-26 06:25:12 +00:00
|
|
|
/* Restore the LED configuration */
|
|
|
|
ath_led_config(sc);
|
|
|
|
ath_hal_setledstate(ah, HAL_LED_INIT);
|
|
|
|
|
2012-06-17 03:08:33 +00:00
|
|
|
if (sc->sc_resume_up)
|
|
|
|
ieee80211_resume_all(ic);
|
2011-06-26 13:53:24 +00:00
|
|
|
|
|
|
|
/* XXX beacons ? */
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ath_shutdown(struct ath_softc *sc)
|
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
ath_stop(ifp);
|
2008-05-29 00:10:48 +00:00
|
|
|
/* NB: no point powering down chip as we're about to reboot */
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Interrupt handler. Most of the actual processing is deferred.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
void
|
|
|
|
ath_intr(void *arg)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2011-04-23 06:37:09 +00:00
|
|
|
HAL_INT status = 0;
|
2011-11-08 18:10:04 +00:00
|
|
|
uint32_t txqs;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
/*
|
|
|
|
* If we're inside a reset path, just print a warning and
|
|
|
|
* clear the ISR. The reset routine will finish it for us.
|
|
|
|
*/
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
if (sc->sc_inreset_cnt) {
|
|
|
|
HAL_INT status;
|
|
|
|
ath_hal_getisr(ah, &status); /* clear ISR */
|
|
|
|
ath_hal_intrset(ah, 0); /* disable further intr's */
|
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY,
|
|
|
|
"%s: in reset, ignoring: status=0x%x\n",
|
|
|
|
__func__, status);
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
if (sc->sc_invalid) {
|
|
|
|
/*
|
2003-08-13 21:29:35 +00:00
|
|
|
* The hardware is not ready/present, don't touch anything.
|
|
|
|
* Note this can happen early on if the IRQ is shared.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid; ignored\n", __func__);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
return;
|
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
if (!ath_hal_intrpend(ah)) { /* shared irq, not for us */
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-04-02 23:49:15 +00:00
|
|
|
return;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
}
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if ((ifp->if_flags & IFF_UP) == 0 ||
|
|
|
|
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
|
|
|
HAL_INT status;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_getisr(ah, &status); /* clear ISR */
|
|
|
|
ath_hal_intrset(ah, 0); /* disable further intr's */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
return;
|
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Figure out the reason(s) for the interrupt. Note
|
|
|
|
* that the hal returns a pseudo-ISR that may include
|
|
|
|
* bits we haven't explicitly enabled so we mask the
|
|
|
|
* value to insure we only process bits we requested.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_getisr(ah, &status); /* NB: clears ISR too */
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_INTR, "%s: status 0x%x\n", __func__, status);
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_INTERRUPTS, 1, "ath_intr: mask=0x%.8x", status);
|
2013-02-20 11:17:03 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
|
|
if_ath_alq_post_intr(&sc->sc_alq, status, ah->ah_intrstate,
|
|
|
|
ah->ah_syncstate);
|
2013-02-20 11:17:29 +00:00
|
|
|
#endif /* ATH_DEBUG_ALQ */
|
2011-11-08 22:50:28 +00:00
|
|
|
#ifdef ATH_KTR_INTR_DEBUG
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_INTERRUPTS, 5,
|
2011-11-08 19:02:59 +00:00
|
|
|
"ath_intr: ISR=0x%.8x, ISR_S0=0x%.8x, ISR_S1=0x%.8x, ISR_S2=0x%.8x, ISR_S5=0x%.8x",
|
|
|
|
ah->ah_intrstate[0],
|
|
|
|
ah->ah_intrstate[1],
|
|
|
|
ah->ah_intrstate[2],
|
|
|
|
ah->ah_intrstate[3],
|
|
|
|
ah->ah_intrstate[6]);
|
2011-11-08 22:50:28 +00:00
|
|
|
#endif
|
2012-04-10 07:23:37 +00:00
|
|
|
|
|
|
|
/* Squirrel away SYNC interrupt debugging */
|
|
|
|
if (ah->ah_syncstate != 0) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i++)
|
|
|
|
if (ah->ah_syncstate & (i << i))
|
|
|
|
sc->sc_intr_stats.sync_intr[i]++;
|
|
|
|
}
|
|
|
|
|
2003-09-15 19:41:54 +00:00
|
|
|
status &= sc->sc_imask; /* discard unasked for bits */
|
2011-04-23 06:37:09 +00:00
|
|
|
|
|
|
|
/* Short-circuit un-handled interrupts */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
if (status == 0x0) {
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
2011-04-23 06:37:09 +00:00
|
|
|
return;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
}
|
2011-04-23 06:37:09 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
/*
|
|
|
|
* Take a note that we're inside the interrupt handler, so
|
|
|
|
* the reset routines know to wait.
|
|
|
|
*/
|
|
|
|
sc->sc_intr_cnt++;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle the interrupt. We won't run concurrent with the reset
|
|
|
|
* or channel change routines as they'll wait for sc_intr_cnt
|
|
|
|
* to be 0 before continuing.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
if (status & HAL_INT_FATAL) {
|
|
|
|
sc->sc_stats.ast_hardware++;
|
|
|
|
ath_hal_intrset(ah, 0); /* disable intr's until reset */
|
2012-04-17 06:02:41 +00:00
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_fataltask);
|
2003-06-23 17:01:19 +00:00
|
|
|
} else {
|
2004-12-08 17:34:36 +00:00
|
|
|
if (status & HAL_INT_SWBA) {
|
|
|
|
/*
|
|
|
|
* Software beacon alert--time to send a beacon.
|
|
|
|
* Handle beacon transmission directly; deferring
|
|
|
|
* this is too slow to meet timing constraints
|
|
|
|
* under load.
|
|
|
|
*/
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (sc->sc_tdma) {
|
|
|
|
if (sc->sc_tdmaswba == 0) {
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
struct ieee80211vap *vap =
|
|
|
|
TAILQ_FIRST(&ic->ic_vaps);
|
|
|
|
ath_tdma_beacon_send(sc, vap);
|
|
|
|
sc->sc_tdmaswba =
|
|
|
|
vap->iv_tdma->tdma_bintval;
|
|
|
|
} else
|
|
|
|
sc->sc_tdmaswba--;
|
|
|
|
} else
|
|
|
|
#endif
|
2009-03-30 21:53:27 +00:00
|
|
|
{
|
2009-01-08 17:12:47 +00:00
|
|
|
ath_beacon_proc(sc, 0);
|
2009-03-30 21:53:27 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
|
|
|
/*
|
|
|
|
* Schedule the rx taskq in case there's no
|
|
|
|
* traffic so any frames held on the staging
|
|
|
|
* queue are aged and potentially flushed.
|
|
|
|
*/
|
2013-03-19 19:32:28 +00:00
|
|
|
sc->sc_rx.recv_sched(sc, 1);
|
2009-03-30 21:53:27 +00:00
|
|
|
#endif
|
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
if (status & HAL_INT_RXEOL) {
|
2011-11-08 18:10:04 +00:00
|
|
|
int imask;
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXEOL");
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* NB: the hardware should re-read the link when
|
|
|
|
* RXE bit is written, but it doesn't work at
|
|
|
|
* least on older hardware revs.
|
|
|
|
*/
|
|
|
|
sc->sc_stats.ast_rxeol++;
|
2011-07-31 16:16:25 +00:00
|
|
|
/*
|
|
|
|
* Disable RXEOL/RXORN - prevent an interrupt
|
|
|
|
* storm until the PCU logic can be reset.
|
Fix a corner case in RXEOL handling which was likely introduced by yours
truly.
Before 802.11n, the RX descriptor list would employ the "self-linked tail
descriptor" trick which linked the last descriptor back to itself.
This way, the RX engine would never hit the "end" of the list and stop
processing RX (and assert RXEOL) as it never hit a descriptor whose next
pointer was 0. It would just keep overwriting the last descriptor until
the software freed up some more RX descriptors and chained them onto the
end.
For 802.11n, this needs to stop as a self-linked RX descriptor tickles the
block-ack logic into ACK'ing whatever frames are received into that
self-linked descriptor - so in very busy periods, you could end up with
A-MPDU traffic that is ACKed but never received by the 802.11 stack.
This would cause some confusion as the ADDBA windows would suddenly
be out of sync.
So when that occured here, the last descriptor would be hit and the PCU
logic would stop. It would only start again when the RX descriptor list
was updated and the PCU RX engine was re-tickled. That wasn't being done,
so RXEOL would be continuously asserted and no RX would continue.
This patch introduces a new flag - sc->sc_kickpcu - which when set,
signals the RX task to kick the PCU after its processed whatever packets
it can. This way completed packets aren't discarded.
In case some other task gets called which resets the hardware, don't
update sc->sc_imask - instead, just update the hardware interrupt mask
directly and let either ath_rx_proc() or ath_reset() restore the imask
to its former setting.
Note: this bug was only triggered when doing a whole lot of frame snooping
with serial console IO in the RX task. This would defer interrupt processing
enough to cause an RX descriptor overflow. It doesn't happen in normal
conditions.
Approved by: re (kib, blanket)
2011-08-02 02:46:03 +00:00
|
|
|
* In case the interface is reset some other
|
|
|
|
* way before "sc_kickpcu" is called, don't
|
|
|
|
* modify sc_imask - that way if it is reset
|
|
|
|
* by a call to ath_reset() somehow, the
|
|
|
|
* interrupt mask will be correctly reprogrammed.
|
2011-07-31 16:16:25 +00:00
|
|
|
*/
|
2011-11-08 18:10:04 +00:00
|
|
|
imask = sc->sc_imask;
|
Fix a corner case in RXEOL handling which was likely introduced by yours
truly.
Before 802.11n, the RX descriptor list would employ the "self-linked tail
descriptor" trick which linked the last descriptor back to itself.
This way, the RX engine would never hit the "end" of the list and stop
processing RX (and assert RXEOL) as it never hit a descriptor whose next
pointer was 0. It would just keep overwriting the last descriptor until
the software freed up some more RX descriptors and chained them onto the
end.
For 802.11n, this needs to stop as a self-linked RX descriptor tickles the
block-ack logic into ACK'ing whatever frames are received into that
self-linked descriptor - so in very busy periods, you could end up with
A-MPDU traffic that is ACKed but never received by the 802.11 stack.
This would cause some confusion as the ADDBA windows would suddenly
be out of sync.
So when that occured here, the last descriptor would be hit and the PCU
logic would stop. It would only start again when the RX descriptor list
was updated and the PCU RX engine was re-tickled. That wasn't being done,
so RXEOL would be continuously asserted and no RX would continue.
This patch introduces a new flag - sc->sc_kickpcu - which when set,
signals the RX task to kick the PCU after its processed whatever packets
it can. This way completed packets aren't discarded.
In case some other task gets called which resets the hardware, don't
update sc->sc_imask - instead, just update the hardware interrupt mask
directly and let either ath_rx_proc() or ath_reset() restore the imask
to its former setting.
Note: this bug was only triggered when doing a whole lot of frame snooping
with serial console IO in the RX task. This would defer interrupt processing
enough to cause an RX descriptor overflow. It doesn't happen in normal
conditions.
Approved by: re (kib, blanket)
2011-08-02 02:46:03 +00:00
|
|
|
imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN);
|
|
|
|
ath_hal_intrset(ah, imask);
|
2011-11-08 18:10:04 +00:00
|
|
|
/*
|
|
|
|
* Only blank sc_rxlink if we've not yet kicked
|
|
|
|
* the PCU.
|
|
|
|
*
|
|
|
|
* This isn't entirely correct - the correct solution
|
|
|
|
* would be to have a PCU lock and engage that for
|
|
|
|
* the duration of the PCU fiddling; which would include
|
|
|
|
* running the RX process. Otherwise we could end up
|
|
|
|
* messing up the RX descriptor chain and making the
|
|
|
|
* RX desc list much shorter.
|
|
|
|
*/
|
|
|
|
if (! sc->sc_kickpcu)
|
|
|
|
sc->sc_rxlink = NULL;
|
|
|
|
sc->sc_kickpcu = 1;
|
2013-03-19 19:32:28 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
Fix a corner case in RXEOL handling which was likely introduced by yours
truly.
Before 802.11n, the RX descriptor list would employ the "self-linked tail
descriptor" trick which linked the last descriptor back to itself.
This way, the RX engine would never hit the "end" of the list and stop
processing RX (and assert RXEOL) as it never hit a descriptor whose next
pointer was 0. It would just keep overwriting the last descriptor until
the software freed up some more RX descriptors and chained them onto the
end.
For 802.11n, this needs to stop as a self-linked RX descriptor tickles the
block-ack logic into ACK'ing whatever frames are received into that
self-linked descriptor - so in very busy periods, you could end up with
A-MPDU traffic that is ACKed but never received by the 802.11 stack.
This would cause some confusion as the ADDBA windows would suddenly
be out of sync.
So when that occured here, the last descriptor would be hit and the PCU
logic would stop. It would only start again when the RX descriptor list
was updated and the PCU RX engine was re-tickled. That wasn't being done,
so RXEOL would be continuously asserted and no RX would continue.
This patch introduces a new flag - sc->sc_kickpcu - which when set,
signals the RX task to kick the PCU after its processed whatever packets
it can. This way completed packets aren't discarded.
In case some other task gets called which resets the hardware, don't
update sc->sc_imask - instead, just update the hardware interrupt mask
directly and let either ath_rx_proc() or ath_reset() restore the imask
to its former setting.
Note: this bug was only triggered when doing a whole lot of frame snooping
with serial console IO in the RX task. This would defer interrupt processing
enough to cause an RX descriptor overflow. It doesn't happen in normal
conditions.
Approved by: re (kib, blanket)
2011-08-02 02:46:03 +00:00
|
|
|
/*
|
|
|
|
* Enqueue an RX proc, to handled whatever
|
|
|
|
* is in the RX queue.
|
|
|
|
* This will then kick the PCU.
|
|
|
|
*/
|
2013-03-19 19:32:28 +00:00
|
|
|
sc->sc_rx.recv_sched(sc, 1);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
if (status & HAL_INT_TXURN) {
|
|
|
|
sc->sc_stats.ast_txurn++;
|
|
|
|
/* bump tx trigger level */
|
|
|
|
ath_hal_updatetxtriglevel(ah, AH_TRUE);
|
|
|
|
}
|
2012-07-10 07:43:31 +00:00
|
|
|
/*
|
|
|
|
* Handle both the legacy and RX EDMA interrupt bits.
|
|
|
|
* Note that HAL_INT_RXLP is also HAL_INT_RXDESC.
|
|
|
|
*/
|
|
|
|
if (status & (HAL_INT_RX | HAL_INT_RXHP | HAL_INT_RXLP)) {
|
2011-11-08 18:10:04 +00:00
|
|
|
sc->sc_stats.ast_rx_intr++;
|
2013-03-19 19:32:28 +00:00
|
|
|
sc->sc_rx.recv_sched(sc, 1);
|
2011-11-08 18:10:04 +00:00
|
|
|
}
|
|
|
|
if (status & HAL_INT_TX) {
|
|
|
|
sc->sc_stats.ast_tx_intr++;
|
|
|
|
/*
|
|
|
|
* Grab all the currently set bits in the HAL txq bitmap
|
|
|
|
* and blank them. This is the only place we should be
|
|
|
|
* doing this.
|
|
|
|
*/
|
2012-08-14 22:32:20 +00:00
|
|
|
if (! sc->sc_isedma) {
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
txqs = 0xffffffff;
|
|
|
|
ath_hal_gettxintrtxqs(sc->sc_ah, &txqs);
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_INTERRUPTS, 3,
|
|
|
|
"ath_intr: TX; txqs=0x%08x, txq_active was 0x%08x, now 0x%08x",
|
|
|
|
txqs,
|
|
|
|
sc->sc_txq_active,
|
|
|
|
sc->sc_txq_active | txqs);
|
2012-08-14 22:32:20 +00:00
|
|
|
sc->sc_txq_active |= txqs;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
}
|
2006-02-09 21:48:51 +00:00
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_txtask);
|
2011-11-08 18:10:04 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
if (status & HAL_INT_BMISS) {
|
|
|
|
sc->sc_stats.ast_bmiss++;
|
2006-02-09 21:48:51 +00:00
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_bmisstask);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2011-04-18 12:15:43 +00:00
|
|
|
if (status & HAL_INT_GTT)
|
|
|
|
sc->sc_stats.ast_tx_timeout++;
|
2011-04-18 14:06:18 +00:00
|
|
|
if (status & HAL_INT_CST)
|
|
|
|
sc->sc_stats.ast_tx_cst++;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (status & HAL_INT_MIB) {
|
|
|
|
sc->sc_stats.ast_mib++;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Disable interrupts until we service the MIB
|
|
|
|
* interrupt; otherwise it will continue to fire.
|
|
|
|
*/
|
|
|
|
ath_hal_intrset(ah, 0);
|
|
|
|
/*
|
|
|
|
* Let the hal handle the event. We assume it will
|
|
|
|
* clear whatever condition caused the interrupt.
|
|
|
|
*/
|
2006-02-09 21:23:44 +00:00
|
|
|
ath_hal_mibevent(ah, &sc->sc_halstats);
|
2011-11-08 18:10:04 +00:00
|
|
|
/*
|
|
|
|
* Don't reset the interrupt if we've just
|
|
|
|
* kicked the PCU, or we may get a nested
|
|
|
|
* RXEOL before the rxproc has had a chance
|
|
|
|
* to run.
|
|
|
|
*/
|
|
|
|
if (sc->sc_kickpcu == 0)
|
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2008-11-24 01:31:10 +00:00
|
|
|
if (status & HAL_INT_RXORN) {
|
|
|
|
/* NB: hal marks HAL_INT_FATAL when RXORN is fatal */
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXORN");
|
2008-11-24 01:31:10 +00:00
|
|
|
sc->sc_stats.ast_rxorn++;
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_intr_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_fatal_proc(void *arg, int pending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2006-02-15 18:23:03 +00:00
|
|
|
u_int32_t *state;
|
|
|
|
u_int32_t len;
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
void *sp;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
if_printf(ifp, "hardware error; resetting\n");
|
2006-02-15 18:23:03 +00:00
|
|
|
/*
|
|
|
|
* Fatal errors are unrecoverable. Typically these
|
|
|
|
* are caused by DMA errors. Collect h/w state from
|
|
|
|
* the hal so we can diagnose what's going on.
|
|
|
|
*/
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (ath_hal_getfatalstate(sc->sc_ah, &sp, &len)) {
|
2006-02-15 18:23:03 +00:00
|
|
|
KASSERT(len >= 6*sizeof(u_int32_t), ("len %u bytes", len));
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
state = sp;
|
2006-02-15 18:23:03 +00:00
|
|
|
if_printf(ifp, "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n",
|
|
|
|
state[0], state[1] , state[2], state[3],
|
|
|
|
state[4], state[5]);
|
|
|
|
}
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_reset(ifp, ATH_RESET_NOLOSS);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
static void
|
|
|
|
ath_bmiss_vap(struct ieee80211vap *vap)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Workaround phantom bmiss interrupts by sanity-checking
|
|
|
|
* the time of our last rx'd frame. If it is within the
|
|
|
|
* beacon miss interval then ignore the interrupt. If it's
|
|
|
|
* truly a bmiss we'll get another interrupt soon and that'll
|
2009-02-10 23:48:29 +00:00
|
|
|
* be dispatched up for processing. Note this applies only
|
|
|
|
* for h/w beacon miss events.
|
2008-04-20 20:35:46 +00:00
|
|
|
*/
|
2009-02-10 23:48:29 +00:00
|
|
|
if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) {
|
|
|
|
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
u_int64_t lastrx = sc->sc_lastrx;
|
|
|
|
u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
|
2012-02-13 00:28:41 +00:00
|
|
|
/* XXX should take a locked ref to iv_bss */
|
2009-02-10 23:48:29 +00:00
|
|
|
u_int bmisstimeout =
|
|
|
|
vap->iv_bmissthreshold * vap->iv_bss->ni_intval * 1024;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_BEACON,
|
|
|
|
"%s: tsf %llu lastrx %lld (%llu) bmiss %u\n",
|
|
|
|
__func__, (unsigned long long) tsf,
|
|
|
|
(unsigned long long)(tsf - lastrx),
|
|
|
|
(unsigned long long) lastrx, bmisstimeout);
|
|
|
|
|
|
|
|
if (tsf - lastrx <= bmisstimeout) {
|
|
|
|
sc->sc_stats.ast_bmiss_phantom++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ATH_VAP(vap)->av_bmiss(vap);
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
int
|
2008-11-30 18:34:27 +00:00
|
|
|
ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs)
|
|
|
|
{
|
|
|
|
uint32_t rsize;
|
|
|
|
void *sp;
|
|
|
|
|
2011-01-20 04:59:11 +00:00
|
|
|
if (!ath_hal_getdiagstate(ah, HAL_DIAG_CHECK_HANGS, &mask, sizeof(mask), &sp, &rsize))
|
2008-11-30 18:34:27 +00:00
|
|
|
return 0;
|
|
|
|
KASSERT(rsize == sizeof(uint32_t), ("resultsize %u", rsize));
|
|
|
|
*hangs = *(uint32_t *)sp;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static void
|
|
|
|
ath_bmiss_proc(void *arg, int pending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2008-11-30 18:34:27 +00:00
|
|
|
uint32_t hangs;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
|
2008-11-30 18:34:27 +00:00
|
|
|
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
/*
|
|
|
|
* Do a reset upon any becaon miss event.
|
|
|
|
*
|
|
|
|
* It may be a non-recognised RX clear hang which needs a reset
|
|
|
|
* to clear.
|
|
|
|
*/
|
2008-11-30 18:34:27 +00:00
|
|
|
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
ath_reset(ifp, ATH_RESET_NOLOSS);
|
2010-02-19 18:23:45 +00:00
|
|
|
if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
} else {
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_reset(ifp, ATH_RESET_NOLOSS);
|
2008-11-30 18:34:27 +00:00
|
|
|
ieee80211_beacon_miss(ifp->if_l2com);
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
|
|
|
* Handle TKIP MIC setup to deal hardware that doesn't do MIC
|
|
|
|
* calcs together with WME. If necessary disable the crypto
|
|
|
|
* hardware and mark the 802.11 state so keys will be setup
|
|
|
|
* with the MIC work done in software.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_settkipmic(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
|
|
|
|
if ((ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP) && !sc->sc_wmetkipmic) {
|
|
|
|
if (ic->ic_flags & IEEE80211_F_WME) {
|
|
|
|
ath_hal_settkipmic(sc->sc_ah, AH_FALSE);
|
|
|
|
ic->ic_cryptocaps &= ~IEEE80211_CRYPTO_TKIPMIC;
|
|
|
|
} else {
|
|
|
|
ath_hal_settkipmic(sc->sc_ah, AH_TRUE);
|
|
|
|
ic->ic_cryptocaps |= IEEE80211_CRYPTO_TKIPMIC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static void
|
|
|
|
ath_init(void *arg)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = (struct ath_softc *) arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
HAL_STATUS status;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
|
|
|
|
__func__, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2003-10-14 22:51:45 +00:00
|
|
|
ATH_LOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Stop anything previously setup. This is safe
|
|
|
|
* whether this is the first time through or not.
|
|
|
|
*/
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_stop_locked(ifp);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The basic interface to setting the hardware in a good
|
|
|
|
* state is ``reset''. On return the hardware is known to
|
|
|
|
* be powered up and with interrupts disabled. This must
|
|
|
|
* be followed by initialization of the appropriate bits
|
|
|
|
* and then setup of the interrupt mask.
|
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_settkipmic(sc);
|
2013-02-25 22:45:02 +00:00
|
|
|
ath_update_chainmasks(sc, ic->ic_curchan);
|
|
|
|
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
|
|
|
sc->sc_cur_rxchainmask);
|
2009-01-28 18:00:22 +00:00
|
|
|
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) {
|
2003-06-23 17:01:19 +00:00
|
|
|
if_printf(ifp, "unable to reset hardware; hal status %u\n",
|
|
|
|
status);
|
2008-04-20 20:35:46 +00:00
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
return;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_chan_change(sc, ic->ic_curchan);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
/* Let DFS at it in case it's a DFS channel */
|
|
|
|
ath_dfs_radar_enable(sc, ic->ic_curchan);
|
|
|
|
|
2013-01-02 03:59:02 +00:00
|
|
|
/* Let spectral at in case spectral is enabled */
|
|
|
|
ath_spectral_enable(sc, ic->ic_curchan);
|
|
|
|
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
/*
|
|
|
|
* Let bluetooth coexistence at in case it's needed for this channel
|
|
|
|
*/
|
|
|
|
ath_btcoex_enable(sc, ic->ic_curchan);
|
|
|
|
|
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
2013-05-21 18:02:54 +00:00
|
|
|
/*
|
|
|
|
* If we're doing TDMA, enforce the TXOP limitation for chips that
|
|
|
|
* support it.
|
|
|
|
*/
|
|
|
|
if (sc->sc_hasenforcetxop && sc->sc_tdma)
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 1);
|
|
|
|
else
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 0);
|
|
|
|
|
2005-07-24 05:11:39 +00:00
|
|
|
/*
|
|
|
|
* Likewise this is set during reset so update
|
|
|
|
* state cached in the driver.
|
|
|
|
*/
|
|
|
|
sc->sc_diversity = ath_hal_getdiversity(ah);
|
2008-12-07 19:26:34 +00:00
|
|
|
sc->sc_lastlongcal = 0;
|
|
|
|
sc->sc_resetcal = 1;
|
|
|
|
sc->sc_lastcalreset = 0;
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_lastani = 0;
|
|
|
|
sc->sc_lastshortcal = 0;
|
|
|
|
sc->sc_doresetcal = AH_FALSE;
|
2011-06-26 13:53:24 +00:00
|
|
|
/*
|
|
|
|
* Beacon timers were cleared here; give ath_newstate()
|
|
|
|
* a hint that the beacon timers should be poked when
|
|
|
|
* things transition to the RUN state.
|
|
|
|
*/
|
|
|
|
sc->sc_beacons = 0;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Setup the hardware after reset: the key cache
|
|
|
|
* is filled as needed and the receive engine is
|
|
|
|
* set going. Frame transmit is handled entirely
|
|
|
|
* in the frame output path; there's nothing to do
|
|
|
|
* here except setup the interrupt mask.
|
|
|
|
*/
|
|
|
|
if (ath_startrecv(sc) != 0) {
|
|
|
|
if_printf(ifp, "unable to start recv logic\n");
|
2008-04-20 20:35:46 +00:00
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
return;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable interrupts.
|
|
|
|
*/
|
|
|
|
sc->sc_imask = HAL_INT_RX | HAL_INT_TX
|
|
|
|
| HAL_INT_RXEOL | HAL_INT_RXORN
|
2013-02-20 11:20:51 +00:00
|
|
|
| HAL_INT_TXURN
|
2003-06-23 17:01:19 +00:00
|
|
|
| HAL_INT_FATAL | HAL_INT_GLOBAL;
|
2012-07-10 07:43:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable RX EDMA bits. Note these overlap with
|
|
|
|
* HAL_INT_RX and HAL_INT_RXDESC respectively.
|
|
|
|
*/
|
|
|
|
if (sc->sc_isedma)
|
|
|
|
sc->sc_imask |= (HAL_INT_RXHP | HAL_INT_RXLP);
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Enable MIB interrupts when there are hardware phy counters.
|
|
|
|
* Note we only do this (at the moment) for station mode.
|
|
|
|
*/
|
|
|
|
if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
|
|
|
|
sc->sc_imask |= HAL_INT_MIB;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-04-18 14:06:18 +00:00
|
|
|
/* Enable global TX timeout and carrier sense timeout if available */
|
2011-04-18 12:15:43 +00:00
|
|
|
if (ath_hal_gtxto_supported(ah))
|
2011-04-18 14:14:54 +00:00
|
|
|
sc->sc_imask |= HAL_INT_GTT;
|
2011-04-18 14:03:05 +00:00
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n",
|
|
|
|
__func__, sc->sc_imask);
|
2011-04-18 12:15:43 +00:00
|
|
|
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
2009-03-09 23:10:19 +00:00
|
|
|
callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
|
|
|
|
|
|
|
ATH_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2006-02-09 21:28:11 +00:00
|
|
|
#ifdef ATH_TX99_DIAG
|
|
|
|
if (sc->sc_tx99 != NULL)
|
|
|
|
sc->sc_tx99->start(sc->sc_tx99);
|
|
|
|
else
|
|
|
|
#endif
|
2008-04-20 20:35:46 +00:00
|
|
|
ieee80211_start_all(ic); /* start all vap's */
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_stop_locked(struct ifnet *ifp)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
|
|
|
|
__func__, sc->sc_invalid, ifp->if_flags);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
ATH_LOCK_ASSERT(sc);
|
2005-08-09 10:20:02 +00:00
|
|
|
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Shutdown the hardware and driver:
|
2004-12-08 17:34:36 +00:00
|
|
|
* reset 802.11 state machine
|
2003-06-23 17:01:19 +00:00
|
|
|
* turn off timers
|
2004-12-08 17:34:36 +00:00
|
|
|
* disable interrupts
|
|
|
|
* turn off the radio
|
2003-06-23 17:01:19 +00:00
|
|
|
* clear transmit machinery
|
|
|
|
* clear receive machinery
|
|
|
|
* drain and release tx queues
|
|
|
|
* reclaim beacon resources
|
|
|
|
* power down hardware
|
|
|
|
*
|
|
|
|
* Note that some of this work is not possible if the
|
|
|
|
* hardware is gone (invalid).
|
|
|
|
*/
|
2006-02-09 21:28:11 +00:00
|
|
|
#ifdef ATH_TX99_DIAG
|
|
|
|
if (sc->sc_tx99 != NULL)
|
|
|
|
sc->sc_tx99->stop(sc->sc_tx99);
|
|
|
|
#endif
|
2009-03-09 23:10:19 +00:00
|
|
|
callout_stop(&sc->sc_wd_ch);
|
|
|
|
sc->sc_wd_timer = 0;
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
2004-12-08 17:34:36 +00:00
|
|
|
if (!sc->sc_invalid) {
|
2005-01-18 19:03:04 +00:00
|
|
|
if (sc->sc_softled) {
|
|
|
|
callout_stop(&sc->sc_ledtimer);
|
|
|
|
ath_hal_gpioset(ah, sc->sc_ledpin,
|
|
|
|
!sc->sc_ledon);
|
|
|
|
sc->sc_blinking = 0;
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_intrset(ah, 0);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_draintxq(sc, ATH_RESET_DEFAULT);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (!sc->sc_invalid) {
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
ath_stoprecv(sc, 1);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_hal_phydisable(ah);
|
|
|
|
} else
|
2003-06-23 17:01:19 +00:00
|
|
|
sc->sc_rxlink = NULL;
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_beacon_free(sc); /* XXX not needed */
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
#define MAX_TXRX_ITERATIONS 1000
|
|
|
|
static void
|
2012-02-17 03:23:01 +00:00
|
|
|
ath_txrx_stop_locked(struct ath_softc *sc)
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
{
|
|
|
|
int i = MAX_TXRX_ITERATIONS;
|
|
|
|
|
|
|
|
ATH_UNLOCK_ASSERT(sc);
|
2012-02-17 03:23:01 +00:00
|
|
|
ATH_PCU_LOCK_ASSERT(sc);
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
/*
|
|
|
|
* Sleep until all the pending operations have completed.
|
|
|
|
*
|
|
|
|
* The caller must ensure that reset has been incremented
|
|
|
|
* or the pending operations may continue being queued.
|
|
|
|
*/
|
|
|
|
while (sc->sc_rxproc_cnt || sc->sc_txproc_cnt ||
|
|
|
|
sc->sc_txstart_cnt || sc->sc_intr_cnt) {
|
2011-11-21 21:59:01 +00:00
|
|
|
if (i <= 0)
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
break;
|
2011-11-21 22:57:28 +00:00
|
|
|
msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", 1);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
i--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i <= 0)
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: didn't finish after %d iterations\n",
|
|
|
|
__func__, MAX_TXRX_ITERATIONS);
|
|
|
|
}
|
|
|
|
#undef MAX_TXRX_ITERATIONS
|
|
|
|
|
2012-02-17 03:46:38 +00:00
|
|
|
#if 0
|
2012-02-17 03:23:01 +00:00
|
|
|
static void
|
|
|
|
ath_txrx_stop(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
ATH_UNLOCK_ASSERT(sc);
|
|
|
|
ATH_PCU_UNLOCK_ASSERT(sc);
|
|
|
|
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
ath_txrx_stop_locked(sc);
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
}
|
2012-02-17 03:46:38 +00:00
|
|
|
#endif
|
2012-02-17 03:23:01 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
static void
|
|
|
|
ath_txrx_start(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
|
|
|
|
taskqueue_unblock(sc->sc_tq);
|
|
|
|
}
|
|
|
|
|
2011-12-23 03:59:49 +00:00
|
|
|
/*
|
|
|
|
* Grab the reset lock, and wait around until noone else
|
|
|
|
* is trying to do anything with it.
|
|
|
|
*
|
|
|
|
* This is totally horrible but we can't hold this lock for
|
|
|
|
* long enough to do TX/RX or we end up with net80211/ip stack
|
|
|
|
* LORs and eventual deadlock.
|
|
|
|
*
|
|
|
|
* "dowait" signals whether to spin, waiting for the reset
|
|
|
|
* lock count to reach 0. This should (for now) only be used
|
|
|
|
* during the reset path, as the rest of the code may not
|
|
|
|
* be locking-reentrant enough to behave correctly.
|
|
|
|
*
|
|
|
|
* Another, cleaner way should be found to serialise all of
|
|
|
|
* these operations.
|
|
|
|
*/
|
|
|
|
#define MAX_RESET_ITERATIONS 10
|
|
|
|
static int
|
|
|
|
ath_reset_grablock(struct ath_softc *sc, int dowait)
|
|
|
|
{
|
|
|
|
int w = 0;
|
|
|
|
int i = MAX_RESET_ITERATIONS;
|
|
|
|
|
|
|
|
ATH_PCU_LOCK_ASSERT(sc);
|
|
|
|
do {
|
|
|
|
if (sc->sc_inreset_cnt == 0) {
|
|
|
|
w = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (dowait == 0) {
|
|
|
|
w = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
pause("ath_reset_grablock", 1);
|
|
|
|
i--;
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
} while (i > 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We always increment the refcounter, regardless
|
|
|
|
* of whether we succeeded to get it in an exclusive
|
|
|
|
* way.
|
|
|
|
*/
|
|
|
|
sc->sc_inreset_cnt++;
|
|
|
|
|
|
|
|
if (i <= 0)
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: didn't finish after %d iterations\n",
|
|
|
|
__func__, MAX_RESET_ITERATIONS);
|
|
|
|
|
|
|
|
if (w == 0)
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: warning, recursive reset path!\n",
|
|
|
|
__func__);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
#undef MAX_RESET_ITERATIONS
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX TODO: write ath_reset_releaselock
|
|
|
|
*/
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
static void
|
|
|
|
ath_stop(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
ATH_LOCK(sc);
|
|
|
|
ath_stop_locked(ifp);
|
2003-10-14 22:51:45 +00:00
|
|
|
ATH_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset the hardware w/o losing operational state. This is
|
|
|
|
* basically a more efficient way of doing ath_stop, ath_init,
|
|
|
|
* followed by state transitions to the current 802.11
|
2004-12-08 17:34:36 +00:00
|
|
|
* operational state. Used to recover from various errors and
|
|
|
|
* to reset or reload hardware state.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2011-03-02 16:03:19 +00:00
|
|
|
int
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
HAL_STATUS status;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
int i;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-11-08 19:02:59 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
|
2011-11-08 19:18:34 +00:00
|
|
|
|
2011-12-23 03:59:49 +00:00
|
|
|
/* Ensure ATH_LOCK isn't held; ath_rx_proc can't be locked */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK_ASSERT(sc);
|
|
|
|
ATH_UNLOCK_ASSERT(sc);
|
|
|
|
|
2012-02-25 19:12:54 +00:00
|
|
|
/* Try to (stop any further TX/RX from occuring */
|
|
|
|
taskqueue_block(sc->sc_tq);
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
2013-06-03 19:39:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Grab the reset lock before TX/RX is stopped.
|
|
|
|
*
|
|
|
|
* This is needed to ensure that when the TX/RX actually does finish,
|
|
|
|
* no further TX/RX/reset runs in parallel with this.
|
|
|
|
*/
|
2011-12-23 03:59:49 +00:00
|
|
|
if (ath_reset_grablock(sc, 1) == 0) {
|
|
|
|
device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n",
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
__func__);
|
|
|
|
}
|
2013-06-03 19:39:37 +00:00
|
|
|
|
|
|
|
/* disable interrupts */
|
|
|
|
ath_hal_intrset(ah, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, ensure that any in progress TX/RX completes before we
|
|
|
|
* continue.
|
|
|
|
*/
|
|
|
|
ath_txrx_stop_locked(sc);
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
|
|
|
/*
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
* Should now wait for pending TX/RX to complete
|
|
|
|
* and block future ones from occuring. This needs to be
|
|
|
|
* done before the TX queue is drained.
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
*/
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_draintxq(sc, reset_type); /* stop xmit side */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
2011-11-08 19:02:59 +00:00
|
|
|
/*
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
* Regardless of whether we're doing a no-loss flush or
|
|
|
|
* not, stop the PCU and handle what's in the RX queue.
|
|
|
|
* That way frames aren't dropped which shouldn't be.
|
2011-11-08 19:02:59 +00:00
|
|
|
*/
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS));
|
2012-07-03 06:59:12 +00:00
|
|
|
ath_rx_flush(sc);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_settkipmic(sc); /* configure TKIP MIC handling */
|
2003-06-23 17:01:19 +00:00
|
|
|
/* NB: indicate channel change so we do a full reset */
|
2013-02-25 22:45:02 +00:00
|
|
|
ath_update_chainmasks(sc, ic->ic_curchan);
|
|
|
|
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
|
|
|
sc->sc_cur_rxchainmask);
|
2009-01-28 18:00:22 +00:00
|
|
|
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
|
2003-06-23 17:01:19 +00:00
|
|
|
if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
|
|
|
|
__func__, status);
|
2005-07-24 05:11:39 +00:00
|
|
|
sc->sc_diversity = ath_hal_getdiversity(ah);
|
2011-06-01 20:09:49 +00:00
|
|
|
|
|
|
|
/* Let DFS at it in case it's a DFS channel */
|
|
|
|
ath_dfs_radar_enable(sc, ic->ic_curchan);
|
|
|
|
|
2013-01-02 03:59:02 +00:00
|
|
|
/* Let spectral at in case spectral is enabled */
|
|
|
|
ath_spectral_enable(sc, ic->ic_curchan);
|
|
|
|
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
/*
|
|
|
|
* Let bluetooth coexistence at in case it's needed for this channel
|
|
|
|
*/
|
|
|
|
ath_btcoex_enable(sc, ic->ic_curchan);
|
|
|
|
|
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
2013-05-21 18:02:54 +00:00
|
|
|
/*
|
|
|
|
* If we're doing TDMA, enforce the TXOP limitation for chips that
|
|
|
|
* support it.
|
|
|
|
*/
|
|
|
|
if (sc->sc_hasenforcetxop && sc->sc_tdma)
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 1);
|
|
|
|
else
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 0);
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (ath_startrecv(sc) != 0) /* restart recv */
|
|
|
|
if_printf(ifp, "%s: unable to start recv logic\n", __func__);
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* We may be doing a reset in response to an ioctl
|
|
|
|
* that changes the channel so update any state that
|
|
|
|
* might change as a result.
|
|
|
|
*/
|
2007-01-15 01:15:57 +00:00
|
|
|
ath_chan_change(sc, ic->ic_curchan);
|
2009-06-02 21:11:26 +00:00
|
|
|
if (sc->sc_beacons) { /* restart beacons */
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (sc->sc_tdma)
|
|
|
|
ath_tdma_config(sc, NULL);
|
|
|
|
else
|
|
|
|
#endif
|
2009-06-02 21:11:26 +00:00
|
|
|
ath_beacon_config(sc, NULL);
|
2009-01-08 17:12:47 +00:00
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Release the reset lock and re-enable interrupts here.
|
|
|
|
* If an interrupt was being processed in ath_intr(),
|
|
|
|
* it would disable interrupts at this point. So we have
|
|
|
|
* to atomically enable interrupts and decrement the
|
|
|
|
* reset counter - this way ath_intr() doesn't end up
|
|
|
|
* disabling interrupts without a corresponding enable
|
|
|
|
* in the rest or channel change path.
|
|
|
|
*/
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_inreset_cnt--;
|
|
|
|
/* XXX only do this if sc_inreset_cnt == 0? */
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
/*
|
|
|
|
* TX and RX can be started here. If it were started with
|
|
|
|
* sc_inreset_cnt > 0, the TX and RX path would abort.
|
|
|
|
* Thus if this is a nested call through the reset or
|
|
|
|
* channel change code, TX completion will occur but
|
|
|
|
* RX completion and ath_start / ath_tx_start will not
|
|
|
|
* run.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Restart TX/RX as needed */
|
|
|
|
ath_txrx_start(sc);
|
|
|
|
|
Delete the per-TXQ locks and replace them with a single TX lock.
I couldn't think of a way to maintain the hardware TXQ locks _and_ layer
on top of that per-TXQ software queuing and any other kind of fine-grained
locks (eg per-TID, or per-node locks.)
So for now, to facilitate some further code refactoring and development
as part of the final push to get software queue ps-poll and u-apsd handling
into this driver, just do away with them entirely.
I may eventually bring them back at some point, when it looks slightly more
architectually cleaner to do so. But as it stands at the present, it's
not really buying us much:
* in order to properly serialise things and not get bitten by scheduling
and locking interactions with things higher up in the stack, we need to
wrap the whole TX path in a long held lock. Otherwise we can end up
being pre-empted during frame handling, resulting in some out of order
frame handling between sequence number allocation and encryption handling
(ie, the seqno and the CCMP IV get out of sequence);
* .. so whilst that's the case, holding the lock for that long means that
we're acquiring and releasing the TXQ lock _inside_ that context;
* And we also acquire it per-frame during frame completion, but we currently
can't hold the lock for the duration of the TX completion as we need
to call net80211 layer things with the locks _unheld_ to avoid LOR.
* .. the other places were grab that lock are reset/flush, which don't happen
often.
My eventual aim is to change the TX path so all rejected frame transmissions
and all frame completions result in any ieee80211_free_node() calls to occur
outside of the TX lock; then I can cut back on the amount of locking that
goes on here.
There may be some LORs that occur when ieee80211_free_node() is called when
the TX queue path fails; I'll begin to address these in follow-up commits.
2012-12-02 06:24:08 +00:00
|
|
|
/* Restart TX completion and pending TX */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
if (reset_type == ATH_RESET_NOLOSS) {
|
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
|
|
|
if (ATH_TXQ_SETUP(sc, i)) {
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK(&sc->sc_txq[i]);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ath_txq_restart_dma(sc, &sc->sc_txq[i]);
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(&sc->sc_txq[i]);
|
|
|
|
|
|
|
|
ATH_TX_LOCK(sc);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ath_txq_sched(sc, &sc->sc_txq[i]);
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This may have been set during an ath_start() call which
|
|
|
|
* set this once it detected a concurrent TX was going on.
|
|
|
|
* So, clear it.
|
|
|
|
*/
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
|
|
|
/* Handle any frames in the TX queue */
|
|
|
|
/*
|
|
|
|
* XXX should this be done by the caller, rather than
|
|
|
|
* ath_reset() ?
|
|
|
|
*/
|
Push the actual TX processing into the ath taskqueue, rather than having
it run out of multiple concurrent contexts.
Right now the ath(4) TX processing is a bit hairy. Specifically:
* It was running out of ath_start(), which could occur from multiple
concurrent sending processes (as if_start() can be started from multiple
sending threads nowdays.. sigh)
* during RX if fast frames are enabled (so not really at the moment, not
until I fix this particular feature again..)
* during ath_reset() - so anything which calls that
* during ath_tx_proc*() in the ath taskqueue - ie, TX is attempted again
after TX completion, as there's now hopefully some ath_bufs available.
* Then, the ic_raw_xmit() method can queue raw frames for transmission
at any time, from any net80211 TX context. Ew.
This has caused packet ordering issues in the past - specifically,
there's absolutely no guarantee that preemption won't occuring _during_
ath_start() by the TX completion processing, which will call ath_start()
again. It's a mess - 802.11 really, really wants things to be in
sequence or things go all kinds of loopy.
So:
* create a new task struct for TX'ing;
* make the if_start method simply queue the task on the ath taskqueue;
* make ath_start() just be called by the new TX task;
* make ath_tx_kick() just schedule the ath TX task, rather than directly
calling ath_start().
Now yes, this means that I've taken a step backwards in terms of
concurrency - TX -and- RX now occur in the same single-task taskqueue.
But there's nothing stopping me from separating out the TX / TX completion
code into a separate taskqueue which runs in parallel with the RX path,
if that ends up being appropriate for some platforms.
This fixes the CCMP/seqno concurrency issues that creep up when you
transmit large amounts of uni-directional UDP traffic (>200MBit) on a
FreeBSD STA -> AP, as now there's only one TX context no matter what's
going on (TX completion->retry/software queue,
userland->net80211->ath_start(), TX completion -> ath_start());
but it won't fix any concurrency issues between raw transmitted frames
and non-raw transmitted frames (eg EAPOL frames on TID 16 and any other
TID 16 multicast traffic that gets put on the CABQ.) That is going to
require a bunch more re-architecture before it's feasible to fix.
In any case, this is a big step towards making the majority of the TX
path locking irrelevant, as now almost all TX activity occurs in the
taskqueue.
Phew.
2012-10-14 20:44:08 +00:00
|
|
|
ath_tx_kick(sc); /* restart xmit */
|
2004-12-08 17:34:36 +00:00
|
|
|
return 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
static int
|
|
|
|
ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
|
|
|
|
{
|
2008-10-27 17:12:41 +00:00
|
|
|
struct ieee80211com *ic = vap->iv_ic;
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case IEEE80211_IOC_TXPOWER:
|
|
|
|
/*
|
|
|
|
* If per-packet TPC is enabled, then we have nothing
|
|
|
|
* to do; otherwise we need to force the global limit.
|
|
|
|
* All this can happen directly; no need to reset.
|
|
|
|
*/
|
|
|
|
if (!ath_hal_gettpc(ah))
|
|
|
|
ath_hal_settxpowlimit(ah, ic->ic_txpowlimit);
|
|
|
|
return 0;
|
|
|
|
}
|
2011-11-08 18:56:52 +00:00
|
|
|
/* XXX? Full or NOLOSS? */
|
|
|
|
return ath_reset(ifp, ATH_RESET_FULL);
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
2011-01-29 11:35:23 +00:00
|
|
|
struct ath_buf *
|
2012-06-13 06:57:55 +00:00
|
|
|
_ath_getbuf_locked(struct ath_softc *sc, ath_buf_type_t btype)
|
2009-01-08 17:12:47 +00:00
|
|
|
{
|
|
|
|
struct ath_buf *bf;
|
|
|
|
|
|
|
|
ATH_TXBUF_LOCK_ASSERT(sc);
|
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
if (btype == ATH_BUFTYPE_MGMT)
|
|
|
|
bf = TAILQ_FIRST(&sc->sc_txbuf_mgmt);
|
|
|
|
else
|
|
|
|
bf = TAILQ_FIRST(&sc->sc_txbuf);
|
|
|
|
|
2011-11-08 21:13:05 +00:00
|
|
|
if (bf == NULL) {
|
|
|
|
sc->sc_stats.ast_tx_getnobuf++;
|
|
|
|
} else {
|
|
|
|
if (bf->bf_flags & ATH_BUF_BUSY) {
|
|
|
|
sc->sc_stats.ast_tx_getbusybuf++;
|
|
|
|
bf = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0) {
|
|
|
|
if (btype == ATH_BUFTYPE_MGMT)
|
|
|
|
TAILQ_REMOVE(&sc->sc_txbuf_mgmt, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
else {
|
2012-06-13 06:57:55 +00:00
|
|
|
TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
sc->sc_txbuf_cnt--;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This shuldn't happen; however just to be
|
|
|
|
* safe print a warning and fudge the txbuf
|
|
|
|
* count.
|
|
|
|
*/
|
|
|
|
if (sc->sc_txbuf_cnt < 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: sc_txbuf_cnt < 0?\n",
|
|
|
|
__func__);
|
|
|
|
sc->sc_txbuf_cnt = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-06-13 06:57:55 +00:00
|
|
|
} else
|
2009-01-08 17:12:47 +00:00
|
|
|
bf = NULL;
|
2011-11-08 21:13:05 +00:00
|
|
|
|
2009-01-08 17:12:47 +00:00
|
|
|
if (bf == NULL) {
|
2012-06-13 06:57:55 +00:00
|
|
|
/* XXX should check which list, mgmt or otherwise */
|
2009-01-08 17:12:47 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: %s\n", __func__,
|
2011-11-08 17:08:12 +00:00
|
|
|
TAILQ_FIRST(&sc->sc_txbuf) == NULL ?
|
2009-01-08 17:12:47 +00:00
|
|
|
"out of xmit buffers" : "xmit buffer busy");
|
2011-11-08 21:13:05 +00:00
|
|
|
return NULL;
|
2009-01-08 17:12:47 +00:00
|
|
|
}
|
2011-11-08 21:13:05 +00:00
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
/* XXX TODO: should do this at buffer list initialisation */
|
|
|
|
/* XXX (then, ensure the buffer has the right flag set) */
|
2013-03-26 19:46:51 +00:00
|
|
|
bf->bf_flags = 0;
|
2012-06-13 06:57:55 +00:00
|
|
|
if (btype == ATH_BUFTYPE_MGMT)
|
|
|
|
bf->bf_flags |= ATH_BUF_MGMT;
|
|
|
|
else
|
|
|
|
bf->bf_flags &= (~ATH_BUF_MGMT);
|
|
|
|
|
2011-11-08 21:13:05 +00:00
|
|
|
/* Valid bf here; clear some basic fields */
|
|
|
|
bf->bf_next = NULL; /* XXX just to be sure */
|
|
|
|
bf->bf_last = NULL; /* XXX again, just to be sure */
|
|
|
|
bf->bf_comp = NULL; /* XXX again, just to be sure */
|
|
|
|
bzero(&bf->bf_state, sizeof(bf->bf_state));
|
|
|
|
|
2012-08-15 06:48:34 +00:00
|
|
|
/*
|
|
|
|
* Track the descriptor ID only if doing EDMA
|
|
|
|
*/
|
|
|
|
if (sc->sc_isedma) {
|
|
|
|
bf->bf_descid = sc->sc_txbuf_descid;
|
|
|
|
sc->sc_txbuf_descid++;
|
|
|
|
}
|
|
|
|
|
2009-01-08 17:12:47 +00:00
|
|
|
return bf;
|
|
|
|
}
|
|
|
|
|
2011-11-08 21:13:05 +00:00
|
|
|
/*
|
|
|
|
* When retrying a software frame, buffers marked ATH_BUF_BUSY
|
|
|
|
* can't be thrown back on the queue as they could still be
|
|
|
|
* in use by the hardware.
|
|
|
|
*
|
|
|
|
* This duplicates the buffer, or returns NULL.
|
|
|
|
*
|
|
|
|
* The descriptor is also copied but the link pointers and
|
|
|
|
* the DMA segments aren't copied; this frame should thus
|
|
|
|
* be again passed through the descriptor setup/chain routines
|
|
|
|
* so the link is correct.
|
|
|
|
*
|
|
|
|
* The caller must free the buffer using ath_freebuf().
|
|
|
|
*/
|
|
|
|
struct ath_buf *
|
2013-04-01 20:57:13 +00:00
|
|
|
ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf)
|
2011-11-08 21:13:05 +00:00
|
|
|
{
|
|
|
|
struct ath_buf *tbf;
|
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
tbf = ath_getbuf(sc,
|
|
|
|
(bf->bf_flags & ATH_BUF_MGMT) ?
|
|
|
|
ATH_BUFTYPE_MGMT : ATH_BUFTYPE_NORMAL);
|
2011-11-08 21:13:05 +00:00
|
|
|
if (tbf == NULL)
|
|
|
|
return NULL; /* XXX failure? Why? */
|
|
|
|
|
|
|
|
/* Copy basics */
|
|
|
|
tbf->bf_next = NULL;
|
|
|
|
tbf->bf_nseg = bf->bf_nseg;
|
2013-03-26 19:46:51 +00:00
|
|
|
tbf->bf_flags = bf->bf_flags & ATH_BUF_FLAGS_CLONE;
|
2011-11-08 21:13:05 +00:00
|
|
|
tbf->bf_status = bf->bf_status;
|
|
|
|
tbf->bf_m = bf->bf_m;
|
|
|
|
tbf->bf_node = bf->bf_node;
|
|
|
|
/* will be setup by the chain/setup function */
|
|
|
|
tbf->bf_lastds = NULL;
|
|
|
|
/* for now, last == self */
|
|
|
|
tbf->bf_last = tbf;
|
|
|
|
tbf->bf_comp = bf->bf_comp;
|
|
|
|
|
|
|
|
/* NOTE: DMA segments will be setup by the setup/chain functions */
|
|
|
|
|
|
|
|
/* The caller has to re-init the descriptor + links */
|
|
|
|
|
2013-04-01 20:57:13 +00:00
|
|
|
/*
|
|
|
|
* Free the DMA mapping here, before we NULL the mbuf.
|
|
|
|
* We must only call bus_dmamap_unload() once per mbuf chain
|
|
|
|
* or behaviour is undefined.
|
|
|
|
*/
|
|
|
|
if (bf->bf_m != NULL) {
|
|
|
|
/*
|
|
|
|
* XXX is this POSTWRITE call required?
|
|
|
|
*/
|
|
|
|
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
|
|
|
|
BUS_DMASYNC_POSTWRITE);
|
|
|
|
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
|
|
|
|
}
|
|
|
|
|
|
|
|
bf->bf_m = NULL;
|
|
|
|
bf->bf_node = NULL;
|
|
|
|
|
2011-11-08 21:13:05 +00:00
|
|
|
/* Copy state */
|
|
|
|
memcpy(&tbf->bf_state, &bf->bf_state, sizeof(bf->bf_state));
|
|
|
|
|
|
|
|
return tbf;
|
|
|
|
}
|
|
|
|
|
2011-01-29 11:35:23 +00:00
|
|
|
struct ath_buf *
|
2012-06-13 06:57:55 +00:00
|
|
|
ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype)
|
2009-01-08 17:12:47 +00:00
|
|
|
{
|
|
|
|
struct ath_buf *bf;
|
|
|
|
|
|
|
|
ATH_TXBUF_LOCK(sc);
|
2012-06-13 06:57:55 +00:00
|
|
|
bf = _ath_getbuf_locked(sc, btype);
|
|
|
|
/*
|
|
|
|
* If a mgmt buffer was requested but we're out of those,
|
|
|
|
* try requesting a normal one.
|
|
|
|
*/
|
|
|
|
if (bf == NULL && btype == ATH_BUFTYPE_MGMT)
|
|
|
|
bf = _ath_getbuf_locked(sc, ATH_BUFTYPE_NORMAL);
|
2012-03-10 20:09:02 +00:00
|
|
|
ATH_TXBUF_UNLOCK(sc);
|
2009-01-08 17:12:47 +00:00
|
|
|
if (bf == NULL) {
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
|
|
|
|
sc->sc_stats.ast_tx_qstop++;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2009-01-08 17:12:47 +00:00
|
|
|
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2009-01-08 17:12:47 +00:00
|
|
|
}
|
|
|
|
return bf;
|
|
|
|
}
|
|
|
|
|
Push the actual TX processing into the ath taskqueue, rather than having
it run out of multiple concurrent contexts.
Right now the ath(4) TX processing is a bit hairy. Specifically:
* It was running out of ath_start(), which could occur from multiple
concurrent sending processes (as if_start() can be started from multiple
sending threads nowdays.. sigh)
* during RX if fast frames are enabled (so not really at the moment, not
until I fix this particular feature again..)
* during ath_reset() - so anything which calls that
* during ath_tx_proc*() in the ath taskqueue - ie, TX is attempted again
after TX completion, as there's now hopefully some ath_bufs available.
* Then, the ic_raw_xmit() method can queue raw frames for transmission
at any time, from any net80211 TX context. Ew.
This has caused packet ordering issues in the past - specifically,
there's absolutely no guarantee that preemption won't occuring _during_
ath_start() by the TX completion processing, which will call ath_start()
again. It's a mess - 802.11 really, really wants things to be in
sequence or things go all kinds of loopy.
So:
* create a new task struct for TX'ing;
* make the if_start method simply queue the task on the ath taskqueue;
* make ath_start() just be called by the new TX task;
* make ath_tx_kick() just schedule the ath TX task, rather than directly
calling ath_start().
Now yes, this means that I've taken a step backwards in terms of
concurrency - TX -and- RX now occur in the same single-task taskqueue.
But there's nothing stopping me from separating out the TX / TX completion
code into a separate taskqueue which runs in parallel with the RX path,
if that ends up being appropriate for some platforms.
This fixes the CCMP/seqno concurrency issues that creep up when you
transmit large amounts of uni-directional UDP traffic (>200MBit) on a
FreeBSD STA -> AP, as now there's only one TX context no matter what's
going on (TX completion->retry/software queue,
userland->net80211->ath_start(), TX completion -> ath_start());
but it won't fix any concurrency issues between raw transmitted frames
and non-raw transmitted frames (eg EAPOL frames on TID 16 and any other
TID 16 multicast traffic that gets put on the CABQ.) That is going to
require a bunch more re-architecture before it's feasible to fix.
In any case, this is a big step towards making the majority of the TX
path locking irrelevant, as now almost all TX activity occurs in the
taskqueue.
Phew.
2012-10-14 20:44:08 +00:00
|
|
|
static void
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
ath_qflush(struct ifnet *ifp)
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
{
|
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/* XXX TODO */
|
Push the actual TX processing into the ath taskqueue, rather than having
it run out of multiple concurrent contexts.
Right now the ath(4) TX processing is a bit hairy. Specifically:
* It was running out of ath_start(), which could occur from multiple
concurrent sending processes (as if_start() can be started from multiple
sending threads nowdays.. sigh)
* during RX if fast frames are enabled (so not really at the moment, not
until I fix this particular feature again..)
* during ath_reset() - so anything which calls that
* during ath_tx_proc*() in the ath taskqueue - ie, TX is attempted again
after TX completion, as there's now hopefully some ath_bufs available.
* Then, the ic_raw_xmit() method can queue raw frames for transmission
at any time, from any net80211 TX context. Ew.
This has caused packet ordering issues in the past - specifically,
there's absolutely no guarantee that preemption won't occuring _during_
ath_start() by the TX completion processing, which will call ath_start()
again. It's a mess - 802.11 really, really wants things to be in
sequence or things go all kinds of loopy.
So:
* create a new task struct for TX'ing;
* make the if_start method simply queue the task on the ath taskqueue;
* make ath_start() just be called by the new TX task;
* make ath_tx_kick() just schedule the ath TX task, rather than directly
calling ath_start().
Now yes, this means that I've taken a step backwards in terms of
concurrency - TX -and- RX now occur in the same single-task taskqueue.
But there's nothing stopping me from separating out the TX / TX completion
code into a separate taskqueue which runs in parallel with the RX path,
if that ends up being appropriate for some platforms.
This fixes the CCMP/seqno concurrency issues that creep up when you
transmit large amounts of uni-directional UDP traffic (>200MBit) on a
FreeBSD STA -> AP, as now there's only one TX context no matter what's
going on (TX completion->retry/software queue,
userland->net80211->ath_start(), TX completion -> ath_start());
but it won't fix any concurrency issues between raw transmitted frames
and non-raw transmitted frames (eg EAPOL frames on TID 16 and any other
TID 16 multicast traffic that gets put on the CABQ.) That is going to
require a bunch more re-architecture before it's feasible to fix.
In any case, this is a big step towards making the majority of the TX
path locking irrelevant, as now almost all TX activity occurs in the
taskqueue.
Phew.
2012-10-14 20:44:08 +00:00
|
|
|
}
|
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Transmit a single frame.
|
|
|
|
*
|
|
|
|
* net80211 will free the node reference if the transmit
|
|
|
|
* fails, so don't free the node reference here.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_transmit(struct ifnet *ifp, struct mbuf *m)
|
Push the actual TX processing into the ath taskqueue, rather than having
it run out of multiple concurrent contexts.
Right now the ath(4) TX processing is a bit hairy. Specifically:
* It was running out of ath_start(), which could occur from multiple
concurrent sending processes (as if_start() can be started from multiple
sending threads nowdays.. sigh)
* during RX if fast frames are enabled (so not really at the moment, not
until I fix this particular feature again..)
* during ath_reset() - so anything which calls that
* during ath_tx_proc*() in the ath taskqueue - ie, TX is attempted again
after TX completion, as there's now hopefully some ath_bufs available.
* Then, the ic_raw_xmit() method can queue raw frames for transmission
at any time, from any net80211 TX context. Ew.
This has caused packet ordering issues in the past - specifically,
there's absolutely no guarantee that preemption won't occuring _during_
ath_start() by the TX completion processing, which will call ath_start()
again. It's a mess - 802.11 really, really wants things to be in
sequence or things go all kinds of loopy.
So:
* create a new task struct for TX'ing;
* make the if_start method simply queue the task on the ath taskqueue;
* make ath_start() just be called by the new TX task;
* make ath_tx_kick() just schedule the ath TX task, rather than directly
calling ath_start().
Now yes, this means that I've taken a step backwards in terms of
concurrency - TX -and- RX now occur in the same single-task taskqueue.
But there's nothing stopping me from separating out the TX / TX completion
code into a separate taskqueue which runs in parallel with the RX path,
if that ends up being appropriate for some platforms.
This fixes the CCMP/seqno concurrency issues that creep up when you
transmit large amounts of uni-directional UDP traffic (>200MBit) on a
FreeBSD STA -> AP, as now there's only one TX context no matter what's
going on (TX completion->retry/software queue,
userland->net80211->ath_start(), TX completion -> ath_start());
but it won't fix any concurrency issues between raw transmitted frames
and non-raw transmitted frames (eg EAPOL frames on TID 16 and any other
TID 16 multicast traffic that gets put on the CABQ.) That is going to
require a bunch more re-architecture before it's feasible to fix.
In any case, this is a big step towards making the majority of the TX
path locking irrelevant, as now almost all TX activity occurs in the
taskqueue.
Phew.
2012-10-14 20:44:08 +00:00
|
|
|
{
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct mbuf *next;
|
|
|
|
struct ath_buf *bf;
|
|
|
|
ath_bufhead frags;
|
|
|
|
int retval = 0;
|
2012-10-31 06:27:58 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Tell the reset path that we're currently transmitting.
|
|
|
|
*/
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
if (sc->sc_inreset_cnt > 0) {
|
2013-10-17 01:53:07 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
"%s: sc_inreset_cnt > 0; bailing\n", __func__);
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2012-06-14 00:51:53 +00:00
|
|
|
sc->sc_stats.ast_tx_qstop++;
|
2012-03-10 20:09:02 +00:00
|
|
|
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2012-10-31 06:27:58 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: OACTIVE, finish");
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
return (ENOBUFS); /* XXX should be EINVAL or? */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
}
|
|
|
|
sc->sc_txstart_cnt++;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: start");
|
|
|
|
/*
|
|
|
|
* Grab the TX lock - it's ok to do this here; we haven't
|
|
|
|
* yet started transmitting.
|
|
|
|
*/
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
ATH_TX_LOCK(sc);
|
Push the actual TX processing into the ath taskqueue, rather than having
it run out of multiple concurrent contexts.
Right now the ath(4) TX processing is a bit hairy. Specifically:
* It was running out of ath_start(), which could occur from multiple
concurrent sending processes (as if_start() can be started from multiple
sending threads nowdays.. sigh)
* during RX if fast frames are enabled (so not really at the moment, not
until I fix this particular feature again..)
* during ath_reset() - so anything which calls that
* during ath_tx_proc*() in the ath taskqueue - ie, TX is attempted again
after TX completion, as there's now hopefully some ath_bufs available.
* Then, the ic_raw_xmit() method can queue raw frames for transmission
at any time, from any net80211 TX context. Ew.
This has caused packet ordering issues in the past - specifically,
there's absolutely no guarantee that preemption won't occuring _during_
ath_start() by the TX completion processing, which will call ath_start()
again. It's a mess - 802.11 really, really wants things to be in
sequence or things go all kinds of loopy.
So:
* create a new task struct for TX'ing;
* make the if_start method simply queue the task on the ath taskqueue;
* make ath_start() just be called by the new TX task;
* make ath_tx_kick() just schedule the ath TX task, rather than directly
calling ath_start().
Now yes, this means that I've taken a step backwards in terms of
concurrency - TX -and- RX now occur in the same single-task taskqueue.
But there's nothing stopping me from separating out the TX / TX completion
code into a separate taskqueue which runs in parallel with the RX path,
if that ends up being appropriate for some platforms.
This fixes the CCMP/seqno concurrency issues that creep up when you
transmit large amounts of uni-directional UDP traffic (>200MBit) on a
FreeBSD STA -> AP, as now there's only one TX context no matter what's
going on (TX completion->retry/software queue,
userland->net80211->ath_start(), TX completion -> ath_start());
but it won't fix any concurrency issues between raw transmitted frames
and non-raw transmitted frames (eg EAPOL frames on TID 16 and any other
TID 16 multicast traffic that gets put on the CABQ.) That is going to
require a bunch more re-architecture before it's feasible to fix.
In any case, this is a big step towards making the majority of the TX
path locking irrelevant, as now almost all TX activity occurs in the
taskqueue.
Phew.
2012-10-14 20:44:08 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Node reference, if there's one.
|
|
|
|
*/
|
|
|
|
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Enforce how deep a node queue can get.
|
|
|
|
*
|
|
|
|
* XXX it would be nicer if we kept an mbuf queue per
|
|
|
|
* node and only whacked them into ath_bufs when we
|
|
|
|
* are ready to schedule some traffic from them.
|
|
|
|
* .. that may come later.
|
|
|
|
*
|
|
|
|
* XXX we should also track the per-node hardware queue
|
|
|
|
* depth so it is easy to limit the _SUM_ of the swq and
|
|
|
|
* hwq frames. Since we only schedule two HWQ frames
|
|
|
|
* at a time, this should be OK for now.
|
|
|
|
*/
|
|
|
|
if ((!(m->m_flags & M_EAPOL)) &&
|
|
|
|
(ATH_NODE(ni)->an_swq_depth > sc->sc_txq_node_maxdepth)) {
|
|
|
|
sc->sc_stats.ast_tx_nodeq_overflow++;
|
|
|
|
m_freem(m);
|
|
|
|
m = NULL;
|
|
|
|
retval = ENOBUFS;
|
|
|
|
goto finish;
|
|
|
|
}
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Check how many TX buffers are available.
|
|
|
|
*
|
|
|
|
* If this is for non-EAPOL traffic, just leave some
|
|
|
|
* space free in order for buffer cloning and raw
|
|
|
|
* frame transmission to occur.
|
|
|
|
*
|
|
|
|
* If it's for EAPOL traffic, ignore this for now.
|
|
|
|
* Management traffic will be sent via the raw transmit
|
|
|
|
* method which bypasses this check.
|
|
|
|
*
|
|
|
|
* This is needed to ensure that EAPOL frames during
|
|
|
|
* (re) keying have a chance to go out.
|
|
|
|
*
|
|
|
|
* See kern/138379 for more information.
|
|
|
|
*/
|
|
|
|
if ((!(m->m_flags & M_EAPOL)) &&
|
|
|
|
(sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree)) {
|
|
|
|
sc->sc_stats.ast_tx_nobuf++;
|
|
|
|
m_freem(m);
|
|
|
|
m = NULL;
|
|
|
|
retval = ENOBUFS;
|
|
|
|
goto finish;
|
|
|
|
}
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Grab a TX buffer and associated resources.
|
|
|
|
*
|
|
|
|
* If it's an EAPOL frame, allocate a MGMT ath_buf.
|
|
|
|
* That way even with temporary buffer exhaustion due to
|
|
|
|
* the data path doesn't leave us without the ability
|
|
|
|
* to transmit management frames.
|
|
|
|
*
|
|
|
|
* Otherwise allocate a normal buffer.
|
|
|
|
*/
|
|
|
|
if (m->m_flags & M_EAPOL)
|
|
|
|
bf = ath_getbuf(sc, ATH_BUFTYPE_MGMT);
|
|
|
|
else
|
|
|
|
bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
|
2013-05-07 07:52:18 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
if (bf == NULL) {
|
2013-05-07 07:52:18 +00:00
|
|
|
/*
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
* If we failed to allocate a buffer, fail.
|
2013-05-07 07:52:18 +00:00
|
|
|
*
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
* We shouldn't fail normally, due to the check
|
|
|
|
* above.
|
2013-05-07 07:52:18 +00:00
|
|
|
*/
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
sc->sc_stats.ast_tx_nobuf++;
|
|
|
|
IF_LOCK(&ifp->if_snd);
|
|
|
|
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
|
|
|
m_freem(m);
|
|
|
|
m = NULL;
|
|
|
|
retval = ENOBUFS;
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point we have a buffer; so we need to free it
|
|
|
|
* if we hit any error conditions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for fragmentation. If this frame
|
|
|
|
* has been broken up verify we have enough
|
|
|
|
* buffers to send all the fragments so all
|
|
|
|
* go out or none...
|
|
|
|
*/
|
|
|
|
TAILQ_INIT(&frags);
|
|
|
|
if ((m->m_flags & M_FRAG) &&
|
|
|
|
!ath_txfrag_setup(sc, &frags, m, ni)) {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
|
|
|
"%s: out of txfrag buffers\n", __func__);
|
|
|
|
sc->sc_stats.ast_tx_nofrag++;
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
ath_freetx(m);
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* At this point if we have any TX fragments, then we will
|
|
|
|
* have bumped the node reference once for each of those.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX Is there anything actually _enforcing_ that the
|
|
|
|
* fragments are being transmitted in one hit, rather than
|
|
|
|
* being interleaved with other transmissions on that
|
|
|
|
* hardware queue?
|
|
|
|
*
|
|
|
|
* The ATH TX output lock is the only thing serialising this
|
|
|
|
* right now.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate the "next fragment" length field in ath_buf
|
|
|
|
* in order to let the transmit path know enough about
|
|
|
|
* what to next write to the hardware.
|
|
|
|
*/
|
|
|
|
if (m->m_flags & M_FRAG) {
|
|
|
|
struct ath_buf *fbf = bf;
|
|
|
|
struct ath_buf *n_fbf = NULL;
|
|
|
|
struct mbuf *fm = m->m_nextpkt;
|
2013-05-07 07:52:18 +00:00
|
|
|
|
|
|
|
/*
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
* We need to walk the list of fragments and set
|
|
|
|
* the next size to the following buffer.
|
|
|
|
* However, the first buffer isn't in the frag
|
|
|
|
* list, so we have to do some gymnastics here.
|
2013-05-07 07:52:18 +00:00
|
|
|
*/
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
TAILQ_FOREACH(n_fbf, &frags, bf_list) {
|
|
|
|
fbf->bf_nextfraglen = fm->m_pkthdr.len;
|
|
|
|
fbf = n_fbf;
|
|
|
|
fm = fm->m_nextpkt;
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
}
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
}
|
2013-05-07 07:52:18 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Bump the ifp output counter.
|
|
|
|
*
|
|
|
|
* XXX should use atomics?
|
|
|
|
*/
|
|
|
|
ifp->if_opackets++;
|
|
|
|
nextfrag:
|
|
|
|
/*
|
|
|
|
* Pass the frame to the h/w for transmission.
|
|
|
|
* Fragmented frames have each frag chained together
|
|
|
|
* with m_nextpkt. We know there are sufficient ath_buf's
|
|
|
|
* to send all the frags because of work done by
|
|
|
|
* ath_txfrag_setup. We leave m_nextpkt set while
|
|
|
|
* calling ath_tx_start so it can use it to extend the
|
|
|
|
* the tx duration to cover the subsequent frag and
|
|
|
|
* so it can reclaim all the mbufs in case of an error;
|
|
|
|
* ath_tx_start clears m_nextpkt once it commits to
|
|
|
|
* handing the frame to the hardware.
|
|
|
|
*
|
|
|
|
* Note: if this fails, then the mbufs are freed but
|
|
|
|
* not the node reference.
|
|
|
|
*/
|
|
|
|
next = m->m_nextpkt;
|
|
|
|
if (ath_tx_start(sc, ni, bf, m)) {
|
|
|
|
bad:
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
reclaim:
|
|
|
|
bf->bf_m = NULL;
|
|
|
|
bf->bf_node = NULL;
|
|
|
|
ATH_TXBUF_LOCK(sc);
|
|
|
|
ath_returnbuf_head(sc, bf);
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
* Free the rest of the node references and
|
|
|
|
* buffers for the fragment list.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
ath_txfrag_cleanup(sc, &frags, ni);
|
|
|
|
ATH_TXBUF_UNLOCK(sc);
|
|
|
|
retval = ENOBUFS;
|
|
|
|
goto finish;
|
|
|
|
}
|
2013-05-07 07:52:18 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Check here if the node is in power save state.
|
|
|
|
*/
|
|
|
|
ath_tx_update_tim(sc, ni, 1);
|
2013-05-07 07:52:18 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
if (next != NULL) {
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
* Beware of state changing between frags.
|
|
|
|
* XXX check sta power-save state?
|
2008-04-20 20:35:46 +00:00
|
|
|
*/
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_XMIT,
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
"%s: flush fragmented packet, state %s\n",
|
|
|
|
__func__,
|
|
|
|
ieee80211_state_name[ni->ni_vap->iv_state]);
|
|
|
|
/* XXX dmamap */
|
|
|
|
ath_freetx(next);
|
|
|
|
goto reclaim;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
m = next;
|
|
|
|
bf = TAILQ_FIRST(&frags);
|
|
|
|
KASSERT(bf != NULL, ("no buf for txfrag"));
|
|
|
|
TAILQ_REMOVE(&frags, bf, bf_list);
|
|
|
|
goto nextfrag;
|
|
|
|
}
|
2012-10-28 21:13:12 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Bump watchdog timer.
|
|
|
|
*/
|
|
|
|
sc->sc_wd_timer = 5;
|
Implement frame (data) transmission using if_transmit(), rather than
if_start().
This removes the overlapping data path TX from occuring, which
solves quite a number of the potential TX queue races in ath(4).
It doesn't fix the net80211 layer TX queue races and it doesn't
fix the raw TX path yet, but it's an important step towards this.
This hasn't dropped the TX performance in my testing; primarily
because now the TX path can quickly queue frames and continue
along processing.
This involves a few rather deep changes:
* Use the ath_buf as a queue placeholder for now, as we need to be
able to support queuing a list of mbufs (ie, when transmitting
fragments) and m_nextpkt can't be used here (because it's what is
joining the fragments together)
* if_transmit() now simply allocates the ath_buf and queues it to
a driver TX staging queue.
* TX is now moved into a taskqueue function.
* The TX taskqueue function now dequeues and transmits frames.
* Fragments are handled correctly here - as the current API passes
the fragment list as one mbuf list (joined with m_nextpkt) through
to the driver if_transmit().
* For the couple of places where ath_start() may be called (mostly
from net80211 when starting the VAP up again), just reimplement
it using the new enqueue and taskqueue methods.
What I don't like (about this work and the TX code in general):
* I'm using the same lock for the staging TX queue management and the
actual TX. This isn't required; I'm just being slack.
* I haven't yet moved TX to a separate taskqueue (but the taskqueue is
created); it's easy enough to do this later if necessary. I just need
to make sure it's a higher priority queue, so TX has the same
behaviour as it used to (where it would preempt existing RX..)
* I need to re-review the TX path a little more and make sure that
ieee80211_node_*() functions aren't called within the TX lock.
When queueing, I should just push failed frames into a queue and
when I'm wrapping up the TX code, unlock the TX lock and
call ieee80211_node_free() on each.
* It would be nice if I could hold the TX lock for the entire
TX and TX completion, rather than this release/re-acquire behaviour.
But that requires that I shuffle around the TX completion code
to handle actual ath_buf free and net80211 callback/free outside
of the TX lock. That's one of my next projects.
* the ic_raw_xmit() path doesn't use this yet - so it still has
sequencing problems with parallel, overlapping calls to the
data path. I'll fix this later.
Tested:
* Hostap - AR9280, AR9220
* STA - AR5212, AR9280, AR5416
2013-01-15 18:01:23 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
finish:
|
|
|
|
ATH_TX_UNLOCK(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
/*
|
|
|
|
* Finished transmitting!
|
|
|
|
*/
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txstart_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
|
|
|
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: finished");
|
|
|
|
|
|
|
|
return (retval);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
Migrate ath(4) to now use if_transmit instead of the legacy if_start
and if queue mechanism; also fix up (non-11n) TX fragment handling.
This may result in a bit of a performance drop for now but I plan on
debugging and resolving this at a later stage.
Whilst here, fix the transmit path so fragment transmission works.
The TX fragmentation handling is a bit more special. In order to
correctly transmit TX fragments, there's a bunch of corner cases that
need to be handled:
* They must be transmitted back to back, in the same order..
* .. ie, you need to hold the TX lock whilst transmitting this
set of fragments rather than interleaving it with other MSDUs
destined to other nodes;
* The length of the next fragment is required when transmitting, in
order to correctly set the NAV field in the current frame to the
length of the next frame; which requires ..
* .. that we know the transmit duration of the next frame, which ..
* .. requires us to set the rate of all fragments to the same length,
or make the decision up-front, etc.
To facilitate this, I've added a new ath_buf field to describe the
length of the next fragment. This avoids having to keep the mbuf
chain together. This used to work before my 11n TX path work because
the ath_tx_start() routine would be handed a single mbuf with m_nextpkt
pointing to the next frame, and that would be maintained all the way
up to when the duration calculation was done. This doesn't hold
true any longer - the actual queuing may occur at any point in the
future (think ath_node TID software queuing) so this information
needs to be maintained.
Right now this does work for non-11n frames but it doesn't at all
enforce the same rate control decision for all frames in the fragment.
I plan on fixing this in a followup commit.
RTS/CTS has the same issue, I'll look at fixing this in a subsequent
commit.
Finaly, 11n fragment support requires the driver to have fully
decided what the rate scenario setup is - including 20/40MHz,
short/long GI, STBC, LDPC, number of streams, etc. Right now that
decision is (currently) made _after_ the NAV field value is updated.
I'll fix all of this in subsequent commits.
Tested:
* AR5416, STA, transmitting 11abg fragments
* AR5416, STA, 11n fragments work but the NAV field is incorrect for
the reasons above.
TODO:
* It would be nice to be able to queue mbufs per-node and per-TID so
we can only queue ath_buf entries when it's time to assemble frames
to send to the hardware.
But honestly, we should just do that level of software queue management
in net80211 rather than ath(4), so I'm going to leave this alone for now.
* More thorough AP, mesh and adhoc testing.
* Ensure that net80211 doesn't hand us fragmented frames when A-MPDU has
been negotiated, as we can't do software retransmission of fragments.
* .. set CLRDMASK when transmitting fragments, just to ensure.
2013-05-26 22:23:39 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static int
|
|
|
|
ath_media_change(struct ifnet *ifp)
|
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
int error = ieee80211_media_change(ifp);
|
|
|
|
/* NB: only the fixed rate can change and that doesn't need a reset */
|
|
|
|
return (error == ENETRESET ? 0 : error);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Block/unblock tx+rx processing while a key change is done.
|
|
|
|
* We assume the caller serializes key management operations
|
|
|
|
* so we only need to worry about synchronization with other
|
|
|
|
* uses that originate in the driver.
|
|
|
|
*/
|
|
|
|
static void
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_key_update_begin(struct ieee80211vap *vap)
|
2004-12-08 17:34:36 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
|
2008-04-20 20:35:46 +00:00
|
|
|
taskqueue_block(sc->sc_tq);
|
2004-12-08 17:34:36 +00:00
|
|
|
IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_key_update_end(struct ieee80211vap *vap)
|
2004-12-08 17:34:36 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
|
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2008-04-20 20:35:46 +00:00
|
|
|
taskqueue_unblock(sc->sc_tq);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2003-10-17 21:58:39 +00:00
|
|
|
static void
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_update_promisc(struct ifnet *ifp)
|
2003-10-17 21:58:39 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
u_int32_t rfilt;
|
2003-10-17 21:58:39 +00:00
|
|
|
|
|
|
|
/* configure rx filter */
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
rfilt = ath_calcrxfilter(sc);
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_setrxfilter(sc->sc_ah, rfilt);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt);
|
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
static void
|
|
|
|
ath_update_mcast(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
u_int32_t mfilt[2];
|
2003-10-17 21:58:39 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/* calculate and install multicast filter */
|
|
|
|
if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifmultiaddr *ifma;
|
|
|
|
/*
|
|
|
|
* Merge multicast addresses to form the hardware filter.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
mfilt[0] = mfilt[1] = 0;
|
2009-06-26 11:45:06 +00:00
|
|
|
if_maddr_rlock(ifp); /* XXX need some fiddling to remove? */
|
2003-06-23 17:01:19 +00:00
|
|
|
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
|
|
|
caddr_t dl;
|
2008-04-20 20:35:46 +00:00
|
|
|
u_int32_t val;
|
|
|
|
u_int8_t pos;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
/* calculate XOR of eight 6bit values */
|
|
|
|
dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
|
|
|
|
val = LE_READ_4(dl + 0);
|
|
|
|
pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
|
|
|
val = LE_READ_4(dl + 3);
|
|
|
|
pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
|
|
|
|
pos &= 0x3f;
|
|
|
|
mfilt[pos / 32] |= (1 << (pos % 32));
|
|
|
|
}
|
2009-06-26 11:45:06 +00:00
|
|
|
if_maddr_runlock(ifp);
|
2008-04-20 20:35:46 +00:00
|
|
|
} else
|
2003-06-23 17:01:19 +00:00
|
|
|
mfilt[0] = mfilt[1] = ~0;
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]);
|
|
|
|
DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n",
|
|
|
|
__func__, mfilt[0], mfilt[1]);
|
|
|
|
}
|
|
|
|
|
2012-05-20 02:05:10 +00:00
|
|
|
void
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_mode_init(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
u_int32_t rfilt;
|
|
|
|
|
|
|
|
/* configure rx filter */
|
|
|
|
rfilt = ath_calcrxfilter(sc);
|
|
|
|
ath_hal_setrxfilter(ah, rfilt);
|
|
|
|
|
|
|
|
/* configure operational mode */
|
|
|
|
ath_hal_setopmode(ah);
|
|
|
|
|
2012-07-09 08:37:59 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_MODE,
|
|
|
|
"%s: ah=%p, ifp=%p, if_addr=%p\n",
|
|
|
|
__func__,
|
|
|
|
ah,
|
|
|
|
ifp,
|
|
|
|
(ifp == NULL) ? NULL : ifp->if_addr);
|
|
|
|
|
2009-03-29 17:59:14 +00:00
|
|
|
/* handle any link-level address change */
|
|
|
|
ath_hal_setmac(ah, IF_LLADDR(ifp));
|
2008-04-20 20:35:46 +00:00
|
|
|
|
|
|
|
/* calculate and install multicast filter */
|
|
|
|
ath_update_mcast(ifp);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Set the slot time based on the current setting.
|
|
|
|
*/
|
2012-05-20 04:14:29 +00:00
|
|
|
void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_setslottime(struct ath_softc *sc)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2006-12-27 19:07:09 +00:00
|
|
|
u_int usec;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2007-01-15 01:15:57 +00:00
|
|
|
if (IEEE80211_IS_CHAN_HALF(ic->ic_curchan))
|
|
|
|
usec = 13;
|
|
|
|
else if (IEEE80211_IS_CHAN_QUARTER(ic->ic_curchan))
|
|
|
|
usec = 21;
|
|
|
|
else if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) {
|
|
|
|
/* honor short/long slot time only in 11g */
|
|
|
|
/* XXX shouldn't honor on pure g or turbo g channel */
|
|
|
|
if (ic->ic_flags & IEEE80211_F_SHSLOT)
|
2006-12-27 19:07:09 +00:00
|
|
|
usec = HAL_SLOT_TIME_9;
|
2007-01-15 01:15:57 +00:00
|
|
|
else
|
|
|
|
usec = HAL_SLOT_TIME_20;
|
|
|
|
} else
|
2006-12-27 19:07:09 +00:00
|
|
|
usec = HAL_SLOT_TIME_9;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET,
|
|
|
|
"%s: chan %u MHz flags 0x%x %s slot, %u usec\n",
|
|
|
|
__func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags,
|
|
|
|
ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", usec);
|
|
|
|
|
|
|
|
ath_hal_setslottime(ah, usec);
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_updateslot = OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Callback from the 802.11 layer to update the
|
|
|
|
* slot time based on the current setting.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_updateslot(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When not coordinating the BSS, change the hardware
|
|
|
|
* immediately. For other operation we defer the change
|
|
|
|
* until beacon updates have propagated to the stations.
|
|
|
|
*/
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
|
|
|
|
ic->ic_opmode == IEEE80211_M_MBSS)
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_updateslot = UPDATE;
|
|
|
|
else
|
|
|
|
ath_setslottime(sc);
|
|
|
|
}
|
|
|
|
|
2006-06-26 03:10:45 +00:00
|
|
|
/*
|
|
|
|
* Append the contents of src to dst; both queues
|
|
|
|
* are assumed to be locked.
|
|
|
|
*/
|
2012-05-20 04:14:29 +00:00
|
|
|
void
|
2006-06-26 03:10:45 +00:00
|
|
|
ath_txqmove(struct ath_txq *dst, struct ath_txq *src)
|
|
|
|
{
|
2012-03-09 08:36:30 +00:00
|
|
|
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK_ASSERT(src);
|
|
|
|
ATH_TXQ_LOCK_ASSERT(dst);
|
|
|
|
|
2011-11-08 17:08:12 +00:00
|
|
|
TAILQ_CONCAT(&dst->axq_q, &src->axq_q, bf_list);
|
2006-06-26 03:10:45 +00:00
|
|
|
dst->axq_link = src->axq_link;
|
|
|
|
src->axq_link = NULL;
|
|
|
|
dst->axq_depth += src->axq_depth;
|
2011-11-08 21:25:36 +00:00
|
|
|
dst->axq_aggr_depth += src->axq_aggr_depth;
|
2006-06-26 03:10:45 +00:00
|
|
|
src->axq_depth = 0;
|
2011-11-08 21:25:36 +00:00
|
|
|
src->axq_aggr_depth = 0;
|
2006-06-26 03:10:45 +00:00
|
|
|
}
|
|
|
|
|
2012-02-25 19:12:54 +00:00
|
|
|
/*
|
|
|
|
* Reset the hardware, with no loss.
|
|
|
|
*
|
|
|
|
* This can't be used for a general case reset.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_reset_proc(void *arg, int pending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if_printf(ifp, "%s: resetting\n", __func__);
|
|
|
|
#endif
|
|
|
|
ath_reset(ifp, ATH_RESET_NOLOSS);
|
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Reset the hardware after detecting beacons have stopped.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_bstuck_proc(void *arg, int pending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2011-11-08 19:18:34 +00:00
|
|
|
uint32_t hangs = 0;
|
|
|
|
|
|
|
|
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0)
|
|
|
|
if_printf(ifp, "bb hang detected (0x%x)\n", hangs);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2013-05-13 21:18:00 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
|
|
if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_STUCK_BEACON))
|
|
|
|
if_ath_alq_post(&sc->sc_alq, ATH_ALQ_STUCK_BEACON, 0, NULL);
|
|
|
|
#endif
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n",
|
|
|
|
sc->sc_bmisscount);
|
2009-02-07 05:34:41 +00:00
|
|
|
sc->sc_stats.ast_bstuck++;
|
2011-11-08 19:18:34 +00:00
|
|
|
/*
|
|
|
|
* This assumes that there's no simultaneous channel mode change
|
|
|
|
* occuring.
|
|
|
|
*/
|
2011-11-08 18:56:52 +00:00
|
|
|
ath_reset(ifp, ATH_RESET_NOLOSS);
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static void
|
|
|
|
ath_load_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
|
|
|
|
{
|
|
|
|
bus_addr_t *paddr = (bus_addr_t*) arg;
|
2004-12-31 20:11:23 +00:00
|
|
|
KASSERT(error == 0, ("error %u on bus_dma callback", error));
|
2003-06-23 17:01:19 +00:00
|
|
|
*paddr = segs->ds_addr;
|
|
|
|
}
|
|
|
|
|
2012-07-27 05:34:45 +00:00
|
|
|
/*
|
|
|
|
* Allocate the descriptors and appropriate DMA tag/setup.
|
|
|
|
*
|
|
|
|
* For some situations (eg EDMA TX completion), there isn't a requirement
|
|
|
|
* for the ath_buf entries to be allocated.
|
|
|
|
*/
|
2012-07-09 08:37:59 +00:00
|
|
|
int
|
2012-07-27 05:34:45 +00:00
|
|
|
ath_descdma_alloc_desc(struct ath_softc *sc,
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_descdma *dd, ath_bufhead *head,
|
2012-07-27 05:48:42 +00:00
|
|
|
const char *name, int ds_size, int ndesc)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2004-12-08 17:34:36 +00:00
|
|
|
#define DS2PHYS(_dd, _ds) \
|
|
|
|
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
|
2011-07-31 08:01:41 +00:00
|
|
|
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
|
|
|
|
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2012-07-27 05:34:45 +00:00
|
|
|
int error;
|
2011-07-31 08:01:41 +00:00
|
|
|
|
2012-07-23 23:40:13 +00:00
|
|
|
dd->dd_descsize = ds_size;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-23 02:26:33 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET,
|
2012-07-27 05:48:42 +00:00
|
|
|
"%s: %s DMA: %u desc, %d bytes per descriptor\n",
|
|
|
|
__func__, name, ndesc, dd->dd_descsize);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
dd->dd_name = name;
|
2012-07-27 05:48:42 +00:00
|
|
|
dd->dd_desc_len = dd->dd_descsize * ndesc;
|
2011-07-31 08:01:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Merlin work-around:
|
|
|
|
* Descriptors that cross the 4KB boundary can't be used.
|
|
|
|
* Assume one skipped descriptor per 4KB page.
|
|
|
|
*/
|
|
|
|
if (! ath_hal_split4ktrans(sc->sc_ah)) {
|
2012-07-27 05:48:42 +00:00
|
|
|
int numpages = dd->dd_desc_len / 4096;
|
|
|
|
dd->dd_desc_len += ds_size * numpages;
|
2011-07-31 08:01:41 +00:00
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup DMA descriptor area.
|
2013-04-02 06:24:22 +00:00
|
|
|
*
|
|
|
|
* BUS_DMA_ALLOCNOW is not used; we never use bounce
|
|
|
|
* buffers for the descriptors themselves.
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
2007-01-21 19:32:51 +00:00
|
|
|
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), /* parent */
|
2004-12-08 17:34:36 +00:00
|
|
|
PAGE_SIZE, 0, /* alignment, bounds */
|
|
|
|
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
|
|
|
BUS_SPACE_MAXADDR, /* highaddr */
|
|
|
|
NULL, NULL, /* filter, filterarg */
|
|
|
|
dd->dd_desc_len, /* maxsize */
|
|
|
|
1, /* nsegments */
|
2006-05-08 20:11:09 +00:00
|
|
|
dd->dd_desc_len, /* maxsegsize */
|
2013-04-02 06:24:22 +00:00
|
|
|
0, /* flags */
|
2004-12-08 17:34:36 +00:00
|
|
|
NULL, /* lockfunc */
|
|
|
|
NULL, /* lockarg */
|
|
|
|
&dd->dd_dmat);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate descriptors */
|
|
|
|
error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
|
2010-02-19 18:23:45 +00:00
|
|
|
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
|
2006-11-24 22:45:26 +00:00
|
|
|
&dd->dd_dmamap);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
|
2012-07-27 05:48:42 +00:00
|
|
|
"error %u\n", ndesc, dd->dd_name, error);
|
2003-06-23 17:01:19 +00:00
|
|
|
goto fail1;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
error = bus_dmamap_load(dd->dd_dmat, dd->dd_dmamap,
|
|
|
|
dd->dd_desc, dd->dd_desc_len,
|
|
|
|
ath_load_cb, &dd->dd_desc_paddr,
|
|
|
|
BUS_DMA_NOWAIT);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "unable to map %s descriptors, error %u\n",
|
|
|
|
dd->dd_name, error);
|
2003-06-23 17:01:19 +00:00
|
|
|
goto fail2;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n",
|
2012-07-27 05:34:45 +00:00
|
|
|
__func__, dd->dd_name, (uint8_t *) dd->dd_desc,
|
|
|
|
(u_long) dd->dd_desc_len, (caddr_t) dd->dd_desc_paddr,
|
|
|
|
/*XXX*/ (u_long) dd->dd_desc_len);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
fail2:
|
|
|
|
bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
|
|
|
|
fail1:
|
|
|
|
bus_dma_tag_destroy(dd->dd_dmat);
|
|
|
|
memset(dd, 0, sizeof(*dd));
|
|
|
|
return error;
|
|
|
|
#undef DS2PHYS
|
|
|
|
#undef ATH_DESC_4KB_BOUND_CHECK
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ath_descdma_setup(struct ath_softc *sc,
|
|
|
|
struct ath_descdma *dd, ath_bufhead *head,
|
|
|
|
const char *name, int ds_size, int nbuf, int ndesc)
|
|
|
|
{
|
|
|
|
#define DS2PHYS(_dd, _ds) \
|
|
|
|
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
|
|
|
|
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
|
|
|
|
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
uint8_t *ds;
|
|
|
|
struct ath_buf *bf;
|
|
|
|
int i, bsize, error;
|
|
|
|
|
|
|
|
/* Allocate descriptors */
|
|
|
|
error = ath_descdma_alloc_desc(sc, dd, head, name, ds_size,
|
2012-07-27 05:48:42 +00:00
|
|
|
nbuf * ndesc);
|
2012-07-27 05:34:45 +00:00
|
|
|
|
|
|
|
/* Assume any errors during allocation were dealt with */
|
|
|
|
if (error != 0) {
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
ds = (uint8_t *) dd->dd_desc;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2006-02-27 17:20:23 +00:00
|
|
|
/* allocate rx buffers */
|
2004-12-08 17:34:36 +00:00
|
|
|
bsize = sizeof(struct ath_buf) * nbuf;
|
|
|
|
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
|
|
|
|
if (bf == NULL) {
|
|
|
|
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
|
|
|
|
dd->dd_name, bsize);
|
|
|
|
goto fail3;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
dd->dd_bufptr = bf;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2011-11-08 17:08:12 +00:00
|
|
|
TAILQ_INIT(head);
|
2012-07-23 02:26:33 +00:00
|
|
|
for (i = 0; i < nbuf; i++, bf++, ds += (ndesc * dd->dd_descsize)) {
|
2011-07-31 08:01:41 +00:00
|
|
|
bf->bf_desc = (struct ath_desc *) ds;
|
2004-12-08 17:34:36 +00:00
|
|
|
bf->bf_daddr = DS2PHYS(dd, ds);
|
2011-07-31 08:01:41 +00:00
|
|
|
if (! ath_hal_split4ktrans(sc->sc_ah)) {
|
|
|
|
/*
|
|
|
|
* Merlin WAR: Skip descriptor addresses which
|
|
|
|
* cause 4KB boundary crossing along any point
|
|
|
|
* in the descriptor.
|
|
|
|
*/
|
|
|
|
if (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr,
|
2012-07-29 08:52:32 +00:00
|
|
|
dd->dd_descsize)) {
|
2011-07-31 08:01:41 +00:00
|
|
|
/* Start at the next page */
|
|
|
|
ds += 0x1000 - (bf->bf_daddr & 0xFFF);
|
|
|
|
bf->bf_desc = (struct ath_desc *) ds;
|
|
|
|
bf->bf_daddr = DS2PHYS(dd, ds);
|
|
|
|
}
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
|
2004-12-08 17:34:36 +00:00
|
|
|
&bf->bf_dmamap);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "unable to create dmamap for %s "
|
|
|
|
"buffer %u, error %u\n", dd->dd_name, i, error);
|
|
|
|
ath_descdma_cleanup(sc, dd, head);
|
|
|
|
return error;
|
|
|
|
}
|
2011-11-08 21:25:36 +00:00
|
|
|
bf->bf_lastds = bf->bf_desc; /* Just an initial value */
|
2011-11-08 17:08:12 +00:00
|
|
|
TAILQ_INSERT_TAIL(head, bf, bf_list);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2012-07-29 08:52:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX TODO: ensure that ds doesn't overflow the descriptor
|
|
|
|
* allocation otherwise weird stuff will occur and crash your
|
|
|
|
* machine.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
return 0;
|
2012-07-27 05:34:45 +00:00
|
|
|
/* XXX this should likely just call ath_descdma_cleanup() */
|
2004-12-08 17:34:36 +00:00
|
|
|
fail3:
|
|
|
|
bus_dmamap_unload(dd->dd_dmat, dd->dd_dmamap);
|
|
|
|
bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
|
|
|
|
bus_dma_tag_destroy(dd->dd_dmat);
|
|
|
|
memset(dd, 0, sizeof(*dd));
|
2003-06-23 17:01:19 +00:00
|
|
|
return error;
|
2004-12-08 17:34:36 +00:00
|
|
|
#undef DS2PHYS
|
2011-07-31 08:01:41 +00:00
|
|
|
#undef ATH_DESC_4KB_BOUND_CHECK
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2012-07-14 02:07:51 +00:00
|
|
|
/*
|
|
|
|
* Allocate ath_buf entries but no descriptor contents.
|
|
|
|
*
|
|
|
|
* This is for RX EDMA where the descriptors are the header part of
|
|
|
|
* the RX buffer.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ath_descdma_setup_rx_edma(struct ath_softc *sc,
|
|
|
|
struct ath_descdma *dd, ath_bufhead *head,
|
|
|
|
const char *name, int nbuf, int rx_status_len)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ath_buf *bf;
|
|
|
|
int i, bsize, error;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers\n",
|
|
|
|
__func__, name, nbuf);
|
|
|
|
|
|
|
|
dd->dd_name = name;
|
|
|
|
/*
|
|
|
|
* This is (mostly) purely for show. We're not allocating any actual
|
|
|
|
* descriptors here as EDMA RX has the descriptor be part
|
|
|
|
* of the RX buffer.
|
|
|
|
*
|
|
|
|
* However, dd_desc_len is used by ath_descdma_free() to determine
|
|
|
|
* whether we have already freed this DMA mapping.
|
|
|
|
*/
|
2012-07-23 02:26:33 +00:00
|
|
|
dd->dd_desc_len = rx_status_len * nbuf;
|
|
|
|
dd->dd_descsize = rx_status_len;
|
2012-07-14 02:07:51 +00:00
|
|
|
|
|
|
|
/* allocate rx buffers */
|
|
|
|
bsize = sizeof(struct ath_buf) * nbuf;
|
|
|
|
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
|
|
|
|
if (bf == NULL) {
|
|
|
|
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
|
|
|
|
dd->dd_name, bsize);
|
2012-07-14 05:51:54 +00:00
|
|
|
error = ENOMEM;
|
2012-07-14 02:07:51 +00:00
|
|
|
goto fail3;
|
|
|
|
}
|
|
|
|
dd->dd_bufptr = bf;
|
|
|
|
|
|
|
|
TAILQ_INIT(head);
|
|
|
|
for (i = 0; i < nbuf; i++, bf++) {
|
|
|
|
bf->bf_desc = NULL;
|
|
|
|
bf->bf_daddr = 0;
|
|
|
|
bf->bf_lastds = NULL; /* Just an initial value */
|
|
|
|
|
|
|
|
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
|
|
|
|
&bf->bf_dmamap);
|
|
|
|
if (error != 0) {
|
|
|
|
if_printf(ifp, "unable to create dmamap for %s "
|
|
|
|
"buffer %u, error %u\n", dd->dd_name, i, error);
|
|
|
|
ath_descdma_cleanup(sc, dd, head);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
TAILQ_INSERT_TAIL(head, bf, bf_list);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
fail3:
|
|
|
|
memset(dd, 0, sizeof(*dd));
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2012-07-09 08:37:59 +00:00
|
|
|
void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_descdma_cleanup(struct ath_softc *sc,
|
|
|
|
struct ath_descdma *dd, ath_bufhead *head)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
|
|
|
struct ath_buf *bf;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ieee80211_node *ni;
|
2013-04-02 06:24:22 +00:00
|
|
|
int do_warning = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-14 02:47:16 +00:00
|
|
|
if (dd->dd_dmamap != 0) {
|
|
|
|
bus_dmamap_unload(dd->dd_dmat, dd->dd_dmamap);
|
|
|
|
bus_dmamem_free(dd->dd_dmat, dd->dd_desc, dd->dd_dmamap);
|
|
|
|
bus_dma_tag_destroy(dd->dd_dmat);
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-27 10:38:17 +00:00
|
|
|
if (head != NULL) {
|
|
|
|
TAILQ_FOREACH(bf, head, bf_list) {
|
|
|
|
if (bf->bf_m) {
|
2013-04-02 06:24:22 +00:00
|
|
|
/*
|
|
|
|
* XXX warn if there's buffers here.
|
|
|
|
* XXX it should have been freed by the
|
|
|
|
* owner!
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (do_warning == 0) {
|
|
|
|
do_warning = 1;
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: %s: mbuf should've been"
|
|
|
|
" unmapped/freed!\n",
|
|
|
|
__func__,
|
|
|
|
dd->dd_name);
|
|
|
|
}
|
|
|
|
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
|
|
|
|
BUS_DMASYNC_POSTREAD);
|
|
|
|
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
|
2012-07-27 10:38:17 +00:00
|
|
|
m_freem(bf->bf_m);
|
|
|
|
bf->bf_m = NULL;
|
|
|
|
}
|
|
|
|
if (bf->bf_dmamap != NULL) {
|
|
|
|
bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
|
|
|
|
bf->bf_dmamap = NULL;
|
|
|
|
}
|
|
|
|
ni = bf->bf_node;
|
|
|
|
bf->bf_node = NULL;
|
|
|
|
if (ni != NULL) {
|
|
|
|
/*
|
|
|
|
* Reclaim node reference.
|
|
|
|
*/
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-27 10:38:17 +00:00
|
|
|
if (head != NULL)
|
|
|
|
TAILQ_INIT(head);
|
|
|
|
|
|
|
|
if (dd->dd_bufptr != NULL)
|
|
|
|
free(dd->dd_bufptr, M_ATHDEV);
|
2004-12-08 17:34:36 +00:00
|
|
|
memset(dd, 0, sizeof(*dd));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ath_desc_alloc(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
|
2013-04-01 20:12:21 +00:00
|
|
|
"tx", sc->sc_tx_desclen, ath_txbuf, ATH_MAX_SCATTER);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (error != 0) {
|
|
|
|
return error;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2012-06-14 00:51:53 +00:00
|
|
|
sc->sc_txbuf_cnt = ath_txbuf;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
error = ath_descdma_setup(sc, &sc->sc_txdma_mgmt, &sc->sc_txbuf_mgmt,
|
2012-07-23 23:40:13 +00:00
|
|
|
"tx_mgmt", sc->sc_tx_desclen, ath_txbuf_mgmt,
|
|
|
|
ATH_TXDESC);
|
2012-06-13 06:57:55 +00:00
|
|
|
if (error != 0) {
|
|
|
|
ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX mark txbuf_mgmt frames with ATH_BUF_MGMT, so the
|
|
|
|
* flag doesn't have to be set in ath_getbuf_locked().
|
|
|
|
*/
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
|
2012-07-23 23:40:13 +00:00
|
|
|
"beacon", sc->sc_tx_desclen, ATH_BCBUF, 1);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (error != 0) {
|
2012-06-13 06:57:55 +00:00
|
|
|
ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
|
|
|
|
ath_descdma_cleanup(sc, &sc->sc_txdma_mgmt,
|
|
|
|
&sc->sc_txbuf_mgmt);
|
2004-12-08 17:34:36 +00:00
|
|
|
return error;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
static void
|
|
|
|
ath_desc_free(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (sc->sc_bdma.dd_desc_len != 0)
|
|
|
|
ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf);
|
|
|
|
if (sc->sc_txdma.dd_desc_len != 0)
|
|
|
|
ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
|
2012-06-13 06:57:55 +00:00
|
|
|
if (sc->sc_txdma_mgmt.dd_desc_len != 0)
|
|
|
|
ath_descdma_cleanup(sc, &sc->sc_txdma_mgmt,
|
|
|
|
&sc->sc_txbuf_mgmt);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211_node *
|
2008-06-07 18:38:02 +00:00
|
|
|
ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2008-06-07 18:38:02 +00:00
|
|
|
struct ieee80211com *ic = vap->iv_ic;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
|
|
|
|
struct ath_node *an;
|
|
|
|
|
|
|
|
an = malloc(space, M_80211_NODE, M_NOWAIT|M_ZERO);
|
|
|
|
if (an == NULL) {
|
|
|
|
/* XXX stat+msg */
|
2003-09-15 22:34:46 +00:00
|
|
|
return NULL;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
ath_rate_node_init(sc, an);
|
|
|
|
|
2011-11-08 02:12:11 +00:00
|
|
|
/* Setup the mutex - there's no associd yet so set the name to NULL */
|
|
|
|
snprintf(an->an_name, sizeof(an->an_name), "%s: node %p",
|
|
|
|
device_get_nameunit(sc->sc_dev), an);
|
|
|
|
mtx_init(&an->an_mtx, an->an_name, NULL, MTX_DEF);
|
|
|
|
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
/* XXX setup ath_tid */
|
|
|
|
ath_tx_tid_init(sc, an);
|
|
|
|
|
2013-05-13 19:52:35 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, mac, ":", an);
|
2004-12-08 17:34:36 +00:00
|
|
|
return &an->an_node;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2011-11-08 18:48:26 +00:00
|
|
|
static void
|
|
|
|
ath_node_cleanup(struct ieee80211_node *ni)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
|
2013-05-13 19:52:35 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
|
|
|
|
ni->ni_macaddr, ":", ATH_NODE(ni));
|
|
|
|
|
2011-11-08 18:48:26 +00:00
|
|
|
/* Cleanup ath_tid, free unused bufs, unlink bufs in TXQ */
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
ath_tx_node_flush(sc, ATH_NODE(ni));
|
2011-11-08 18:48:26 +00:00
|
|
|
ath_rate_node_cleanup(sc, ATH_NODE(ni));
|
|
|
|
sc->sc_node_cleanup(ni);
|
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_node_free(struct ieee80211_node *ni)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
2011-11-08 18:48:26 +00:00
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
2004-04-03 00:06:23 +00:00
|
|
|
|
2013-05-13 19:52:35 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
|
|
|
|
ni->ni_macaddr, ":", ATH_NODE(ni));
|
2011-11-08 02:12:11 +00:00
|
|
|
mtx_destroy(&ATH_NODE(ni)->an_mtx);
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_node_free(ni);
|
|
|
|
}
|
2003-09-15 22:34:46 +00:00
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
static void
|
|
|
|
ath_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
*rssi = ic->ic_node_getrssi(ni);
|
2009-01-28 18:00:22 +00:00
|
|
|
if (ni->ni_chan != IEEE80211_CHAN_ANYC)
|
|
|
|
*noise = ath_hal_getchannoise(ah, ni->ni_chan);
|
|
|
|
else
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
*noise = -95; /* nominally correct */
|
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Set the default antenna.
|
|
|
|
*/
|
2012-05-20 02:05:10 +00:00
|
|
|
void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_setdefantenna(struct ath_softc *sc, u_int antenna)
|
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
|
|
|
|
/* XXX block beacon interrupts */
|
|
|
|
ath_hal_setdefantenna(ah, antenna);
|
|
|
|
if (sc->sc_defant != antenna)
|
|
|
|
sc->sc_stats.ast_ant_defswitch++;
|
|
|
|
sc->sc_defant = antenna;
|
|
|
|
sc->sc_rxotherant = 0;
|
|
|
|
}
|
|
|
|
|
2006-06-26 03:10:45 +00:00
|
|
|
static void
|
|
|
|
ath_txq_init(struct ath_softc *sc, struct ath_txq *txq, int qnum)
|
|
|
|
{
|
|
|
|
txq->axq_qnum = qnum;
|
2009-03-30 21:53:27 +00:00
|
|
|
txq->axq_ac = 0;
|
2006-06-26 03:10:45 +00:00
|
|
|
txq->axq_depth = 0;
|
2011-11-08 19:18:34 +00:00
|
|
|
txq->axq_aggr_depth = 0;
|
2006-06-26 03:10:45 +00:00
|
|
|
txq->axq_intrcnt = 0;
|
|
|
|
txq->axq_link = NULL;
|
2011-11-08 17:08:12 +00:00
|
|
|
txq->axq_softc = sc;
|
|
|
|
TAILQ_INIT(&txq->axq_q);
|
|
|
|
TAILQ_INIT(&txq->axq_tidq);
|
2013-03-26 19:46:51 +00:00
|
|
|
TAILQ_INIT(&txq->fifo.axq_q);
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK_INIT(sc, txq);
|
2006-06-26 03:10:45 +00:00
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* Setup a h/w transmit queue.
|
|
|
|
*/
|
|
|
|
static struct ath_txq *
|
|
|
|
ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
|
|
|
{
|
|
|
|
#define N(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
HAL_TXQ_INFO qi;
|
|
|
|
int qnum;
|
|
|
|
|
|
|
|
memset(&qi, 0, sizeof(qi));
|
|
|
|
qi.tqi_subtype = subtype;
|
|
|
|
qi.tqi_aifs = HAL_TXQ_USEDEFAULT;
|
|
|
|
qi.tqi_cwmin = HAL_TXQ_USEDEFAULT;
|
|
|
|
qi.tqi_cwmax = HAL_TXQ_USEDEFAULT;
|
|
|
|
/*
|
|
|
|
* Enable interrupts only for EOL and DESC conditions.
|
|
|
|
* We mark tx descriptors to receive a DESC interrupt
|
|
|
|
* when a tx queue gets deep; otherwise waiting for the
|
|
|
|
* EOL to reap descriptors. Note that this is done to
|
|
|
|
* reduce interrupt load and this only defers reaping
|
|
|
|
* descriptors, never transmitting frames. Aside from
|
|
|
|
* reducing interrupts this also permits more concurrency.
|
|
|
|
* The only potential downside is if the tx queue backs
|
|
|
|
* up in which case the top half of the kernel may backup
|
|
|
|
* due to a lack of tx descriptors.
|
|
|
|
*/
|
2013-04-11 22:02:35 +00:00
|
|
|
if (sc->sc_isedma)
|
|
|
|
qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE |
|
|
|
|
HAL_TXQ_TXOKINT_ENABLE;
|
|
|
|
else
|
|
|
|
qi.tqi_qflags = HAL_TXQ_TXEOLINT_ENABLE |
|
|
|
|
HAL_TXQ_TXDESCINT_ENABLE;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
qnum = ath_hal_setuptxqueue(ah, qtype, &qi);
|
|
|
|
if (qnum == -1) {
|
|
|
|
/*
|
2005-06-06 16:39:21 +00:00
|
|
|
* NB: don't print a message, this happens
|
2004-12-31 20:35:05 +00:00
|
|
|
* normally on parts with too few tx queues
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (qnum >= N(sc->sc_txq)) {
|
2004-12-15 02:25:21 +00:00
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"hal qnum %u out of range, max %zu!\n",
|
2004-12-08 17:34:36 +00:00
|
|
|
qnum, N(sc->sc_txq));
|
|
|
|
ath_hal_releasetxqueue(ah, qnum);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (!ATH_TXQ_SETUP(sc, qnum)) {
|
2006-06-26 03:10:45 +00:00
|
|
|
ath_txq_init(sc, &sc->sc_txq[qnum], qnum);
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_txqsetup |= 1<<qnum;
|
|
|
|
}
|
|
|
|
return &sc->sc_txq[qnum];
|
|
|
|
#undef N
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup a hardware data transmit queue for the specified
|
|
|
|
* access control. The hal may not support all requested
|
|
|
|
* queues in which case it will return a reference to a
|
|
|
|
* previously setup queue. We record the mapping from ac's
|
|
|
|
* to h/w queues for use by ath_tx_start and also track
|
|
|
|
* the set of h/w queues being used to optimize work in the
|
|
|
|
* transmit interrupt handler and related routines.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_tx_setup(struct ath_softc *sc, int ac, int haltype)
|
|
|
|
{
|
|
|
|
#define N(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
struct ath_txq *txq;
|
|
|
|
|
|
|
|
if (ac >= N(sc->sc_ac2q)) {
|
2004-12-15 02:25:21 +00:00
|
|
|
device_printf(sc->sc_dev, "AC %u out of range, max %zu!\n",
|
2004-12-08 17:34:36 +00:00
|
|
|
ac, N(sc->sc_ac2q));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
txq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, haltype);
|
|
|
|
if (txq != NULL) {
|
2009-03-30 21:53:27 +00:00
|
|
|
txq->axq_ac = ac;
|
2004-12-08 17:34:36 +00:00
|
|
|
sc->sc_ac2q[ac] = txq;
|
|
|
|
return 1;
|
|
|
|
} else
|
|
|
|
return 0;
|
|
|
|
#undef N
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update WME parameters for a transmit queue.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_txq_update(struct ath_softc *sc, int ac)
|
|
|
|
{
|
|
|
|
#define ATH_EXPONENT_TO_VALUE(v) ((1<<v)-1)
|
|
|
|
#define ATH_TXOP_TO_US(v) (v<<5)
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_txq *txq = sc->sc_ac2q[ac];
|
|
|
|
struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
HAL_TXQ_INFO qi;
|
|
|
|
|
|
|
|
ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (sc->sc_tdma) {
|
|
|
|
/*
|
|
|
|
* AIFS is zero so there's no pre-transmit wait. The
|
|
|
|
* burst time defines the slot duration and is configured
|
2009-06-02 21:12:07 +00:00
|
|
|
* through net80211. The QCU is setup to not do post-xmit
|
2009-01-08 17:12:47 +00:00
|
|
|
* back off, lockout all lower-priority QCU's, and fire
|
|
|
|
* off the DMA beacon alert timer which is setup based
|
|
|
|
* on the slot configuration.
|
|
|
|
*/
|
|
|
|
qi.tqi_qflags = HAL_TXQ_TXOKINT_ENABLE
|
|
|
|
| HAL_TXQ_TXERRINT_ENABLE
|
|
|
|
| HAL_TXQ_TXURNINT_ENABLE
|
|
|
|
| HAL_TXQ_TXEOLINT_ENABLE
|
|
|
|
| HAL_TXQ_DBA_GATED
|
|
|
|
| HAL_TXQ_BACKOFF_DISABLE
|
|
|
|
| HAL_TXQ_ARB_LOCKOUT_GLOBAL
|
|
|
|
;
|
|
|
|
qi.tqi_aifs = 0;
|
|
|
|
/* XXX +dbaprep? */
|
|
|
|
qi.tqi_readyTime = sc->sc_tdmaslotlen;
|
|
|
|
qi.tqi_burstTime = qi.tqi_readyTime;
|
|
|
|
} else {
|
|
|
|
#endif
|
2011-11-08 19:18:34 +00:00
|
|
|
/*
|
|
|
|
* XXX shouldn't this just use the default flags
|
|
|
|
* used in the previous queue setup?
|
|
|
|
*/
|
2009-01-08 17:12:47 +00:00
|
|
|
qi.tqi_qflags = HAL_TXQ_TXOKINT_ENABLE
|
|
|
|
| HAL_TXQ_TXERRINT_ENABLE
|
|
|
|
| HAL_TXQ_TXDESCINT_ENABLE
|
|
|
|
| HAL_TXQ_TXURNINT_ENABLE
|
2011-11-08 21:55:40 +00:00
|
|
|
| HAL_TXQ_TXEOLINT_ENABLE
|
2009-01-08 17:12:47 +00:00
|
|
|
;
|
|
|
|
qi.tqi_aifs = wmep->wmep_aifsn;
|
|
|
|
qi.tqi_cwmin = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmin);
|
|
|
|
qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
|
|
|
|
qi.tqi_readyTime = 0;
|
|
|
|
qi.tqi_burstTime = ATH_TXOP_TO_US(wmep->wmep_txopLimit);
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET,
|
|
|
|
"%s: Q%u qflags 0x%x aifs %u cwmin %u cwmax %u burstTime %u\n",
|
|
|
|
__func__, txq->axq_qnum, qi.tqi_qflags,
|
|
|
|
qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
|
2008-04-20 20:35:46 +00:00
|
|
|
if_printf(ifp, "unable to update hardware queue "
|
2004-12-08 17:34:36 +00:00
|
|
|
"parameters for %s traffic!\n",
|
|
|
|
ieee80211_wme_acnames[ac]);
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to h/w */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#undef ATH_TXOP_TO_US
|
|
|
|
#undef ATH_EXPONENT_TO_VALUE
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Callback from the 802.11 layer to update WME parameters.
|
|
|
|
*/
|
2012-05-20 02:49:42 +00:00
|
|
|
int
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_wme_update(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
|
|
|
|
return !ath_txq_update(sc, WME_AC_BE) ||
|
|
|
|
!ath_txq_update(sc, WME_AC_BK) ||
|
|
|
|
!ath_txq_update(sc, WME_AC_VI) ||
|
|
|
|
!ath_txq_update(sc, WME_AC_VO) ? EIO : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reclaim resources for a setup queue.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
|
{
|
|
|
|
|
|
|
|
ath_hal_releasetxqueue(sc->sc_ah, txq->axq_qnum);
|
|
|
|
sc->sc_txqsetup &= ~(1<<txq->axq_qnum);
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK_DESTROY(txq);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reclaim all tx queue resources.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2004-12-08 17:34:36 +00:00
|
|
|
static void
|
|
|
|
ath_tx_cleanup(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ATH_TXBUF_LOCK_DESTROY(sc);
|
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
|
|
|
|
if (ATH_TXQ_SETUP(sc, i))
|
|
|
|
ath_tx_cleanupq(sc, &sc->sc_txq[i]);
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2006-02-09 21:15:36 +00:00
|
|
|
/*
|
2009-05-07 00:35:32 +00:00
|
|
|
* Return h/w rate index for an IEEE rate (w/o basic rate bit)
|
|
|
|
* using the current rates in sc_rixmap.
|
2006-02-09 21:15:36 +00:00
|
|
|
*/
|
2011-01-29 11:35:23 +00:00
|
|
|
int
|
2009-05-07 00:35:32 +00:00
|
|
|
ath_tx_findrix(const struct ath_softc *sc, uint8_t rate)
|
2006-02-09 21:15:36 +00:00
|
|
|
{
|
2009-05-07 00:35:32 +00:00
|
|
|
int rix = sc->sc_rixmap[rate];
|
|
|
|
/* NB: return lowest rix for invalid rate */
|
|
|
|
return (rix == 0xff ? 0 : rix);
|
2006-02-09 21:15:36 +00:00
|
|
|
}
|
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
static void
|
|
|
|
ath_tx_update_stats(struct ath_softc *sc, struct ath_tx_status *ts,
|
|
|
|
struct ath_buf *bf)
|
|
|
|
{
|
|
|
|
struct ieee80211_node *ni = bf->bf_node;
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
int sr, lr, pri;
|
|
|
|
|
|
|
|
if (ts->ts_status == 0) {
|
|
|
|
u_int8_t txant = ts->ts_antenna;
|
|
|
|
sc->sc_stats.ast_ant_tx[txant]++;
|
|
|
|
sc->sc_ant_tx[txant]++;
|
|
|
|
if (ts->ts_finaltsi != 0)
|
|
|
|
sc->sc_stats.ast_tx_altrate++;
|
|
|
|
pri = M_WME_GETAC(bf->bf_m);
|
|
|
|
if (pri >= WME_AC_VO)
|
|
|
|
ic->ic_wme.wme_hipri_traffic++;
|
2012-04-07 02:01:26 +00:00
|
|
|
if ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0)
|
2011-11-08 21:49:33 +00:00
|
|
|
ni->ni_inact = ni->ni_inact_reload;
|
|
|
|
} else {
|
|
|
|
if (ts->ts_status & HAL_TXERR_XRETRY)
|
|
|
|
sc->sc_stats.ast_tx_xretries++;
|
|
|
|
if (ts->ts_status & HAL_TXERR_FIFO)
|
|
|
|
sc->sc_stats.ast_tx_fifoerr++;
|
|
|
|
if (ts->ts_status & HAL_TXERR_FILT)
|
|
|
|
sc->sc_stats.ast_tx_filtered++;
|
|
|
|
if (ts->ts_status & HAL_TXERR_XTXOP)
|
|
|
|
sc->sc_stats.ast_tx_xtxop++;
|
|
|
|
if (ts->ts_status & HAL_TXERR_TIMER_EXPIRED)
|
|
|
|
sc->sc_stats.ast_tx_timerexpired++;
|
|
|
|
|
|
|
|
if (bf->bf_m->m_flags & M_FF)
|
|
|
|
sc->sc_stats.ast_ff_txerr++;
|
|
|
|
}
|
|
|
|
/* XXX when is this valid? */
|
2013-02-20 11:14:55 +00:00
|
|
|
if (ts->ts_flags & HAL_TX_DESC_CFG_ERR)
|
2011-11-08 21:49:33 +00:00
|
|
|
sc->sc_stats.ast_tx_desccfgerr++;
|
2013-02-20 11:14:55 +00:00
|
|
|
/*
|
|
|
|
* This can be valid for successful frame transmission!
|
|
|
|
* If there's a TX FIFO underrun during aggregate transmission,
|
|
|
|
* the MAC will pad the rest of the aggregate with delimiters.
|
|
|
|
* If a BA is returned, the frame is marked as "OK" and it's up
|
|
|
|
* to the TX completion code to notice which frames weren't
|
|
|
|
* successfully transmitted.
|
|
|
|
*/
|
|
|
|
if (ts->ts_flags & HAL_TX_DATA_UNDERRUN)
|
|
|
|
sc->sc_stats.ast_tx_data_underrun++;
|
|
|
|
if (ts->ts_flags & HAL_TX_DELIM_UNDERRUN)
|
|
|
|
sc->sc_stats.ast_tx_delim_underrun++;
|
2011-11-08 21:49:33 +00:00
|
|
|
|
|
|
|
sr = ts->ts_shortretry;
|
|
|
|
lr = ts->ts_longretry;
|
|
|
|
sc->sc_stats.ast_tx_shortretry += sr;
|
|
|
|
sc->sc_stats.ast_tx_longretry += lr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The default completion. If fail is 1, this means
|
|
|
|
* "please don't retry the frame, and just return -1 status
|
|
|
|
* to the net80211 stack.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail)
|
|
|
|
{
|
|
|
|
struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
|
|
|
|
int st;
|
|
|
|
|
|
|
|
if (fail == 1)
|
|
|
|
st = -1;
|
|
|
|
else
|
2012-04-07 02:01:26 +00:00
|
|
|
st = ((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0) ?
|
2011-11-08 21:49:33 +00:00
|
|
|
ts->ts_status : HAL_TXERR_XRETRY;
|
|
|
|
|
2013-02-21 21:47:35 +00:00
|
|
|
#if 0
|
2011-11-08 21:49:33 +00:00
|
|
|
if (bf->bf_state.bfs_dobaw)
|
|
|
|
device_printf(sc->sc_dev,
|
2012-03-16 23:24:27 +00:00
|
|
|
"%s: bf %p: seqno %d: dobaw should've been cleared!\n",
|
|
|
|
__func__,
|
|
|
|
bf,
|
|
|
|
SEQNO(bf->bf_state.bfs_seqno));
|
2013-02-21 21:47:35 +00:00
|
|
|
#endif
|
2011-11-08 21:49:33 +00:00
|
|
|
if (bf->bf_next != NULL)
|
|
|
|
device_printf(sc->sc_dev,
|
2012-03-16 23:24:27 +00:00
|
|
|
"%s: bf %p: seqno %d: bf_next not NULL!\n",
|
|
|
|
__func__,
|
|
|
|
bf,
|
|
|
|
SEQNO(bf->bf_state.bfs_seqno));
|
2011-11-08 21:49:33 +00:00
|
|
|
|
2012-10-28 21:13:12 +00:00
|
|
|
/*
|
|
|
|
* Check if the node software queue is empty; if so
|
|
|
|
* then clear the TIM.
|
|
|
|
*
|
|
|
|
* This needs to be done before the buffer is freed as
|
|
|
|
* otherwise the node reference will have been released
|
|
|
|
* and the node may not actually exist any longer.
|
|
|
|
*
|
|
|
|
* XXX I don't like this belonging here, but it's cleaner
|
|
|
|
* to do it here right now then all the other places
|
|
|
|
* where ath_tx_default_comp() is called.
|
|
|
|
*
|
|
|
|
* XXX TODO: during drain, ensure that the callback is
|
|
|
|
* being called so we get a chance to update the TIM.
|
|
|
|
*/
|
2013-05-13 18:56:04 +00:00
|
|
|
if (bf->bf_node) {
|
|
|
|
ATH_TX_LOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
ath_tx_update_tim(sc, bf->bf_node, 0);
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
|
|
|
}
|
2012-10-28 21:13:12 +00:00
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
/*
|
|
|
|
* Do any tx complete callback. Note this must
|
|
|
|
* be done before releasing the node reference.
|
|
|
|
* This will free the mbuf, release the net80211
|
|
|
|
* node and recycle the ath_buf.
|
|
|
|
*/
|
|
|
|
ath_tx_freebuf(sc, bf, st);
|
|
|
|
}
|
|
|
|
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
/*
|
|
|
|
* Update rate control with the given completion status.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni,
|
|
|
|
struct ath_rc_series *rc, struct ath_tx_status *ts, int frmlen,
|
|
|
|
int nframes, int nbad)
|
|
|
|
{
|
|
|
|
struct ath_node *an;
|
|
|
|
|
|
|
|
/* Only for unicast frames */
|
|
|
|
if (ni == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
an = ATH_NODE(ni);
|
2012-10-28 21:13:12 +00:00
|
|
|
ATH_NODE_UNLOCK_ASSERT(an);
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
|
|
|
|
if ((ts->ts_status & HAL_TXERR_FILT) == 0) {
|
|
|
|
ATH_NODE_LOCK(an);
|
|
|
|
ath_rate_tx_complete(sc, an, rc, ts, frmlen, nframes, nbad);
|
|
|
|
ATH_NODE_UNLOCK(an);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 22:32:20 +00:00
|
|
|
/*
|
|
|
|
* Process the completion of the given buffer.
|
|
|
|
*
|
|
|
|
* This calls the rate control update and then the buffer completion.
|
|
|
|
* This will either free the buffer or requeue it. In any case, the
|
|
|
|
* bf pointer should be treated as invalid after this function is called.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq,
|
|
|
|
struct ath_tx_status *ts, struct ath_buf *bf)
|
|
|
|
{
|
|
|
|
struct ieee80211_node *ni = bf->bf_node;
|
|
|
|
struct ath_node *an = NULL;
|
|
|
|
|
Delete the per-TXQ locks and replace them with a single TX lock.
I couldn't think of a way to maintain the hardware TXQ locks _and_ layer
on top of that per-TXQ software queuing and any other kind of fine-grained
locks (eg per-TID, or per-node locks.)
So for now, to facilitate some further code refactoring and development
as part of the final push to get software queue ps-poll and u-apsd handling
into this driver, just do away with them entirely.
I may eventually bring them back at some point, when it looks slightly more
architectually cleaner to do so. But as it stands at the present, it's
not really buying us much:
* in order to properly serialise things and not get bitten by scheduling
and locking interactions with things higher up in the stack, we need to
wrap the whole TX path in a long held lock. Otherwise we can end up
being pre-empted during frame handling, resulting in some out of order
frame handling between sequence number allocation and encryption handling
(ie, the seqno and the CCMP IV get out of sequence);
* .. so whilst that's the case, holding the lock for that long means that
we're acquiring and releasing the TXQ lock _inside_ that context;
* And we also acquire it per-frame during frame completion, but we currently
can't hold the lock for the duration of the TX completion as we need
to call net80211 layer things with the locks _unheld_ to avoid LOR.
* .. the other places were grab that lock are reset/flush, which don't happen
often.
My eventual aim is to change the TX path so all rejected frame transmissions
and all frame completions result in any ieee80211_free_node() calls to occur
outside of the TX lock; then I can cut back on the amount of locking that
goes on here.
There may be some LORs that occur when ieee80211_free_node() is called when
the TX queue path fails; I'll begin to address these in follow-up commits.
2012-12-02 06:24:08 +00:00
|
|
|
ATH_TX_UNLOCK_ASSERT(sc);
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXQ_UNLOCK_ASSERT(txq);
|
2012-08-14 22:32:20 +00:00
|
|
|
|
|
|
|
/* If unicast frame, update general statistics */
|
|
|
|
if (ni != NULL) {
|
|
|
|
an = ATH_NODE(ni);
|
|
|
|
/* update statistics */
|
|
|
|
ath_tx_update_stats(sc, ts, bf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Call the completion handler.
|
|
|
|
* The completion handler is responsible for
|
|
|
|
* calling the rate control code.
|
|
|
|
*
|
|
|
|
* Frames with no completion handler get the
|
|
|
|
* rate control code called here.
|
|
|
|
*/
|
|
|
|
if (bf->bf_comp == NULL) {
|
|
|
|
if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
|
|
|
|
(bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0) {
|
|
|
|
/*
|
|
|
|
* XXX assume this isn't an aggregate
|
|
|
|
* frame.
|
|
|
|
*/
|
|
|
|
ath_tx_update_ratectrl(sc, ni,
|
|
|
|
bf->bf_state.bfs_rc, ts,
|
|
|
|
bf->bf_state.bfs_pktlen, 1,
|
|
|
|
(ts->ts_status == 0 ? 0 : 1));
|
|
|
|
}
|
|
|
|
ath_tx_default_comp(sc, bf, 0);
|
|
|
|
} else
|
|
|
|
bf->bf_comp(sc, bf, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Process completed xmit descriptors from the specified queue.
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
* Kick the packet scheduler if needed. This can occur from this
|
|
|
|
* particular task.
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
2012-08-12 00:37:29 +00:00
|
|
|
static int
|
|
|
|
ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2011-11-08 21:49:33 +00:00
|
|
|
struct ath_buf *bf;
|
2011-11-08 21:25:36 +00:00
|
|
|
struct ath_desc *ds;
|
2006-12-13 19:34:35 +00:00
|
|
|
struct ath_tx_status *ts;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ieee80211_node *ni;
|
2012-04-11 02:34:32 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
2012-04-10 19:47:44 +00:00
|
|
|
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
2012-04-11 02:34:32 +00:00
|
|
|
#endif /* IEEE80211_SUPPORT_SUPERG */
|
2011-11-08 21:49:33 +00:00
|
|
|
int nacked;
|
2003-06-23 17:01:19 +00:00
|
|
|
HAL_STATUS status;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: tx queue %u head %p link %p\n",
|
|
|
|
__func__, txq->axq_qnum,
|
|
|
|
(caddr_t)(uintptr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
|
|
|
txq->axq_link);
|
2012-09-24 20:35:56 +00:00
|
|
|
|
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 4,
|
|
|
|
"ath_tx_processq: txq=%u head %p link %p depth %p",
|
|
|
|
txq->axq_qnum,
|
|
|
|
(caddr_t)(uintptr_t) ath_hal_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
|
|
|
txq->axq_link,
|
|
|
|
txq->axq_depth);
|
|
|
|
|
2006-02-09 22:03:26 +00:00
|
|
|
nacked = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
for (;;) {
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK(txq);
|
2004-12-08 17:34:36 +00:00
|
|
|
txq->axq_intrcnt = 0; /* reset periodic desc intr count */
|
2011-11-08 17:08:12 +00:00
|
|
|
bf = TAILQ_FIRST(&txq->axq_q);
|
2003-06-23 17:01:19 +00:00
|
|
|
if (bf == NULL) {
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-08 21:25:36 +00:00
|
|
|
ds = bf->bf_lastds; /* XXX must be setup correctly! */
|
2006-12-13 19:34:35 +00:00
|
|
|
ts = &bf->bf_status.ds_txstat;
|
2012-09-24 20:35:56 +00:00
|
|
|
|
2006-12-13 19:34:35 +00:00
|
|
|
status = ath_hal_txprocdesc(ah, ds, ts);
|
2006-04-03 18:14:02 +00:00
|
|
|
#ifdef ATH_DEBUG
|
2004-12-08 17:34:36 +00:00
|
|
|
if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
|
2008-11-24 01:34:56 +00:00
|
|
|
ath_printtxbuf(sc, bf, txq->axq_qnum, 0,
|
|
|
|
status == HAL_OK);
|
2012-09-24 20:35:56 +00:00
|
|
|
else if ((sc->sc_debug & ATH_DEBUG_RESET) && (dosched == 0))
|
2012-04-04 22:24:11 +00:00
|
|
|
ath_printtxbuf(sc, bf, txq->axq_qnum, 0,
|
|
|
|
status == HAL_OK);
|
2003-06-23 17:01:19 +00:00
|
|
|
#endif
|
2012-11-16 19:57:16 +00:00
|
|
|
#ifdef ATH_DEBUG_ALQ
|
|
|
|
if (if_ath_alq_checkdebug(&sc->sc_alq,
|
|
|
|
ATH_ALQ_EDMA_TXSTATUS)) {
|
|
|
|
if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS,
|
|
|
|
sc->sc_tx_statuslen,
|
|
|
|
(char *) ds);
|
|
|
|
}
|
|
|
|
#endif
|
2012-09-24 20:35:56 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
if (status == HAL_EINPROGRESS) {
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 3,
|
|
|
|
"ath_tx_processq: txq=%u, bf=%p ds=%p, HAL_EINPROGRESS",
|
|
|
|
txq->axq_qnum, bf, ds);
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-08 17:08:12 +00:00
|
|
|
ATH_TXQ_REMOVE(txq, bf, bf_list);
|
2013-05-08 21:23:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Sanity check.
|
|
|
|
*/
|
|
|
|
if (txq->axq_qnum != bf->bf_state.bfs_tx_queue) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: TXQ=%d: bf=%p, bfs_tx_queue=%d\n",
|
|
|
|
__func__,
|
|
|
|
txq->axq_qnum,
|
|
|
|
bf,
|
|
|
|
bf->bf_state.bfs_tx_queue);
|
|
|
|
}
|
|
|
|
if (txq->axq_qnum != bf->bf_last->bf_state.bfs_tx_queue) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: TXQ=%d: bf_last=%p, bfs_tx_queue=%d\n",
|
|
|
|
__func__,
|
|
|
|
txq->axq_qnum,
|
|
|
|
bf->bf_last,
|
|
|
|
bf->bf_last->bf_state.bfs_tx_queue);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
2013-05-08 07:30:33 +00:00
|
|
|
if (txq->axq_depth > 0) {
|
|
|
|
/*
|
|
|
|
* More frames follow. Mark the buffer busy
|
|
|
|
* so it's not re-used while the hardware may
|
|
|
|
* still re-read the link field in the descriptor.
|
|
|
|
*
|
|
|
|
* Use the last buffer in an aggregate as that
|
|
|
|
* is where the hardware may be - intermediate
|
|
|
|
* descriptors won't be "busy".
|
|
|
|
*/
|
|
|
|
bf->bf_last->bf_flags |= ATH_BUF_BUSY;
|
|
|
|
} else
|
|
|
|
txq->axq_link = NULL;
|
2013-05-08 21:23:51 +00:00
|
|
|
#else
|
|
|
|
bf->bf_last->bf_flags |= ATH_BUF_BUSY;
|
|
|
|
#endif
|
2011-11-08 21:25:36 +00:00
|
|
|
if (bf->bf_state.bfs_aggr)
|
|
|
|
txq->axq_aggr_depth--;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
ni = bf->bf_node;
|
2012-09-24 20:35:56 +00:00
|
|
|
|
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 5,
|
|
|
|
"ath_tx_processq: txq=%u, bf=%p, ds=%p, ni=%p, ts_status=0x%08x",
|
|
|
|
txq->axq_qnum, bf, ds, ni, ts->ts_status);
|
2011-11-08 21:49:33 +00:00
|
|
|
/*
|
|
|
|
* If unicast frame was ack'd update RSSI,
|
|
|
|
* including the last rx time used to
|
|
|
|
* workaround phantom bmiss interrupts.
|
|
|
|
*/
|
|
|
|
if (ni != NULL && ts->ts_status == 0 &&
|
2012-04-07 02:01:26 +00:00
|
|
|
((bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) == 0)) {
|
2011-11-08 21:49:33 +00:00
|
|
|
nacked++;
|
|
|
|
sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
|
|
|
|
ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
|
|
|
|
ts->ts_rssi);
|
|
|
|
}
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
2011-11-08 21:49:33 +00:00
|
|
|
|
|
|
|
/*
|
2012-08-14 22:32:20 +00:00
|
|
|
* Update statistics and call completion
|
2011-11-08 21:49:33 +00:00
|
|
|
*/
|
2012-08-14 22:32:20 +00:00
|
|
|
ath_tx_process_buf_completion(sc, txq, ts, bf);
|
2012-10-28 21:13:12 +00:00
|
|
|
|
|
|
|
/* XXX at this point, bf and ni may be totally invalid */
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2009-03-30 21:53:27 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
/*
|
|
|
|
* Flush fast-frame staging queue when traffic slows.
|
|
|
|
*/
|
|
|
|
if (txq->axq_depth <= 1)
|
2009-05-02 20:16:55 +00:00
|
|
|
ieee80211_ff_flush(ic, txq->axq_ac);
|
2009-03-30 21:53:27 +00:00
|
|
|
#endif
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
|
2013-02-07 02:15:25 +00:00
|
|
|
/* Kick the software TXQ scheduler */
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
if (dosched) {
|
2013-02-11 07:48:26 +00:00
|
|
|
ATH_TX_LOCK(sc);
|
|
|
|
ath_txq_sched(sc, txq);
|
|
|
|
ATH_TX_UNLOCK(sc);
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
}
|
|
|
|
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
|
|
|
|
"ath_tx_processq: txq=%u: done",
|
|
|
|
txq->axq_qnum);
|
|
|
|
|
2006-02-09 22:03:26 +00:00
|
|
|
return nacked;
|
|
|
|
}
|
|
|
|
|
2011-11-08 18:10:04 +00:00
|
|
|
#define TXQACTIVE(t, q) ( (t) & (1 << (q)))
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Deferred processing of transmit interrupt; special-cased
|
|
|
|
* for a single hardware transmit queue (e.g. 5210 and 5211).
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_tx_proc_q0(void *arg, int npending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2011-11-08 18:10:04 +00:00
|
|
|
uint32_t txqs;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt++;
|
2011-11-08 18:10:04 +00:00
|
|
|
txqs = sc->sc_txq_active;
|
|
|
|
sc->sc_txq_active &= ~txqs;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2011-11-08 18:10:04 +00:00
|
|
|
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
|
|
|
|
"ath_tx_proc_q0: txqs=0x%08x", txqs);
|
|
|
|
|
2011-11-08 18:45:15 +00:00
|
|
|
if (TXQACTIVE(txqs, 0) && ath_tx_processq(sc, &sc->sc_txq[0], 1))
|
2011-11-08 18:10:04 +00:00
|
|
|
/* XXX why is lastrx updated in tx code? */
|
2006-02-09 22:03:26 +00:00
|
|
|
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, sc->sc_cabq->axq_qnum))
|
2011-11-08 18:45:15 +00:00
|
|
|
ath_tx_processq(sc, sc->sc_cabq, 1);
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2009-03-09 23:10:19 +00:00
|
|
|
sc->sc_wd_timer = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2005-01-18 19:03:04 +00:00
|
|
|
if (sc->sc_softled)
|
2008-10-27 18:22:44 +00:00
|
|
|
ath_led_event(sc, sc->sc_txrix);
|
2005-01-18 19:03:04 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
|
|
|
|
ath_tx_kick(sc);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* Deferred processing of transmit interrupt; special-cased
|
|
|
|
* for four hardware queues, 0-3 (e.g. 5212 w/ WME support).
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
|
|
|
static void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_tx_proc_q0123(void *arg, int npending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2006-02-09 22:03:26 +00:00
|
|
|
int nacked;
|
2011-11-08 18:10:04 +00:00
|
|
|
uint32_t txqs;
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt++;
|
2011-11-08 18:10:04 +00:00
|
|
|
txqs = sc->sc_txq_active;
|
|
|
|
sc->sc_txq_active &= ~txqs;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 1,
|
|
|
|
"ath_tx_proc_q0123: txqs=0x%08x", txqs);
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Process each active queue.
|
|
|
|
*/
|
2006-02-09 22:03:26 +00:00
|
|
|
nacked = 0;
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, 0))
|
2011-11-08 18:45:15 +00:00
|
|
|
nacked += ath_tx_processq(sc, &sc->sc_txq[0], 1);
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, 1))
|
2011-11-08 18:45:15 +00:00
|
|
|
nacked += ath_tx_processq(sc, &sc->sc_txq[1], 1);
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, 2))
|
2011-11-08 18:45:15 +00:00
|
|
|
nacked += ath_tx_processq(sc, &sc->sc_txq[2], 1);
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, 3))
|
2011-11-08 18:45:15 +00:00
|
|
|
nacked += ath_tx_processq(sc, &sc->sc_txq[3], 1);
|
2011-11-08 18:10:04 +00:00
|
|
|
if (TXQACTIVE(txqs, sc->sc_cabq->axq_qnum))
|
2011-11-08 18:45:15 +00:00
|
|
|
ath_tx_processq(sc, sc->sc_cabq, 1);
|
2006-02-09 22:03:26 +00:00
|
|
|
if (nacked)
|
|
|
|
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2009-03-09 23:10:19 +00:00
|
|
|
sc->sc_wd_timer = 0;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2005-01-18 19:03:04 +00:00
|
|
|
if (sc->sc_softled)
|
2008-10-27 18:22:44 +00:00
|
|
|
ath_led_event(sc, sc->sc_txrix);
|
2005-01-18 19:03:04 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
|
|
|
|
ath_tx_kick(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deferred processing of transmit interrupt.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_tx_proc(void *arg, int npending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2006-02-09 22:03:26 +00:00
|
|
|
int i, nacked;
|
2011-11-08 18:10:04 +00:00
|
|
|
uint32_t txqs;
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt++;
|
2011-11-08 18:10:04 +00:00
|
|
|
txqs = sc->sc_txq_active;
|
|
|
|
sc->sc_txq_active &= ~txqs;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-09-24 20:35:56 +00:00
|
|
|
ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc: txqs=0x%08x", txqs);
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Process each active queue.
|
|
|
|
*/
|
2006-02-09 22:03:26 +00:00
|
|
|
nacked = 0;
|
2004-12-08 17:34:36 +00:00
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++)
|
2011-11-08 18:10:04 +00:00
|
|
|
if (ATH_TXQ_SETUP(sc, i) && TXQACTIVE(txqs, i))
|
2011-11-08 18:45:15 +00:00
|
|
|
nacked += ath_tx_processq(sc, &sc->sc_txq[i], 1);
|
2006-02-09 22:03:26 +00:00
|
|
|
if (nacked)
|
|
|
|
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
/* XXX check this inside of IF_LOCK? */
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2009-03-09 23:10:19 +00:00
|
|
|
sc->sc_wd_timer = 0;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2005-01-18 19:03:04 +00:00
|
|
|
if (sc->sc_softled)
|
2008-10-27 18:22:44 +00:00
|
|
|
ath_led_event(sc, sc->sc_txrix);
|
2005-01-18 19:03:04 +00:00
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
Pull out the if_transmit() work and revert back to ath_start().
My changed had some rather significant behavioural changes to throughput.
The two issues I noticed:
* With if_start and the ifnet mbuf queue, any temporary latency
would get eaten up by some mbufs being queued. With ath_transmit()
queuing things to ath_buf's, I'd only get 512 TX buffers before I
couldn't queue any further frames.
* There's also some non-zero latency involved with TX being pushed
into a taskqueue via direct dispatch. Any time the scheduler didn't
immediately schedule the ath TX task would cause extra latency.
Various 1ge/10ge drivers implement both direct dispatch (if the TX
lock can be acquired) and deferred task transmission (if the TX lock
can't be acquired), with frames being pushed into a drbd queue.
I'll have to do this at some point, but until I figure out how to
deal with 802.11 fragments, I'll have to wait a while longer.
So what I saw:
* lots of extra latency, specially under load - if the taskqueue
wasn't immediately scheduled, things went pear shaped;
* any extra latency would result in TX ath_buf's taking their sweet time
being replenished, so any further calls to ath_transmit() would drop
mbufs.
* .. yes, there's no explicit backpressure here - things are just dropped.
Eek.
With this, the general performance has gone up, but those subtle if_start()
related race conditions are back. For some reason, this is doubly-obvious
with the AR5416 NIC and I don't quite understand why yet.
There's an unrelated issue with AR5416 performance in STA mode (it's
fine in AP mode when bridging frames, weirdly..) that requires a little
further investigation. Specifically - it works fine on a Lenovo T40
(single core CPU) running a March 2012 9-STABLE kernel, but a Lenovo T60
(dual core) running an early November 2012 kernel behaves very poorly.
The same hardware with an AR9160 or AR9280 behaves perfectly.
2013-02-13 05:32:19 +00:00
|
|
|
|
|
|
|
ath_tx_kick(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2011-11-08 19:18:34 +00:00
|
|
|
#undef TXQACTIVE
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-03-29 17:39:18 +00:00
|
|
|
/*
|
|
|
|
* Deferred processing of TXQ rescheduling.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_txq_sched_tasklet(void *arg, int npending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* XXX is skipping ok? */
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
#if 0
|
|
|
|
if (sc->sc_inreset_cnt > 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: sc_inreset_cnt > 0; skipping\n", __func__);
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
sc->sc_txproc_cnt++;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
Delete the per-TXQ locks and replace them with a single TX lock.
I couldn't think of a way to maintain the hardware TXQ locks _and_ layer
on top of that per-TXQ software queuing and any other kind of fine-grained
locks (eg per-TID, or per-node locks.)
So for now, to facilitate some further code refactoring and development
as part of the final push to get software queue ps-poll and u-apsd handling
into this driver, just do away with them entirely.
I may eventually bring them back at some point, when it looks slightly more
architectually cleaner to do so. But as it stands at the present, it's
not really buying us much:
* in order to properly serialise things and not get bitten by scheduling
and locking interactions with things higher up in the stack, we need to
wrap the whole TX path in a long held lock. Otherwise we can end up
being pre-empted during frame handling, resulting in some out of order
frame handling between sequence number allocation and encryption handling
(ie, the seqno and the CCMP IV get out of sequence);
* .. so whilst that's the case, holding the lock for that long means that
we're acquiring and releasing the TXQ lock _inside_ that context;
* And we also acquire it per-frame during frame completion, but we currently
can't hold the lock for the duration of the TX completion as we need
to call net80211 layer things with the locks _unheld_ to avoid LOR.
* .. the other places were grab that lock are reset/flush, which don't happen
often.
My eventual aim is to change the TX path so all rejected frame transmissions
and all frame completions result in any ieee80211_free_node() calls to occur
outside of the TX lock; then I can cut back on the amount of locking that
goes on here.
There may be some LORs that occur when ieee80211_free_node() is called when
the TX queue path fails; I'll begin to address these in follow-up commits.
2012-12-02 06:24:08 +00:00
|
|
|
ATH_TX_LOCK(sc);
|
2012-03-29 17:39:18 +00:00
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
2012-03-29 21:54:19 +00:00
|
|
|
if (ATH_TXQ_SETUP(sc, i)) {
|
2012-03-29 17:39:18 +00:00
|
|
|
ath_txq_sched(sc, &sc->sc_txq[i]);
|
2012-03-29 21:54:19 +00:00
|
|
|
}
|
2012-03-29 17:39:18 +00:00
|
|
|
}
|
Delete the per-TXQ locks and replace them with a single TX lock.
I couldn't think of a way to maintain the hardware TXQ locks _and_ layer
on top of that per-TXQ software queuing and any other kind of fine-grained
locks (eg per-TID, or per-node locks.)
So for now, to facilitate some further code refactoring and development
as part of the final push to get software queue ps-poll and u-apsd handling
into this driver, just do away with them entirely.
I may eventually bring them back at some point, when it looks slightly more
architectually cleaner to do so. But as it stands at the present, it's
not really buying us much:
* in order to properly serialise things and not get bitten by scheduling
and locking interactions with things higher up in the stack, we need to
wrap the whole TX path in a long held lock. Otherwise we can end up
being pre-empted during frame handling, resulting in some out of order
frame handling between sequence number allocation and encryption handling
(ie, the seqno and the CCMP IV get out of sequence);
* .. so whilst that's the case, holding the lock for that long means that
we're acquiring and releasing the TXQ lock _inside_ that context;
* And we also acquire it per-frame during frame completion, but we currently
can't hold the lock for the duration of the TX completion as we need
to call net80211 layer things with the locks _unheld_ to avoid LOR.
* .. the other places were grab that lock are reset/flush, which don't happen
often.
My eventual aim is to change the TX path so all rejected frame transmissions
and all frame completions result in any ieee80211_free_node() calls to occur
outside of the TX lock; then I can cut back on the amount of locking that
goes on here.
There may be some LORs that occur when ieee80211_free_node() is called when
the TX queue path fails; I'll begin to address these in follow-up commits.
2012-12-02 06:24:08 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-03-29 17:39:18 +00:00
|
|
|
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_txproc_cnt--;
|
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
2012-06-13 05:39:16 +00:00
|
|
|
void
|
|
|
|
ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf)
|
|
|
|
{
|
|
|
|
|
|
|
|
ATH_TXBUF_LOCK_ASSERT(sc);
|
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
if (bf->bf_flags & ATH_BUF_MGMT)
|
|
|
|
TAILQ_INSERT_TAIL(&sc->sc_txbuf_mgmt, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
else {
|
2012-06-13 06:57:55 +00:00
|
|
|
TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
sc->sc_txbuf_cnt++;
|
|
|
|
if (sc->sc_txbuf_cnt > ath_txbuf) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: sc_txbuf_cnt > %d?\n",
|
|
|
|
__func__,
|
|
|
|
ath_txbuf);
|
|
|
|
sc->sc_txbuf_cnt = ath_txbuf;
|
|
|
|
}
|
|
|
|
}
|
2012-06-13 05:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf)
|
|
|
|
{
|
|
|
|
|
|
|
|
ATH_TXBUF_LOCK_ASSERT(sc);
|
|
|
|
|
2012-06-13 06:57:55 +00:00
|
|
|
if (bf->bf_flags & ATH_BUF_MGMT)
|
|
|
|
TAILQ_INSERT_HEAD(&sc->sc_txbuf_mgmt, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
else {
|
2012-06-13 06:57:55 +00:00
|
|
|
TAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
|
2012-06-14 00:51:53 +00:00
|
|
|
sc->sc_txbuf_cnt++;
|
|
|
|
if (sc->sc_txbuf_cnt > ATH_TXBUF) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: sc_txbuf_cnt > %d?\n",
|
|
|
|
__func__,
|
|
|
|
ATH_TXBUF);
|
|
|
|
sc->sc_txbuf_cnt = ATH_TXBUF;
|
|
|
|
}
|
|
|
|
}
|
2012-06-13 05:39:16 +00:00
|
|
|
}
|
|
|
|
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
/*
|
|
|
|
* Free the holding buffer if it exists
|
|
|
|
*/
|
2013-03-26 19:46:51 +00:00
|
|
|
void
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
ath_txq_freeholdingbuf(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
|
{
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXBUF_UNLOCK_ASSERT(sc);
|
|
|
|
ATH_TXQ_LOCK_ASSERT(txq);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
|
|
|
|
if (txq->axq_holdingbf == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
txq->axq_holdingbf->bf_flags &= ~ATH_BUF_BUSY;
|
2013-05-08 21:23:51 +00:00
|
|
|
|
|
|
|
ATH_TXBUF_LOCK(sc);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
ath_returnbuf_tail(sc, txq->axq_holdingbf);
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXBUF_UNLOCK(sc);
|
|
|
|
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
txq->axq_holdingbf = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add this buffer to the holding queue, freeing the previous
|
|
|
|
* one if it exists.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_txq_addholdingbuf(struct ath_softc *sc, struct ath_buf *bf)
|
|
|
|
{
|
|
|
|
struct ath_txq *txq;
|
|
|
|
|
2013-05-08 21:23:51 +00:00
|
|
|
txq = &sc->sc_txq[bf->bf_state.bfs_tx_queue];
|
|
|
|
|
|
|
|
ATH_TXBUF_UNLOCK_ASSERT(sc);
|
|
|
|
ATH_TXQ_LOCK_ASSERT(txq);
|
2013-03-15 02:52:37 +00:00
|
|
|
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
/* XXX assert ATH_BUF_BUSY is set */
|
|
|
|
|
|
|
|
/* XXX assert the tx queue is under the max number */
|
|
|
|
if (bf->bf_state.bfs_tx_queue > HAL_NUM_TX_QUEUES) {
|
|
|
|
device_printf(sc->sc_dev, "%s: bf=%p: invalid tx queue (%d)\n",
|
|
|
|
__func__,
|
|
|
|
bf,
|
|
|
|
bf->bf_state.bfs_tx_queue);
|
|
|
|
bf->bf_flags &= ~ATH_BUF_BUSY;
|
|
|
|
ath_returnbuf_tail(sc, bf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ath_txq_freeholdingbuf(sc, txq);
|
|
|
|
txq->axq_holdingbf = bf;
|
|
|
|
}
|
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
/*
|
|
|
|
* Return a buffer to the pool and update the 'busy' flag on the
|
|
|
|
* previous 'tail' entry.
|
|
|
|
*
|
|
|
|
* This _must_ only be called when the buffer is involved in a completed
|
|
|
|
* TX. The logic is that if it was part of an active TX, the previous
|
|
|
|
* buffer on the list is now not involved in a halted TX DMA queue, waiting
|
|
|
|
* for restart (eg for TDMA.)
|
|
|
|
*
|
|
|
|
* The caller must free the mbuf and recycle the node reference.
|
2013-05-08 21:23:51 +00:00
|
|
|
*
|
|
|
|
* XXX This method of handling busy / holding buffers is insanely stupid.
|
|
|
|
* It requires bf_state.bfs_tx_queue to be correctly assigned. It would
|
|
|
|
* be much nicer if buffers in the processq() methods would instead be
|
|
|
|
* always completed there (pushed onto a txq or ath_bufhead) so we knew
|
|
|
|
* exactly what hardware queue they came from in the first place.
|
2011-11-08 21:49:33 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_freebuf(struct ath_softc *sc, struct ath_buf *bf)
|
|
|
|
{
|
2013-05-08 21:23:51 +00:00
|
|
|
struct ath_txq *txq;
|
|
|
|
|
|
|
|
txq = &sc->sc_txq[bf->bf_state.bfs_tx_queue];
|
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
KASSERT((bf->bf_node == NULL), ("%s: bf->bf_node != NULL\n", __func__));
|
|
|
|
KASSERT((bf->bf_m == NULL), ("%s: bf->bf_m != NULL\n", __func__));
|
|
|
|
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
/*
|
2013-05-08 21:23:51 +00:00
|
|
|
* If this buffer is busy, push it onto the holding queue.
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
*/
|
|
|
|
if (bf->bf_flags & ATH_BUF_BUSY) {
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXQ_LOCK(txq);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
ath_txq_addholdingbuf(sc, bf);
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not a busy buffer, so free normally
|
|
|
|
*/
|
2011-11-08 21:49:33 +00:00
|
|
|
ATH_TXBUF_LOCK(sc);
|
2012-06-13 05:39:16 +00:00
|
|
|
ath_returnbuf_tail(sc, bf);
|
2011-11-08 21:49:33 +00:00
|
|
|
ATH_TXBUF_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is currently used by ath_tx_draintxq() and
|
|
|
|
* ath_tx_tid_free_pkts().
|
|
|
|
*
|
|
|
|
* It recycles a single ath_buf.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_tx_freebuf(struct ath_softc *sc, struct ath_buf *bf, int status)
|
|
|
|
{
|
|
|
|
struct ieee80211_node *ni = bf->bf_node;
|
|
|
|
struct mbuf *m0 = bf->bf_m;
|
|
|
|
|
2013-04-01 20:57:13 +00:00
|
|
|
/*
|
|
|
|
* Make sure that we only sync/unload if there's an mbuf.
|
|
|
|
* If not (eg we cloned a buffer), the unload will have already
|
|
|
|
* occured.
|
|
|
|
*/
|
|
|
|
if (bf->bf_m != NULL) {
|
|
|
|
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
|
|
|
|
BUS_DMASYNC_POSTWRITE);
|
|
|
|
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
|
|
|
|
}
|
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
bf->bf_node = NULL;
|
|
|
|
bf->bf_m = NULL;
|
|
|
|
|
|
|
|
/* Free the buffer, it's not needed any longer */
|
|
|
|
ath_freebuf(sc, bf);
|
|
|
|
|
2013-08-27 14:39:37 +00:00
|
|
|
/* Pass the buffer back to net80211 - completing it */
|
|
|
|
ieee80211_tx_complete(ni, m0, status);
|
2011-11-08 21:49:33 +00:00
|
|
|
}
|
|
|
|
|
2013-03-26 19:46:51 +00:00
|
|
|
static struct ath_buf *
|
|
|
|
ath_tx_draintxq_get_one(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
|
{
|
|
|
|
struct ath_buf *bf;
|
|
|
|
|
|
|
|
ATH_TXQ_LOCK_ASSERT(txq);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Drain the FIFO queue first, then if it's
|
|
|
|
* empty, move to the normal frame queue.
|
|
|
|
*/
|
|
|
|
bf = TAILQ_FIRST(&txq->fifo.axq_q);
|
|
|
|
if (bf != NULL) {
|
|
|
|
/*
|
|
|
|
* Is it the last buffer in this set?
|
|
|
|
* Decrement the FIFO counter.
|
|
|
|
*/
|
|
|
|
if (bf->bf_flags & ATH_BUF_FIFOEND) {
|
|
|
|
if (txq->axq_fifo_depth == 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: Q%d: fifo_depth=0, fifo.axq_depth=%d?\n",
|
|
|
|
__func__,
|
|
|
|
txq->axq_qnum,
|
|
|
|
txq->fifo.axq_depth);
|
|
|
|
} else
|
|
|
|
txq->axq_fifo_depth--;
|
|
|
|
}
|
|
|
|
ATH_TXQ_REMOVE(&txq->fifo, bf, bf_list);
|
|
|
|
return (bf);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Debugging!
|
|
|
|
*/
|
|
|
|
if (txq->axq_fifo_depth != 0 || txq->fifo.axq_depth != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: Q%d: fifo_depth=%d, fifo.axq_depth=%d\n",
|
|
|
|
__func__,
|
|
|
|
txq->axq_qnum,
|
|
|
|
txq->axq_fifo_depth,
|
|
|
|
txq->fifo.axq_depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now drain the pending queue.
|
|
|
|
*/
|
|
|
|
bf = TAILQ_FIRST(&txq->axq_q);
|
|
|
|
if (bf == NULL) {
|
|
|
|
txq->axq_link = NULL;
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
ATH_TXQ_REMOVE(txq, bf, bf_list);
|
|
|
|
return (bf);
|
|
|
|
}
|
|
|
|
|
2011-11-08 21:49:33 +00:00
|
|
|
void
|
2012-08-12 00:46:15 +00:00
|
|
|
ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2006-04-03 18:14:02 +00:00
|
|
|
#ifdef ATH_DEBUG
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2006-02-15 18:35:09 +00:00
|
|
|
#endif
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_buf *bf;
|
2006-02-15 18:31:04 +00:00
|
|
|
u_int ix;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* NB: this assumes output has been stopped and
|
2008-10-27 17:53:34 +00:00
|
|
|
* we do not need to block ath_tx_proc
|
2004-12-08 17:34:36 +00:00
|
|
|
*/
|
2006-02-15 18:31:04 +00:00
|
|
|
for (ix = 0;; ix++) {
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_LOCK(txq);
|
2013-03-26 19:46:51 +00:00
|
|
|
bf = ath_tx_draintxq_get_one(sc, txq);
|
2003-06-23 17:01:19 +00:00
|
|
|
if (bf == NULL) {
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-11-08 21:25:36 +00:00
|
|
|
if (bf->bf_state.bfs_aggr)
|
|
|
|
txq->axq_aggr_depth--;
|
2006-04-03 18:14:02 +00:00
|
|
|
#ifdef ATH_DEBUG
|
2006-04-16 18:24:27 +00:00
|
|
|
if (sc->sc_debug & ATH_DEBUG_RESET) {
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
2012-08-12 00:46:15 +00:00
|
|
|
int status = 0;
|
2008-04-20 20:35:46 +00:00
|
|
|
|
2012-08-12 00:46:15 +00:00
|
|
|
/*
|
|
|
|
* EDMA operation has a TX completion FIFO
|
|
|
|
* separate from the TX descriptor, so this
|
|
|
|
* method of checking the "completion" status
|
|
|
|
* is wrong.
|
|
|
|
*/
|
|
|
|
if (! sc->sc_isedma) {
|
|
|
|
status = (ath_hal_txprocdesc(ah,
|
|
|
|
bf->bf_lastds,
|
2006-12-13 19:34:35 +00:00
|
|
|
&bf->bf_status.ds_txstat) == HAL_OK);
|
2012-08-12 00:46:15 +00:00
|
|
|
}
|
|
|
|
ath_printtxbuf(sc, bf, txq->axq_qnum, ix, status);
|
2009-04-13 20:58:47 +00:00
|
|
|
ieee80211_dump_pkt(ic, mtod(bf->bf_m, const uint8_t *),
|
|
|
|
bf->bf_m->m_len, 0, -1);
|
2006-04-16 18:24:27 +00:00
|
|
|
}
|
2006-04-03 18:14:02 +00:00
|
|
|
#endif /* ATH_DEBUG */
|
2011-11-08 21:49:33 +00:00
|
|
|
/*
|
|
|
|
* Since we're now doing magic in the completion
|
|
|
|
* functions, we -must- call it for aggregation
|
|
|
|
* destinations or BAW tracking will get upset.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Clear ATH_BUF_BUSY; the completion handler
|
|
|
|
* will free the buffer.
|
|
|
|
*/
|
Overhaul the TXQ locking (again!) as part of some beacon/cabq timing
related issues.
Moving the TX locking under one lock made things easier to progress on
but it had one important side-effect - it increased the latency when
handling CABQ setup when sending beacons.
This commit introduces a bunch of new changes and a few unrelated changs
that are just easier to lump in here.
The aim is to have the CABQ locking separate from other locking.
The CABQ transmit path in the beacon process thus doesn't have to grab
the general TX lock, reducing lock contention/latency and making it
more likely that we'll make the beacon TX timing.
The second half of this commit is the CABQ related setup changes needed
for sane looking EDMA CABQ support. Right now the EDMA TX code naively
assumes that only one frame (MPDU or A-MPDU) is being pushed into each
FIFO slot. For the CABQ this isn't true - a whole list of frames is
being pushed in - and thus CABQ handling breaks very quickly.
The aim here is to setup the CABQ list and then push _that list_ to
the hardware for transmission. I can then extend the EDMA TX code
to stamp that list as being "one" FIFO entry (likely by tagging the
last buffer in that list as "FIFO END") so the EDMA TX completion code
correctly tracks things.
Major:
* Migrate the per-TXQ add/removal locking back to per-TXQ, rather than
a single lock.
* Leave the software queue side of things under the ATH_TX_LOCK lock,
(continuing) to serialise things as they are.
* Add a new function which is called whenever there's a beacon miss,
to print out some debugging. This is primarily designed to help
me figure out if the beacon miss events are due to a noisy environment,
issues with the PHY/MAC, or other.
* Move the CABQ setup/enable to occur _after_ all the VAPs have been
looked at. This means that for multiple VAPS in bursted mode, the
CABQ gets primed once all VAPs are checked, rather than being primed
on the first VAP and then having frames appended after this.
Minor:
* Add a (disabled) twiddle to let me enable/disable cabq traffic.
It's primarily there to let me easily debug what's going on with beacon
and CABQ setup/traffic; there's some DMA engine hangs which I'm finally
trying to trace down.
* Clear bf_next when flushing frames; it should quieten some warnings
that show up when a node goes away.
Tested:
* AR9280, STA/hostap, up to 4 vaps (staggered)
* AR5416, STA/hostap, up to 4 vaps (staggered)
TODO:
* (Lots) more AR9380 and later testing, as I may have missed something here.
* Leverage this to fix CABQ hanling for AR9380 and later chips.
* Force bursted beaconing on the chips that default to staggered beacons and
ensure the CABQ stuff is all sane (eg, the MORE bits that aren't being
correctly set when chaining descriptors.)
2013-03-24 00:03:12 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
2009-01-08 17:12:47 +00:00
|
|
|
bf->bf_flags &= ~ATH_BUF_BUSY;
|
2011-11-08 21:49:33 +00:00
|
|
|
if (bf->bf_comp)
|
|
|
|
bf->bf_comp(sc, bf, 1);
|
|
|
|
else
|
|
|
|
ath_tx_default_comp(sc, bf, 1);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2011-11-08 21:49:33 +00:00
|
|
|
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
/*
|
|
|
|
* Free the holding buffer if it exists
|
|
|
|
*/
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXQ_LOCK(txq);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
ath_txq_freeholdingbuf(sc, txq);
|
2013-05-08 21:23:51 +00:00
|
|
|
ATH_TXQ_UNLOCK(txq);
|
Implement "holding buffers" per TX queue rather than globally.
When working on TDMA, Sam Leffler found that the MAC DMA hardware
would re-read the last TX descriptor when getting ready to transmit
the next one. Thus the whole ATH_BUF_BUSY came into existance -
the descriptor must be left alone (very specifically the link pointer
must be maintained) until the hardware has moved onto the next frame.
He saw this in TDMA because the MAC would be frequently stopping during
active transmit (ie, when it wasn't its turn to transmit.)
Fast-forward to today. It turns out that this is a problem not with
a single MAC DMA instance, but with each QCU (from 0->9). They each
maintain separate descriptor pointers and will re-read the last
descriptor when starting to transmit the next.
So when your AP is busy transmitting from multiple TX queues, you'll
(more) frequently see one QCU stopped, waiting for a higher-priority QCU
to finsh transmitting, before it'll go ahead and continue. If you mess
up the descriptor (ie by freeing it) then you're short of luck.
Thanks to rpaulo for sticking with me whilst I diagnosed this issue
that he was quite reliably triggering in his environment.
This is a reimplementation; it doesn't have anything in common with
the ath9k or the Qualcomm Atheros reference driver.
Now - it in theory doesn't apply on the EDMA chips, as long as you
push one complete frame into the FIFO at a time. But the MAC can DMA
from a list of frames pushed into the hardware queue (ie, you concat
'n' frames together with link pointers, and then push the head pointer
into the TXQ FIFO.) Since that's likely how I'm going to implement
CABQ handling in hostap mode, it's likely that I will end up teaching
the EDMA TX completion code about busy buffers, just to be "sure"
this doesn't creep up.
Tested - iperf ap->sta and sta->ap (with both sides running this code):
* AR5416 STA
* AR9160/AR9220 hostap
To validate that it doesn't break the EDMA (FIFO) chips:
* AR9380, AR9485, AR9462 STA
Using iperf with the -S <tos byte decimal value> to set the TCP client
side DSCP bits, mapping to different TIDs and thus different TX queues.
TODO:
* Make this work on the EDMA chips, if we end up pushing lists of frames
to the hardware (eg how we eventually will handle cabq in hostap/ibss
mode.)
2013-03-14 06:20:02 +00:00
|
|
|
|
Introduce TX aggregation and software TX queue management
for Atheros AR5416 and later wireless devices.
This is a very large commit - the complete history can be
found in the user/adrian/if_ath_tx branch.
Legacy (ie, pre-AR5416) devices also use the per-software
TXQ support and (in theory) can support non-aggregation
ADDBA sessions. However, the net80211 stack doesn't currently
support this.
In summary:
TX path:
* queued frames normally go onto a per-TID, per-node queue
* some special frames (eg ADDBA control frames) are thrown
directly onto the relevant hardware queue so they can
go out before any software queued frames are queued.
* Add methods to create, suspend, resume and tear down an
aggregation session.
* Add in software retransmission of both normal and aggregate
frames.
* Add in completion handling of aggregate frames, including
parsing the block ack bitmap provided by the hardware.
* Write an aggregation function which can assemble frames into
an aggregate based on the selected rate control and channel
configuration.
* The per-TID queues are locked based on their target hardware
TX queue. This matches what ath9k/atheros does, and thus
simplified porting over some of the aggregation logic.
* When doing TX aggregation, stick the sequence number allocation
in the TX path rather than net80211 TX path, and protect it
by the TXQ lock.
Rate control:
* Delay rate control selection until the frame is about to
be queued to the hardware, so retried frames can have their
rate control choices changed. Frames with a static rate
control selection have that applied before each TX, just
to simplify the TX path (ie, not have "static" and "dynamic"
rate control special cased.)
* Teach ath_rate_sample about aggregates - both completion and
errors.
* Add an EWMA for tracking what the current "good" MCS rate is
based on failure rates.
Misc:
* Introduce a bunch of dirty hacks and workarounds so TID mapping
and net80211 frame inspection can be kept out of the net80211
layer. Because of the way this code works (and it's from Atheros
and Linux ath9k), there is a consistent, 1:1 mapping between
TID and AC. So we need to ensure that frames going to a specific
TID will _always_ end up on the right AC, and vice versa, or the
completion/locking will simply get very confused. I plan on
addressing this mess in the future.
Known issues:
* There is no BAR frame transmission just yet. A whole lot of
tidying up needs to occur before BAR frame TX can occur in the
"correct" place - ie, once the TID TX queue has been drained.
* Interface reset/purge/etc results in frames in the TX and RX
queues being removed. This creates holes in the sequence numbers
being assigned and the TX/RX AMPDU code (on either side) just
hangs.
* There's no filtered frame support at the present moment, so
stations going into power saving mode will simply have a number
of frames dropped - likely resulting in a traffic "hang".
* Raw frame TX is going to just not function with 11n aggregation.
Likely this needs to be modified to always override the sequence
number if the frame is going into an aggregation session.
However, general raw frame injection currently doesn't work in
general in net80211, so let's just ignore this for now until
this is sorted out.
* HT protection is just not implemented and won't be until the above
is sorted out. In addition, the AR5416 has issues RTS protecting
large aggregates (anything >8k), so the work around needs to be
ported and tested. Thus, this will be put on hold until the above
work is complete.
* The rate control module 'sample' is the only currently supported
module; onoe/amrr haven't been tested and have likely bit rotted
a little. I'll follow up with some commits to make them work again
for non-11n rates, but they won't be updated to handle 11n and
aggregation. If someone wishes to do so then they're welcome to
send along patches.
* .. and "sample" doesn't really do a good job of 11n TX. Specifically,
the metrics used (packet TX time and failure/success rates) isn't as
useful for 11n. It's likely that it should be extended to take into
account the aggregate throughput possible and then choose a rate
which maximises that. Ie, it may be acceptable for a higher MCS rate
with a higher failure to be used if it gives a more acceptable
throughput/latency then a lower MCS rate @ a lower error rate.
Again, patches will be gratefully accepted.
Because of this, ATH_ENABLE_11N is still not enabled by default.
Sponsored by: Hobnob, Inc.
Obtained from: Linux, Atheros
2011-11-08 22:43:13 +00:00
|
|
|
/*
|
|
|
|
* Drain software queued frames which are on
|
|
|
|
* active TIDs.
|
|
|
|
*/
|
|
|
|
ath_tx_txq_drain(sc, txq);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
ATH_TXQ_LOCK_ASSERT(txq);
|
|
|
|
|
2013-03-09 06:11:58 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET,
|
2013-05-16 17:45:01 +00:00
|
|
|
"%s: tx queue [%u] %p, active=%d, hwpending=%d, flags 0x%08x, "
|
|
|
|
"link %p, holdingbf=%p\n",
|
2013-03-09 06:11:58 +00:00
|
|
|
__func__,
|
|
|
|
txq->axq_qnum,
|
2004-12-15 02:25:21 +00:00
|
|
|
(caddr_t)(uintptr_t) ath_hal_gettxbuf(ah, txq->axq_qnum),
|
2013-04-29 07:28:29 +00:00
|
|
|
(int) (!! ath_hal_txqenabled(ah, txq->axq_qnum)),
|
|
|
|
(int) ath_hal_numtxpending(ah, txq->axq_qnum),
|
2013-03-09 06:11:58 +00:00
|
|
|
txq->axq_flags,
|
2013-05-16 17:45:01 +00:00
|
|
|
txq->axq_link,
|
|
|
|
txq->axq_holdingbf);
|
|
|
|
|
2006-04-16 18:24:27 +00:00
|
|
|
(void) ath_hal_stoptxdma(ah, txq->axq_qnum);
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
/* We've stopped TX DMA, so mark this as stopped. */
|
|
|
|
txq->axq_flags &= ~ATH_TXQ_PUTRUNNING;
|
2013-05-16 17:45:01 +00:00
|
|
|
|
|
|
|
#ifdef ATH_DEBUG
|
|
|
|
if ((sc->sc_debug & ATH_DEBUG_RESET)
|
|
|
|
&& (txq->axq_holdingbf != NULL)) {
|
|
|
|
ath_printtxbuf(sc, txq->axq_holdingbf, txq->axq_qnum, 0, 0);
|
|
|
|
}
|
|
|
|
#endif
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
2012-08-14 22:32:20 +00:00
|
|
|
int
|
2011-11-08 21:06:36 +00:00
|
|
|
ath_stoptxdma(struct ath_softc *sc)
|
2004-12-08 17:34:36 +00:00
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* XXX return value */
|
2011-11-08 21:06:36 +00:00
|
|
|
if (sc->sc_invalid)
|
|
|
|
return 0;
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
if (!sc->sc_invalid) {
|
|
|
|
/* don't touch the hardware if marked invalid */
|
2006-04-16 18:24:27 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: tx queue [%u] %p, link %p\n",
|
|
|
|
__func__, sc->sc_bhalq,
|
|
|
|
(caddr_t)(uintptr_t) ath_hal_gettxbuf(ah, sc->sc_bhalq),
|
|
|
|
NULL);
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
|
|
|
|
/* stop the beacon queue */
|
2004-12-08 17:34:36 +00:00
|
|
|
(void) ath_hal_stoptxdma(ah, sc->sc_bhalq);
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
|
|
|
|
/* Stop the data queues */
|
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
|
|
|
if (ATH_TXQ_SETUP(sc, i)) {
|
|
|
|
ATH_TXQ_LOCK(&sc->sc_txq[i]);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_tx_stopdma(sc, &sc->sc_txq[i]);
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
ATH_TXQ_UNLOCK(&sc->sc_txq[i]);
|
|
|
|
}
|
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2011-11-08 21:06:36 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-04-26 22:22:38 +00:00
|
|
|
#ifdef ATH_DEBUG
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
void
|
2013-04-26 21:51:17 +00:00
|
|
|
ath_tx_dump(struct ath_softc *sc, struct ath_txq *txq)
|
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
struct ath_buf *bf;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if (! (sc->sc_debug & ATH_DEBUG_RESET))
|
|
|
|
return;
|
|
|
|
|
|
|
|
device_printf(sc->sc_dev, "%s: Q%d: begin\n",
|
|
|
|
__func__, txq->axq_qnum);
|
|
|
|
TAILQ_FOREACH(bf, &txq->axq_q, bf_list) {
|
|
|
|
ath_printtxbuf(sc, bf, txq->axq_qnum, i,
|
|
|
|
ath_hal_txprocdesc(ah, bf->bf_lastds,
|
|
|
|
&bf->bf_status.ds_txstat) == HAL_OK);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
device_printf(sc->sc_dev, "%s: Q%d: end\n",
|
|
|
|
__func__, txq->axq_qnum);
|
|
|
|
}
|
2013-04-26 22:22:38 +00:00
|
|
|
#endif /* ATH_DEBUG */
|
2013-04-26 21:51:17 +00:00
|
|
|
|
2011-11-08 21:06:36 +00:00
|
|
|
/*
|
|
|
|
* Drain the transmit queues and reclaim resources.
|
|
|
|
*/
|
2012-08-12 00:37:29 +00:00
|
|
|
void
|
|
|
|
ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
|
2011-11-08 21:06:36 +00:00
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
int i;
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
struct ath_buf *bf_last;
|
2011-11-08 21:06:36 +00:00
|
|
|
|
|
|
|
(void) ath_stoptxdma(sc);
|
|
|
|
|
2013-04-26 21:51:17 +00:00
|
|
|
/*
|
|
|
|
* Dump the queue contents
|
|
|
|
*/
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
|
|
|
|
/*
|
|
|
|
* XXX TODO: should we just handle the completed TX frames
|
|
|
|
* here, whether or not the reset is a full one or not?
|
|
|
|
*/
|
|
|
|
if (ATH_TXQ_SETUP(sc, i)) {
|
2013-04-26 22:22:38 +00:00
|
|
|
#ifdef ATH_DEBUG
|
2013-04-26 21:51:17 +00:00
|
|
|
if (sc->sc_debug & ATH_DEBUG_RESET)
|
|
|
|
ath_tx_dump(sc, &sc->sc_txq[i]);
|
2013-04-26 22:22:38 +00:00
|
|
|
#endif /* ATH_DEBUG */
|
2013-05-10 10:06:45 +00:00
|
|
|
if (reset_type == ATH_RESET_NOLOSS) {
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ath_tx_processq(sc, &sc->sc_txq[i], 0);
|
2013-05-10 10:06:45 +00:00
|
|
|
ATH_TXQ_LOCK(&sc->sc_txq[i]);
|
|
|
|
/*
|
|
|
|
* Free the holding buffer; DMA is now
|
|
|
|
* stopped.
|
|
|
|
*/
|
|
|
|
ath_txq_freeholdingbuf(sc, &sc->sc_txq[i]);
|
|
|
|
/*
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
* Setup the link pointer to be the
|
|
|
|
* _last_ buffer/descriptor in the list.
|
|
|
|
* If there's nothing in the list, set it
|
|
|
|
* to NULL.
|
2013-05-10 10:06:45 +00:00
|
|
|
*/
|
Be (very) careful about how to add more TX DMA work.
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
2013-05-18 18:27:53 +00:00
|
|
|
bf_last = ATH_TXQ_LAST(&sc->sc_txq[i],
|
|
|
|
axq_q_s);
|
|
|
|
if (bf_last != NULL) {
|
|
|
|
ath_hal_gettxdesclinkptr(ah,
|
|
|
|
bf_last->bf_lastds,
|
|
|
|
&sc->sc_txq[i].axq_link);
|
|
|
|
} else {
|
|
|
|
sc->sc_txq[i].axq_link = NULL;
|
|
|
|
}
|
2013-05-10 10:06:45 +00:00
|
|
|
ATH_TXQ_UNLOCK(&sc->sc_txq[i]);
|
|
|
|
} else
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ath_tx_draintxq(sc, &sc->sc_txq[i]);
|
|
|
|
}
|
|
|
|
}
|
2006-04-16 18:24:27 +00:00
|
|
|
#ifdef ATH_DEBUG
|
|
|
|
if (sc->sc_debug & ATH_DEBUG_RESET) {
|
2011-11-08 17:08:12 +00:00
|
|
|
struct ath_buf *bf = TAILQ_FIRST(&sc->sc_bbuf);
|
2006-04-16 18:24:27 +00:00
|
|
|
if (bf != NULL && bf->bf_m != NULL) {
|
2008-11-24 01:34:56 +00:00
|
|
|
ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
|
2011-11-08 21:25:36 +00:00
|
|
|
ath_hal_txprocdesc(ah, bf->bf_lastds,
|
2006-12-13 19:34:35 +00:00
|
|
|
&bf->bf_status.ds_txstat) == HAL_OK);
|
2009-04-13 20:58:47 +00:00
|
|
|
ieee80211_dump_pkt(ifp->if_l2com,
|
|
|
|
mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len,
|
|
|
|
0, -1);
|
2006-04-16 18:24:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* ATH_DEBUG */
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
2005-08-09 10:20:02 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
2009-03-09 23:10:19 +00:00
|
|
|
sc->sc_wd_timer = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2010-02-19 18:23:45 +00:00
|
|
|
/*
|
2004-12-08 17:34:36 +00:00
|
|
|
* Update internal state after a channel change.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
|
|
|
|
{
|
|
|
|
enum ieee80211_phymode mode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change channels and update the h/w rate map
|
|
|
|
* if we're switching; e.g. 11a to 11b/g.
|
|
|
|
*/
|
2009-02-19 05:22:40 +00:00
|
|
|
mode = ieee80211_chan2mode(chan);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (mode != sc->sc_curmode)
|
|
|
|
ath_setcurmode(sc, mode);
|
2009-01-28 18:00:22 +00:00
|
|
|
sc->sc_curchan = chan;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Set/change channels. If the channel is really being changed,
|
2010-02-19 18:23:45 +00:00
|
|
|
* it's done by resetting the chip. To accomplish this we must
|
2003-06-23 17:01:19 +00:00
|
|
|
* first cleanup any pending DMA, then restart stuff after a la
|
|
|
|
* ath_init.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
|
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2003-06-23 17:01:19 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
/* Treat this as an interface reset */
|
2012-02-25 19:12:54 +00:00
|
|
|
ATH_PCU_UNLOCK_ASSERT(sc);
|
|
|
|
ATH_UNLOCK_ASSERT(sc);
|
|
|
|
|
|
|
|
/* (Try to) stop TX/RX from occuring */
|
|
|
|
taskqueue_block(sc->sc_tq);
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_LOCK(sc);
|
2013-06-03 19:39:37 +00:00
|
|
|
|
|
|
|
/* Stop new RX/TX/interrupt completion */
|
2011-12-23 03:59:49 +00:00
|
|
|
if (ath_reset_grablock(sc, 1) == 0) {
|
|
|
|
device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n",
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
__func__);
|
2011-12-23 03:59:49 +00:00
|
|
|
}
|
2013-06-03 19:39:37 +00:00
|
|
|
|
|
|
|
ath_hal_intrset(ah, 0);
|
|
|
|
|
|
|
|
/* Stop pending RX/TX completion */
|
|
|
|
ath_txrx_stop_locked(sc);
|
|
|
|
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2009-01-28 18:00:22 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_RESET, "%s: %u (%u MHz, flags 0x%x)\n",
|
|
|
|
__func__, ieee80211_chan2ieee(ic, chan),
|
|
|
|
chan->ic_freq, chan->ic_flags);
|
|
|
|
if (chan != sc->sc_curchan) {
|
2003-06-23 17:01:19 +00:00
|
|
|
HAL_STATUS status;
|
|
|
|
/*
|
|
|
|
* To switch channels clear any pending DMA operations;
|
|
|
|
* wait long enough for the RX fifo to drain, reset the
|
|
|
|
* hardware at the new frequency, and then re-enable
|
|
|
|
* the relevant bits of the h/w.
|
|
|
|
*/
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
#if 0
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_intrset(ah, 0); /* disable interrupts */
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
#endif
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
ath_stoprecv(sc, 1); /* turn off frame recv */
|
|
|
|
/*
|
|
|
|
* First, handle completed TX/RX frames.
|
|
|
|
*/
|
2012-07-03 06:59:12 +00:00
|
|
|
ath_rx_flush(sc);
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
ath_draintxq(sc, ATH_RESET_NOLOSS);
|
|
|
|
/*
|
|
|
|
* Next, flush the non-scheduled frames.
|
|
|
|
*/
|
2011-11-08 19:02:59 +00:00
|
|
|
ath_draintxq(sc, ATH_RESET_FULL); /* clear pending tx frames */
|
Begin breaking apart the receive setup/stop path in preparation for more
"correct" handling of frames in the RX pending queue during interface
transitions.
* ath_stoprecv() doesn't blank out the descriptor list - that's what
ath_startrecv() does. So, change a comment to reflect that.
* ath_stoprecv() does include a large (3ms) delay to let pending DMA
complete. However, I'm under the impression that the stopdma hal
method does check for a bit in the PCU to indicate DMA has stopped.
So, to help with fast abort and restart, modify ath_stoprecv() to take
a flag which indicates whether this is needed.
* Modify the uses of ath_stoprecv() to pass in a flag to support the
existing behaviour (ie, do the delay.)
* Remove some duplicate PCU teardown code (which wasn't shutting down DMA,
so it wasn't entirely correct..) and replace it with a call to
ath_stoprecv(sc, 0) - which disables the DELAY call.
The upshoot of this is now channel change doesn't simply drop completed
frames on the floor, but instead it cleanly handles those frames.
It still discards pending TX frames in the software and hardware queues
as there's no (current) logic which forcibly recalculates the rate control
information (or whether they're appropriate to be on the TX queue after
a channel change), that'll come later.
This still doesn't stop all the sources of queue stalls but it does
tidy up some of the code duplication.
To be complete, queue stalls now occur during normal behaviour -
they only occur after some kind of broken behaviour causes an interface
or node flush, upsetting the TX/RX BAW. Subsequent commits will
incrementally fix these and other related issues.
Sponsored by: Hobnob, Inc.
2011-11-19 21:05:31 +00:00
|
|
|
|
2013-02-25 22:45:02 +00:00
|
|
|
ath_update_chainmasks(sc, chan);
|
|
|
|
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
|
|
|
sc->sc_cur_rxchainmask);
|
2009-01-28 18:00:22 +00:00
|
|
|
if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
|
2008-04-20 20:35:46 +00:00
|
|
|
if_printf(ifp, "%s: unable to reset "
|
2010-01-12 17:59:58 +00:00
|
|
|
"channel %u (%u MHz, flags 0x%x), hal status %u\n",
|
2009-01-28 18:00:22 +00:00
|
|
|
__func__, ieee80211_chan2ieee(ic, chan),
|
|
|
|
chan->ic_freq, chan->ic_flags, status);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ret = EIO;
|
|
|
|
goto finish;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2005-07-24 05:11:39 +00:00
|
|
|
sc->sc_diversity = ath_hal_getdiversity(ah);
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
/* Let DFS at it in case it's a DFS channel */
|
2012-02-23 08:32:54 +00:00
|
|
|
ath_dfs_radar_enable(sc, chan);
|
2011-06-01 20:09:49 +00:00
|
|
|
|
2013-01-02 03:59:02 +00:00
|
|
|
/* Let spectral at in case spectral is enabled */
|
|
|
|
ath_spectral_enable(sc, chan);
|
|
|
|
|
Bring over the initial static bluetooth coexistence configuration
for the WB195 combo NIC - an AR9285 w/ an AR3011 USB bluetooth NIC.
The AR3011 is wired up using a 3-wire coexistence scheme to the AR9285.
The code in if_ath_btcoex.c sets up the initial hardware mapping
and coexistence configuration. There's nothing special about it -
it's static; it doesn't try to configure bluetooth / MAC traffic priorities
or try to figure out what's actually going on. It's enough to stop basic
bluetooth traffic from causing traffic stalls and diassociation from
the wireless network.
To use this code, you must have the above NIC. No, it won't work
for the AR9287+AR3012, nor the AR9485, AR9462 or AR955x combo cards.
Then you set a kernel hint before boot or before kldload, where 'X'
is the unit number of your AR9285 NIC:
# kenv hint.ath.X.btcoex_profile=wb195
This will then appear in your boot messages:
[100482] athX: Enabling WB195 BTCOEX
This code is going to evolve pretty quickly (well, depending upon my
spare time) so don't assume the btcoex API is going to stay stable.
In order to use the bluetooth side, you must also load in firmware using
ath3kfw and the binary firmware file (ath3k-1.fw in my case.)
Tested:
* AR9280, no interference
* WB195 - AR9285 + AR3011 combo; STA mode; basic bluetooth inquiries
were enough to cause traffic stalls and disassociations. This has
stopped with the btcoex profile code.
TODO:
* Importantly - the AR9285 needs ASPM disabled if bluetooth coexistence
is enabled. No, I don't know why. It's likely some kind of bug to do
with the AR3011 sending bluetooth coexistence signals whilst the device
is asleep. Since we don't actually sleep the MAC just yet, it shouldn't
be a problem. That said, to be totally correct:
+ ASPM should be disabled - upon attach and wakeup
+ The PCIe powersave HAL code should never be called
Look at what the ath9k driver does for inspiration.
* Add WB197 (AR9287+AR3012) support
* Add support for the AR9485, which is another combo like the AR9285
* The later NICs have a different signaling mechanism between the MAC
and the bluetooth device; I haven't even begun to experiment with
making that HAL code work. But it should be a lot more automatic.
* The hardware can do much more interesting traffic weighting with
bluetooth and wifi traffic. None of this is currently used.
Ideally someone would code up something to watch the bluetooth traffic
GPIO (via an interrupt) and then watch it go high/low; then figure out
what the bluetooth traffic is and adjust things appropriately.
* If I get the time I may add in some code to at least track this stuff
and expose statistics. But it's up to someone else to experiment with
the bluetooth coexistence support and add the interesting stuff (like
"real" detection of bulk, audio, etc bluetooth traffic patterns and
change wifi parameters appropriately - eg, maximum aggregate length,
transmit power, using quiet time to control TX duty cycle, etc.)
2013-06-07 09:02:02 +00:00
|
|
|
/*
|
|
|
|
* Let bluetooth coexistence at in case it's needed for this
|
|
|
|
* channel
|
|
|
|
*/
|
|
|
|
ath_btcoex_enable(sc, ic->ic_curchan);
|
|
|
|
|
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
2013-05-21 18:02:54 +00:00
|
|
|
/*
|
|
|
|
* If we're doing TDMA, enforce the TXOP limitation for chips
|
|
|
|
* that support it.
|
|
|
|
*/
|
|
|
|
if (sc->sc_hasenforcetxop && sc->sc_tdma)
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 1);
|
|
|
|
else
|
|
|
|
ath_hal_setenforcetxop(sc->sc_ah, 0);
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Re-enable rx framework.
|
|
|
|
*/
|
|
|
|
if (ath_startrecv(sc) != 0) {
|
2008-04-20 20:35:46 +00:00
|
|
|
if_printf(ifp, "%s: unable to restart recv logic\n",
|
|
|
|
__func__);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ret = EIO;
|
|
|
|
goto finish;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Change channels and update the h/w rate map
|
|
|
|
* if we're switching; e.g. 11a to 11b/g.
|
|
|
|
*/
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_chan_change(sc, chan);
|
2003-08-19 22:17:04 +00:00
|
|
|
|
2011-06-26 13:53:24 +00:00
|
|
|
/*
|
|
|
|
* Reset clears the beacon timers; reset them
|
|
|
|
* here if needed.
|
|
|
|
*/
|
|
|
|
if (sc->sc_beacons) { /* restart beacons */
|
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
|
|
|
if (sc->sc_tdma)
|
|
|
|
ath_tdma_config(sc, NULL);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
ath_beacon_config(sc, NULL);
|
|
|
|
}
|
|
|
|
|
2003-08-19 22:17:04 +00:00
|
|
|
/*
|
|
|
|
* Re-enable interrupts.
|
|
|
|
*/
|
2012-02-17 03:46:38 +00:00
|
|
|
#if 0
|
2003-08-19 22:17:04 +00:00
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
#endif
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
|
|
|
finish:
|
|
|
|
ATH_PCU_LOCK(sc);
|
|
|
|
sc->sc_inreset_cnt--;
|
|
|
|
/* XXX only do this if sc_inreset_cnt == 0? */
|
2012-02-17 03:46:38 +00:00
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
|
|
|
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_LOCK(&ifp->if_snd);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
2012-03-10 20:09:02 +00:00
|
|
|
IF_UNLOCK(&ifp->if_snd);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
ath_txrx_start(sc);
|
|
|
|
/* XXX ath_start? */
|
|
|
|
|
|
|
|
return ret;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Periodically recalibrate the PHY to account
|
|
|
|
* for temperature/environment changes.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_calibrate(void *arg)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = arg;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2008-12-07 19:26:34 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2009-01-23 03:15:28 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2012-10-05 16:44:00 +00:00
|
|
|
HAL_BOOL longCal, isCalDone = AH_TRUE;
|
2011-01-21 05:21:00 +00:00
|
|
|
HAL_BOOL aniCal, shortCal = AH_FALSE;
|
2008-12-07 19:26:34 +00:00
|
|
|
int nextcal;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2009-01-23 03:15:28 +00:00
|
|
|
if (ic->ic_flags & IEEE80211_F_SCAN) /* defer, off channel */
|
|
|
|
goto restart;
|
2008-12-07 19:26:34 +00:00
|
|
|
longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz);
|
2011-01-21 05:21:00 +00:00
|
|
|
aniCal = (ticks - sc->sc_lastani >= ath_anicalinterval*hz/1000);
|
|
|
|
if (sc->sc_doresetcal)
|
|
|
|
shortCal = (ticks - sc->sc_lastshortcal >= ath_shortcalinterval*hz/1000);
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: shortCal=%d; longCal=%d; aniCal=%d\n", __func__, shortCal, longCal, aniCal);
|
|
|
|
if (aniCal) {
|
|
|
|
sc->sc_stats.ast_ani_cal++;
|
|
|
|
sc->sc_lastani = ticks;
|
|
|
|
ath_hal_ani_poll(ah, sc->sc_curchan);
|
|
|
|
}
|
|
|
|
|
2008-12-07 19:26:34 +00:00
|
|
|
if (longCal) {
|
|
|
|
sc->sc_stats.ast_per_cal++;
|
2010-08-10 07:56:56 +00:00
|
|
|
sc->sc_lastlongcal = ticks;
|
2008-12-07 19:26:34 +00:00
|
|
|
if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) {
|
|
|
|
/*
|
|
|
|
* Rfgain is out of bounds, reset the chip
|
|
|
|
* to load new gain values.
|
|
|
|
*/
|
|
|
|
DPRINTF(sc, ATH_DEBUG_CALIBRATE,
|
|
|
|
"%s: rfgain change\n", __func__);
|
|
|
|
sc->sc_stats.ast_per_rfgain++;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
sc->sc_resetcal = 0;
|
|
|
|
sc->sc_doresetcal = AH_TRUE;
|
2012-02-25 19:12:54 +00:00
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask);
|
|
|
|
callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
return;
|
2008-12-07 19:26:34 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
2008-12-07 19:26:34 +00:00
|
|
|
* If this long cal is after an idle period, then
|
|
|
|
* reset the data collection state so we start fresh.
|
2003-06-23 17:01:19 +00:00
|
|
|
*/
|
2008-12-07 19:26:34 +00:00
|
|
|
if (sc->sc_resetcal) {
|
2009-01-28 18:00:22 +00:00
|
|
|
(void) ath_hal_calreset(ah, sc->sc_curchan);
|
2008-12-07 19:26:34 +00:00
|
|
|
sc->sc_lastcalreset = ticks;
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_lastshortcal = ticks;
|
2008-12-07 19:26:34 +00:00
|
|
|
sc->sc_resetcal = 0;
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_doresetcal = AH_TRUE;
|
2008-12-07 19:26:34 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2011-01-21 05:21:00 +00:00
|
|
|
|
|
|
|
/* Only call if we're doing a short/long cal, not for ANI calibration */
|
|
|
|
if (shortCal || longCal) {
|
2012-10-05 16:44:00 +00:00
|
|
|
isCalDone = AH_FALSE;
|
2011-01-21 05:21:00 +00:00
|
|
|
if (ath_hal_calibrateN(ah, sc->sc_curchan, longCal, &isCalDone)) {
|
|
|
|
if (longCal) {
|
|
|
|
/*
|
|
|
|
* Calibrate noise floor data again in case of change.
|
|
|
|
*/
|
|
|
|
ath_hal_process_noisefloor(ah);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY,
|
|
|
|
"%s: calibration of channel %u failed\n",
|
|
|
|
__func__, sc->sc_curchan->ic_freq);
|
|
|
|
sc->sc_stats.ast_per_calfail++;
|
2008-12-07 19:26:34 +00:00
|
|
|
}
|
2011-01-21 05:21:00 +00:00
|
|
|
if (shortCal)
|
|
|
|
sc->sc_lastshortcal = ticks;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2008-12-07 19:26:34 +00:00
|
|
|
if (!isCalDone) {
|
2009-01-23 03:15:28 +00:00
|
|
|
restart:
|
2008-12-07 19:26:34 +00:00
|
|
|
/*
|
|
|
|
* Use a shorter interval to potentially collect multiple
|
|
|
|
* data samples required to complete calibration. Once
|
|
|
|
* we're told the work is done we drop back to a longer
|
|
|
|
* interval between requests. We're more aggressive doing
|
|
|
|
* work when operating as an AP to improve operation right
|
|
|
|
* after startup.
|
|
|
|
*/
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_lastshortcal = ticks;
|
|
|
|
nextcal = ath_shortcalinterval*hz/1000;
|
2008-12-07 19:26:34 +00:00
|
|
|
if (sc->sc_opmode != HAL_M_HOSTAP)
|
|
|
|
nextcal *= 10;
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_doresetcal = AH_TRUE;
|
2008-12-07 19:26:34 +00:00
|
|
|
} else {
|
2011-01-21 05:21:00 +00:00
|
|
|
/* nextcal should be the shortest time for next event */
|
2008-12-07 19:26:34 +00:00
|
|
|
nextcal = ath_longcalinterval*hz;
|
|
|
|
if (sc->sc_lastcalreset == 0)
|
|
|
|
sc->sc_lastcalreset = sc->sc_lastlongcal;
|
|
|
|
else if (ticks - sc->sc_lastcalreset >= ath_resetcalinterval*hz)
|
|
|
|
sc->sc_resetcal = 1; /* setup reset next trip */
|
2011-01-21 05:21:00 +00:00
|
|
|
sc->sc_doresetcal = AH_FALSE;
|
2008-12-07 19:26:34 +00:00
|
|
|
}
|
2011-01-21 05:21:00 +00:00
|
|
|
/* ANI calibration may occur more often than short/long/resetcal */
|
|
|
|
if (ath_anicalinterval > 0)
|
|
|
|
nextcal = MIN(nextcal, ath_anicalinterval*hz/1000);
|
2008-12-07 19:26:34 +00:00
|
|
|
|
|
|
|
if (nextcal != 0) {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: next +%u (%sisCalDone)\n",
|
|
|
|
__func__, nextcal, isCalDone ? "" : "!");
|
|
|
|
callout_reset(&sc->sc_cal_ch, nextcal, ath_calibrate, sc);
|
|
|
|
} else {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: calibration disabled\n",
|
|
|
|
__func__);
|
|
|
|
/* NB: don't rearm timer */
|
2006-02-10 19:07:08 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
static void
|
|
|
|
ath_scan_start(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
u_int32_t rfilt;
|
|
|
|
|
|
|
|
/* XXX calibration timer? */
|
|
|
|
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_LOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
sc->sc_scanning = 1;
|
|
|
|
sc->sc_syncbeacon = 0;
|
|
|
|
rfilt = ath_calcrxfilter(sc);
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
|
|
|
|
ATH_PCU_LOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ath_hal_setrxfilter(ah, rfilt);
|
|
|
|
ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0);
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
|
|
|
|
__func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_scan_end(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
u_int32_t rfilt;
|
|
|
|
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_LOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
sc->sc_scanning = 0;
|
|
|
|
rfilt = ath_calcrxfilter(sc);
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_UNLOCK(sc);
|
|
|
|
|
|
|
|
ATH_PCU_LOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ath_hal_setrxfilter(ah, rfilt);
|
|
|
|
ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
|
|
|
|
|
|
|
|
ath_hal_process_noisefloor(ah);
|
2012-03-02 02:57:10 +00:00
|
|
|
ATH_PCU_UNLOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
|
|
|
|
__func__, rfilt, ether_sprintf(sc->sc_curbssid),
|
|
|
|
sc->sc_curaid);
|
|
|
|
}
|
|
|
|
|
2012-04-10 06:25:11 +00:00
|
|
|
#ifdef ATH_ENABLE_11N
|
2012-03-25 03:14:31 +00:00
|
|
|
/*
|
|
|
|
* For now, just do a channel change.
|
|
|
|
*
|
|
|
|
* Later, we'll go through the hard slog of suspending tx/rx, changing rate
|
|
|
|
* control state and resetting the hardware without dropping frames out
|
|
|
|
* of the queue.
|
|
|
|
*
|
|
|
|
* The unfortunate trouble here is making absolutely sure that the
|
|
|
|
* channel width change has propagated enough so the hardware
|
|
|
|
* absolutely isn't handed bogus frames for it's current operating
|
|
|
|
* mode. (Eg, 40MHz frames in 20MHz mode.) Since TX and RX can and
|
|
|
|
* does occur in parallel, we need to make certain we've blocked
|
|
|
|
* any further ongoing TX (and RX, that can cause raw TX)
|
|
|
|
* before we do this.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_update_chw(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE, "%s: called\n", __func__);
|
|
|
|
ath_set_channel(ic);
|
|
|
|
}
|
2012-04-10 06:25:11 +00:00
|
|
|
#endif /* ATH_ENABLE_11N */
|
2012-03-25 03:14:31 +00:00
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
static void
|
|
|
|
ath_set_channel(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = ic->ic_ifp;
|
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
(void) ath_chan_set(sc, ic->ic_curchan);
|
|
|
|
/*
|
|
|
|
* If we are returning to our bss channel then mark state
|
|
|
|
* so the next recv'd beacon's tsf will be used to sync the
|
|
|
|
* beacon timers. Note that since we only hear beacons in
|
|
|
|
* sta/ibss mode this has no effect in other operating modes.
|
|
|
|
*/
|
2012-03-02 03:11:53 +00:00
|
|
|
ATH_LOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan)
|
|
|
|
sc->sc_syncbeacon = 1;
|
2012-03-02 03:11:53 +00:00
|
|
|
ATH_UNLOCK(sc);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
}
|
|
|
|
|
2010-02-19 18:23:45 +00:00
|
|
|
/*
|
2008-04-20 20:35:46 +00:00
|
|
|
* Walk the vap list and check if there any vap's in RUN state.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
static int
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_isanyrunningvaps(struct ieee80211vap *this)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = this->iv_ic;
|
|
|
|
struct ieee80211vap *vap;
|
|
|
|
|
|
|
|
IEEE80211_LOCK_ASSERT(ic);
|
|
|
|
|
|
|
|
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
2009-06-03 17:25:19 +00:00
|
|
|
if (vap != this && vap->iv_state >= IEEE80211_S_RUN)
|
2008-04-20 20:35:46 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = vap->iv_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_vap *avp = ATH_VAP(vap);
|
2003-07-20 21:38:20 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211_node *ni = NULL;
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
int i, error, stamode;
|
2003-06-23 17:01:19 +00:00
|
|
|
u_int32_t rfilt;
|
2011-06-29 13:21:52 +00:00
|
|
|
int csa_run_transition = 0;
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
static const HAL_LED_STATE leds[] = {
|
|
|
|
HAL_LED_INIT, /* IEEE80211_S_INIT */
|
|
|
|
HAL_LED_SCAN, /* IEEE80211_S_SCAN */
|
|
|
|
HAL_LED_AUTH, /* IEEE80211_S_AUTH */
|
|
|
|
HAL_LED_ASSOC, /* IEEE80211_S_ASSOC */
|
2007-09-17 05:12:19 +00:00
|
|
|
HAL_LED_RUN, /* IEEE80211_S_CAC */
|
2003-06-23 17:01:19 +00:00
|
|
|
HAL_LED_RUN, /* IEEE80211_S_RUN */
|
2007-09-17 05:12:19 +00:00
|
|
|
HAL_LED_RUN, /* IEEE80211_S_CSA */
|
|
|
|
HAL_LED_RUN, /* IEEE80211_S_SLEEP */
|
2003-06-23 17:01:19 +00:00
|
|
|
};
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE, "%s: %s -> %s\n", __func__,
|
2008-04-20 20:35:46 +00:00
|
|
|
ieee80211_state_name[vap->iv_state],
|
2004-12-08 17:34:36 +00:00
|
|
|
ieee80211_state_name[nstate]);
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-02-18 09:18:06 +00:00
|
|
|
/*
|
|
|
|
* net80211 _should_ have the comlock asserted at this point.
|
|
|
|
* There are some comments around the calls to vap->iv_newstate
|
|
|
|
* which indicate that it (newstate) may end up dropping the
|
|
|
|
* lock. This and the subsequent lock assert check after newstate
|
|
|
|
* are an attempt to catch these and figure out how/why.
|
|
|
|
*/
|
|
|
|
IEEE80211_LOCK_ASSERT(ic);
|
|
|
|
|
2011-06-29 13:21:52 +00:00
|
|
|
if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
|
|
|
|
csa_run_transition = 1;
|
|
|
|
|
2009-03-09 23:10:19 +00:00
|
|
|
callout_drain(&sc->sc_cal_ch);
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_setledstate(ah, leds[nstate]); /* set LED */
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
if (nstate == IEEE80211_S_SCAN) {
|
2005-01-18 19:31:31 +00:00
|
|
|
/*
|
2008-04-20 20:35:46 +00:00
|
|
|
* Scanning: turn off beacon miss and don't beacon.
|
|
|
|
* Mark beacon state so when we reach RUN state we'll
|
|
|
|
* [re]setup beacons. Unblock the task q thread so
|
|
|
|
* deferred interrupt processing is done.
|
2005-01-18 19:31:31 +00:00
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_intrset(ah,
|
|
|
|
sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
|
2007-05-29 16:13:59 +00:00
|
|
|
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
|
2008-04-20 20:35:46 +00:00
|
|
|
sc->sc_beacons = 0;
|
|
|
|
taskqueue_unblock(sc->sc_tq);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
|
2012-02-13 00:28:41 +00:00
|
|
|
ni = ieee80211_ref_node(vap->iv_bss);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
rfilt = ath_calcrxfilter(sc);
|
2008-04-20 20:35:46 +00:00
|
|
|
stamode = (vap->iv_opmode == IEEE80211_M_STA ||
|
2008-10-27 17:54:17 +00:00
|
|
|
vap->iv_opmode == IEEE80211_M_AHDEMO ||
|
2008-04-20 20:35:46 +00:00
|
|
|
vap->iv_opmode == IEEE80211_M_IBSS);
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (stamode && nstate == IEEE80211_S_RUN) {
|
|
|
|
sc->sc_curaid = ni->ni_associd;
|
|
|
|
IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid);
|
2008-04-20 20:35:46 +00:00
|
|
|
ath_hal_setassocid(ah, sc->sc_curbssid, sc->sc_curaid);
|
|
|
|
}
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0x%x\n",
|
2008-04-20 20:35:46 +00:00
|
|
|
__func__, rfilt, ether_sprintf(sc->sc_curbssid), sc->sc_curaid);
|
2003-06-23 17:01:19 +00:00
|
|
|
ath_hal_setrxfilter(ah, rfilt);
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
/* XXX is this to restore keycache on resume? */
|
|
|
|
if (vap->iv_opmode != IEEE80211_M_STA &&
|
|
|
|
(vap->iv_flags & IEEE80211_F_PRIVACY)) {
|
2003-06-23 17:01:19 +00:00
|
|
|
for (i = 0; i < IEEE80211_WEP_NKID; i++)
|
|
|
|
if (ath_hal_keyisvalid(ah, i))
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ath_hal_keysetmac(ah, i, ni->ni_bssid);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2008-04-20 20:35:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Invoke the parent method to do net80211 work.
|
|
|
|
*/
|
|
|
|
error = avp->av_newstate(vap, nstate, arg);
|
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
2004-12-08 17:34:36 +00:00
|
|
|
|
2012-02-18 09:18:06 +00:00
|
|
|
/*
|
|
|
|
* See above: ensure av_newstate() doesn't drop the lock
|
|
|
|
* on us.
|
|
|
|
*/
|
|
|
|
IEEE80211_LOCK_ASSERT(ic);
|
|
|
|
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
if (nstate == IEEE80211_S_RUN) {
|
2008-04-20 20:35:46 +00:00
|
|
|
/* NB: collect bss node again, it may have changed */
|
2012-02-13 00:28:41 +00:00
|
|
|
ieee80211_free_node(ni);
|
|
|
|
ni = ieee80211_ref_node(vap->iv_bss);
|
2008-04-20 20:35:46 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_STATE,
|
2008-04-20 20:35:46 +00:00
|
|
|
"%s(RUN): iv_flags 0x%08x bintvl %d bssid %s "
|
|
|
|
"capinfo 0x%04x chan %d\n", __func__,
|
|
|
|
vap->iv_flags, ni->ni_intval, ether_sprintf(ni->ni_bssid),
|
|
|
|
ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
|
|
|
|
|
|
|
|
switch (vap->iv_opmode) {
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
case IEEE80211_M_AHDEMO:
|
|
|
|
if ((vap->iv_caps & IEEE80211_C_TDMA) == 0)
|
|
|
|
break;
|
|
|
|
/* fall thru... */
|
|
|
|
#endif
|
2005-06-06 16:39:21 +00:00
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
case IEEE80211_M_IBSS:
|
Implementation of the upcoming Wireless Mesh standard, 802.11s, on the
net80211 wireless stack. This work is based on the March 2009 D3.0 draft
standard. This standard is expected to become final next year.
This includes two main net80211 modules, ieee80211_mesh.c
which deals with peer link management, link metric calculation,
routing table control and mesh configuration and ieee80211_hwmp.c
which deals with the actually routing process on the mesh network.
HWMP is the mandatory routing protocol on by the mesh standard, but
others, such as RA-OLSR, can be implemented.
Authentication and encryption are not implemented.
There are several scripts under tools/tools/net80211/scripts that can be
used to test different mesh network topologies and they also teach you
how to setup a mesh vap (for the impatient: ifconfig wlan0 create
wlandev ... wlanmode mesh).
A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled
by default on GENERIC kernels for i386, amd64, sparc64 and pc98.
Drivers that support mesh networks right now are: ath, ral and mwl.
More information at: http://wiki.freebsd.org/WifiMesh
Please note that this work is experimental. Also, please note that
bridging a mesh vap with another network interface is not yet supported.
Many thanks to the FreeBSD Foundation for sponsoring this project and to
Sam Leffler for his support.
Also, I would like to thank Gateworks Corporation for sending me a
Cambria board which was used during the development of this project.
Reviewed by: sam
Approved by: re (kensmith)
Obtained from: projects/mesh11s
2009-07-11 15:02:45 +00:00
|
|
|
case IEEE80211_M_MBSS:
|
2005-01-24 20:05:03 +00:00
|
|
|
/*
|
2005-06-06 16:39:21 +00:00
|
|
|
* Allocate and setup the beacon frame.
|
|
|
|
*
|
2005-01-24 20:05:03 +00:00
|
|
|
* Stop any previous beacon DMA. This may be
|
|
|
|
* necessary, for example, when an ibss merge
|
|
|
|
* causes reconfiguration; there will be a state
|
|
|
|
* transition from RUN->RUN that means we may
|
|
|
|
* be called with beacon transmission active.
|
|
|
|
*/
|
|
|
|
ath_hal_stoptxdma(ah, sc->sc_bhalq);
|
2008-04-20 20:35:46 +00:00
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
error = ath_beacon_alloc(sc, ni);
|
|
|
|
if (error != 0)
|
|
|
|
goto bad;
|
2006-02-09 21:42:53 +00:00
|
|
|
/*
|
2006-02-09 22:21:53 +00:00
|
|
|
* If joining an adhoc network defer beacon timer
|
|
|
|
* configuration to the next beacon frame so we
|
|
|
|
* have a current TSF to use. Otherwise we're
|
2008-04-20 20:35:46 +00:00
|
|
|
* starting an ibss/bss so there's no need to delay;
|
|
|
|
* if this is the first vap moving to RUN state, then
|
|
|
|
* beacon state needs to be [re]configured.
|
2006-02-09 21:42:53 +00:00
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
if (vap->iv_opmode == IEEE80211_M_IBSS &&
|
|
|
|
ni->ni_tstamp.tsf != 0) {
|
2006-02-09 22:21:53 +00:00
|
|
|
sc->sc_syncbeacon = 1;
|
2008-04-20 20:35:46 +00:00
|
|
|
} else if (!sc->sc_beacons) {
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
if (vap->iv_caps & IEEE80211_C_TDMA)
|
|
|
|
ath_tdma_config(sc, vap);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
ath_beacon_config(sc, vap);
|
2008-04-20 20:35:46 +00:00
|
|
|
sc->sc_beacons = 1;
|
|
|
|
}
|
2005-06-06 16:39:21 +00:00
|
|
|
break;
|
|
|
|
case IEEE80211_M_STA:
|
2006-02-09 21:42:53 +00:00
|
|
|
/*
|
2006-02-09 22:21:53 +00:00
|
|
|
* Defer beacon timer configuration to the next
|
|
|
|
* beacon frame so we have a current TSF to use
|
|
|
|
* (any TSF collected when scanning is likely old).
|
2011-06-29 13:21:52 +00:00
|
|
|
* However if it's due to a CSA -> RUN transition,
|
|
|
|
* force a beacon update so we pick up a lack of
|
|
|
|
* beacons from an AP in CAC and thus force a
|
|
|
|
* scan.
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
*
|
|
|
|
* And, there's also corner cases here where
|
|
|
|
* after a scan, the AP may have disappeared.
|
|
|
|
* In that case, we may not receive an actual
|
|
|
|
* beacon to update the beacon timer and thus we
|
|
|
|
* won't get notified of the missing beacons.
|
2006-02-09 21:42:53 +00:00
|
|
|
*/
|
2006-02-09 22:21:53 +00:00
|
|
|
sc->sc_syncbeacon = 1;
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
#if 0
|
2011-06-29 13:21:52 +00:00
|
|
|
if (csa_run_transition)
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
#endif
|
2011-06-29 13:21:52 +00:00
|
|
|
ath_beacon_config(sc, vap);
|
Fix hangs (exposed by spectral scan activity) in STA mode when the
chip hangs.
* Always do a reset in ath_bmiss_proc(), regardless of whether the
hardware is "hung" or not. Specifically, for spectral scan, there's
likely a whole bunch of potential hangs that we don't (yet) recognise
in the HAL. So to avoid staying RX deaf persisting until the station
disassociates, just do a no-loss reset.
* Set sc_beacons=1 in STA mode. During a reset, the beacon programming
isn't done. (It's likely I need to set sc_syncbeacons during a hang
reset, but I digress.) Thus after a reset, there's no beacon timer
programming to send a BMISS interrupt if beacons aren't heard ..
thus if the AP disappears, you won't get notified and you'll have to
reset your interface.
This hasn't yet fixed all of the hangs that I've seen when debugging
spectral scan, but it's certainly reduced the hang frequency and it
should improve general STA stability in very noisy environments.
Tested:
* AR9280, STA mode, spectral scan off/on
PR: kern/175227
2013-01-17 16:43:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* PR: kern/175227
|
|
|
|
*
|
|
|
|
* Reconfigure beacons during reset; as otherwise
|
|
|
|
* we won't get the beacon timers reprogrammed
|
|
|
|
* after a reset and thus we won't pick up a
|
|
|
|
* beacon miss interrupt.
|
|
|
|
*
|
|
|
|
* Hopefully we'll see a beacon before the BMISS
|
|
|
|
* timer fires (too often), leading to a STA
|
|
|
|
* disassociation.
|
|
|
|
*/
|
|
|
|
sc->sc_beacons = 1;
|
2005-06-06 16:39:21 +00:00
|
|
|
break;
|
2008-04-20 20:35:46 +00:00
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
/*
|
|
|
|
* Monitor mode vaps have only INIT->RUN and RUN->RUN
|
|
|
|
* transitions so we must re-enable interrupts here to
|
|
|
|
* handle the case of a single monitor mode vap.
|
|
|
|
*/
|
|
|
|
ath_hal_intrset(ah, sc->sc_imask);
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_WDS:
|
|
|
|
break;
|
2005-06-06 16:39:21 +00:00
|
|
|
default:
|
|
|
|
break;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2006-01-09 17:13:20 +00:00
|
|
|
/*
|
|
|
|
* Let the hal process statistics collected during a
|
|
|
|
* scan so it can provide calibrated noise floor data.
|
|
|
|
*/
|
|
|
|
ath_hal_process_noisefloor(ah);
|
2006-02-09 21:23:44 +00:00
|
|
|
/*
|
|
|
|
* Reset rssi stats; maybe not the best place...
|
|
|
|
*/
|
|
|
|
sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
|
|
|
sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
|
|
|
|
sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
|
2008-04-20 20:35:46 +00:00
|
|
|
/*
|
|
|
|
* Finally, start any timers and the task q thread
|
|
|
|
* (in case we didn't go through SCAN state).
|
|
|
|
*/
|
2008-12-07 19:26:34 +00:00
|
|
|
if (ath_longcalinterval != 0) {
|
2008-04-20 20:35:46 +00:00
|
|
|
/* start periodic recalibration timer */
|
2008-12-07 19:26:34 +00:00
|
|
|
callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc);
|
|
|
|
} else {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_CALIBRATE,
|
|
|
|
"%s: calibration disabled\n", __func__);
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
taskqueue_unblock(sc->sc_tq);
|
|
|
|
} else if (nstate == IEEE80211_S_INIT) {
|
|
|
|
/*
|
|
|
|
* If there are no vaps left in RUN state then
|
|
|
|
* shutdown host/driver operation:
|
|
|
|
* o disable interrupts
|
|
|
|
* o disable the task queue thread
|
|
|
|
* o mark beacon processing as stopped
|
|
|
|
*/
|
|
|
|
if (!ath_isanyrunningvaps(vap)) {
|
|
|
|
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
|
|
|
|
/* disable interrupts */
|
|
|
|
ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
|
|
|
|
taskqueue_block(sc->sc_tq);
|
|
|
|
sc->sc_beacons = 0;
|
|
|
|
}
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
ath_hal_setcca(ah, AH_TRUE);
|
|
|
|
#endif
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
bad:
|
2012-02-13 00:28:41 +00:00
|
|
|
ieee80211_free_node(ni);
|
2003-06-23 17:01:19 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2005-06-06 16:39:21 +00:00
|
|
|
/*
|
|
|
|
* Allocate a key cache slot to the station so we can
|
|
|
|
* setup a mapping from key index to node. The key cache
|
|
|
|
* slot is needed for managing antenna state and for
|
|
|
|
* compression when stations do not use crypto. We do
|
|
|
|
* it uniliaterally here; if crypto is employed this slot
|
|
|
|
* will be reassigned.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_setup_stationkey(struct ieee80211_node *ni)
|
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
2005-08-08 18:46:36 +00:00
|
|
|
ieee80211_keyix keyix, rxkeyix;
|
2005-06-06 16:39:21 +00:00
|
|
|
|
2012-02-13 00:28:41 +00:00
|
|
|
/* XXX should take a locked ref to vap->iv_bss */
|
2008-04-20 20:35:46 +00:00
|
|
|
if (!ath_key_alloc(vap, &ni->ni_ucastkey, &keyix, &rxkeyix)) {
|
2005-06-06 16:39:21 +00:00
|
|
|
/*
|
|
|
|
* Key cache is full; we'll fall back to doing
|
|
|
|
* the more expensive lookup in software. Note
|
|
|
|
* this also means no h/w compression.
|
|
|
|
*/
|
|
|
|
/* XXX msg+statistic */
|
|
|
|
} else {
|
2005-08-08 18:46:36 +00:00
|
|
|
/* XXX locking? */
|
2005-06-06 16:39:21 +00:00
|
|
|
ni->ni_ucastkey.wk_keyix = keyix;
|
2005-08-08 18:46:36 +00:00
|
|
|
ni->ni_ucastkey.wk_rxkeyix = rxkeyix;
|
2009-02-10 19:27:50 +00:00
|
|
|
/* NB: must mark device key to get called back on delete */
|
|
|
|
ni->ni_ucastkey.wk_flags |= IEEE80211_KEY_DEVKEY;
|
2008-05-29 00:10:48 +00:00
|
|
|
IEEE80211_ADDR_COPY(ni->ni_ucastkey.wk_macaddr, ni->ni_macaddr);
|
2005-06-06 16:39:21 +00:00
|
|
|
/* NB: this will create a pass-thru key entry */
|
2011-11-08 19:25:52 +00:00
|
|
|
ath_keyset(sc, vap, &ni->ni_ucastkey, vap->iv_bss);
|
2005-06-06 16:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-23 17:01:19 +00:00
|
|
|
/*
|
|
|
|
* Setup driver-specific state for a newly associated node.
|
|
|
|
* Note that we're called also on a re-associate, the isnew
|
|
|
|
* param tells us if this is the first time or not.
|
|
|
|
*/
|
|
|
|
static void
|
2005-07-22 17:57:16 +00:00
|
|
|
ath_newassoc(struct ieee80211_node *ni, int isnew)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ath_node *an = ATH_NODE(ni);
|
|
|
|
struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
2008-10-27 17:03:24 +00:00
|
|
|
const struct ieee80211_txparam *tp = ni->ni_txparms;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2009-05-07 00:35:32 +00:00
|
|
|
an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
|
|
|
|
an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate);
|
2008-04-20 20:35:46 +00:00
|
|
|
|
|
|
|
ath_rate_newassoc(sc, an, isnew);
|
2013-05-29 05:10:11 +00:00
|
|
|
|
2010-02-19 18:23:45 +00:00
|
|
|
if (isnew &&
|
2008-04-20 20:35:46 +00:00
|
|
|
(vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey &&
|
|
|
|
ni->ni_ucastkey.wk_keyix == IEEE80211_KEYIX_NONE)
|
2005-06-06 16:39:21 +00:00
|
|
|
ath_setup_stationkey(ni);
|
2013-05-13 18:56:04 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're reassociating, make sure that any paused queues
|
|
|
|
* get unpaused.
|
|
|
|
*
|
|
|
|
* Now, we may hvae frames in the hardware queue for this node.
|
|
|
|
* So if we are reassociating and there are frames in the queue,
|
|
|
|
* we need to go through the cleanup path to ensure that they're
|
|
|
|
* marked as non-aggregate.
|
|
|
|
*/
|
|
|
|
if (! isnew) {
|
2013-05-29 05:10:11 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE,
|
2013-05-13 18:56:04 +00:00
|
|
|
"%s: %6D: reassoc; is_powersave=%d\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
an->an_is_powersave);
|
|
|
|
|
|
|
|
/* XXX for now, we can't hold the lock across assoc */
|
|
|
|
ath_tx_node_reassoc(sc, an);
|
|
|
|
|
|
|
|
/* XXX for now, we can't hold the lock across wakeup */
|
|
|
|
if (an->an_is_powersave)
|
|
|
|
ath_tx_node_wakeup(sc, an);
|
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-01-28 18:00:22 +00:00
|
|
|
ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
|
2008-04-20 20:35:46 +00:00
|
|
|
int nchans, struct ieee80211_channel chans[])
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2009-01-28 18:00:22 +00:00
|
|
|
HAL_STATUS status;
|
2008-04-20 20:35:46 +00:00
|
|
|
|
2008-10-27 17:35:09 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_REGDOMAIN,
|
2009-01-28 18:00:22 +00:00
|
|
|
"%s: rd %u cc %u location %c%s\n",
|
|
|
|
__func__, reg->regdomain, reg->country, reg->location,
|
|
|
|
reg->ecm ? " ecm" : "");
|
|
|
|
|
|
|
|
status = ath_hal_set_channels(ah, chans, nchans,
|
|
|
|
reg->country, reg->regdomain);
|
|
|
|
if (status != HAL_OK) {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: failed, status %u\n",
|
|
|
|
__func__, status);
|
|
|
|
return EINVAL; /* XXX */
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
2011-08-08 16:22:42 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_getradiocaps(struct ieee80211com *ic,
|
2009-01-27 23:19:36 +00:00
|
|
|
int maxchans, int *nchans, struct ieee80211_channel chans[])
|
2008-04-20 20:35:46 +00:00
|
|
|
{
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2008-10-27 17:35:09 +00:00
|
|
|
|
2009-01-28 18:00:22 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n",
|
|
|
|
__func__, SKU_DEBUG, CTRY_DEFAULT);
|
2008-10-27 17:35:09 +00:00
|
|
|
|
2009-01-28 18:00:22 +00:00
|
|
|
/* XXX check return */
|
|
|
|
(void) ath_hal_getchannels(ah, chans, maxchans, nchans,
|
|
|
|
HAL_MODE_ALL, CTRY_DEFAULT, SKU_DEBUG, AH_TRUE);
|
2008-04-27 22:03:56 +00:00
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ath_getchannels(struct ath_softc *sc)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2009-01-28 18:00:22 +00:00
|
|
|
HAL_STATUS status;
|
2008-04-20 20:35:46 +00:00
|
|
|
|
|
|
|
/*
|
2009-01-28 18:00:22 +00:00
|
|
|
* Collect channel set based on EEPROM contents.
|
2008-04-20 20:35:46 +00:00
|
|
|
*/
|
2009-01-28 18:00:22 +00:00
|
|
|
status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX,
|
|
|
|
&ic->ic_nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE);
|
|
|
|
if (status != HAL_OK) {
|
2008-04-20 20:35:46 +00:00
|
|
|
if_printf(ifp, "%s: unable to collect channel list from hal, "
|
2009-01-28 18:00:22 +00:00
|
|
|
"status %d\n", __func__, status);
|
|
|
|
return EINVAL;
|
2008-04-20 20:35:46 +00:00
|
|
|
}
|
2009-01-28 18:00:22 +00:00
|
|
|
(void) ath_hal_getregdomain(ah, &sc->sc_eerd);
|
|
|
|
ath_hal_getcountrycode(ah, &sc->sc_eecc); /* NB: cannot fail */
|
|
|
|
/* XXX map Atheros sku's to net80211 SKU's */
|
|
|
|
/* XXX net80211 types too small */
|
|
|
|
ic->ic_regdomain.regdomain = (uint16_t) sc->sc_eerd;
|
|
|
|
ic->ic_regdomain.country = (uint16_t) sc->sc_eecc;
|
|
|
|
ic->ic_regdomain.isocc[0] = ' '; /* XXX don't know */
|
|
|
|
ic->ic_regdomain.isocc[1] = ' ';
|
|
|
|
|
2008-04-20 20:35:46 +00:00
|
|
|
ic->ic_regdomain.ecm = 1;
|
|
|
|
ic->ic_regdomain.location = 'I';
|
2008-10-27 17:35:09 +00:00
|
|
|
|
|
|
|
DPRINTF(sc, ATH_DEBUG_REGDOMAIN,
|
2009-01-28 18:00:22 +00:00
|
|
|
"%s: eeprom rd %u cc %u (mapped rd %u cc %u) location %c%s\n",
|
2008-10-27 17:35:09 +00:00
|
|
|
__func__, sc->sc_eerd, sc->sc_eecc,
|
|
|
|
ic->ic_regdomain.regdomain, ic->ic_regdomain.country,
|
2009-01-28 18:00:22 +00:00
|
|
|
ic->ic_regdomain.location, ic->ic_regdomain.ecm ? " ecm" : "");
|
2003-06-23 17:01:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ath_rate_setup(struct ath_softc *sc, u_int mode)
|
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
const HAL_RATE_TABLE *rt;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case IEEE80211_MODE_11A:
|
2006-02-09 21:31:48 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11A);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
2007-01-15 01:15:57 +00:00
|
|
|
case IEEE80211_MODE_HALF:
|
2006-12-27 19:07:09 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11A_HALF_RATE);
|
|
|
|
break;
|
2007-01-15 01:15:57 +00:00
|
|
|
case IEEE80211_MODE_QUARTER:
|
2006-12-27 19:07:09 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11A_QUARTER_RATE);
|
|
|
|
break;
|
2003-06-23 17:01:19 +00:00
|
|
|
case IEEE80211_MODE_11B:
|
2006-02-09 21:31:48 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11B);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
|
|
|
case IEEE80211_MODE_11G:
|
2006-02-09 21:31:48 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11G);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
2004-12-08 17:34:36 +00:00
|
|
|
case IEEE80211_MODE_TURBO_A:
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_108A);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
2004-12-08 17:34:36 +00:00
|
|
|
case IEEE80211_MODE_TURBO_G:
|
2006-02-09 21:31:48 +00:00
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_108G);
|
2004-12-08 17:34:36 +00:00
|
|
|
break;
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
case IEEE80211_MODE_STURBO_A:
|
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_TURBO);
|
|
|
|
break;
|
|
|
|
case IEEE80211_MODE_11NA:
|
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11NA_HT20);
|
|
|
|
break;
|
|
|
|
case IEEE80211_MODE_11NG:
|
|
|
|
rt = ath_hal_getratetable(ah, HAL_MODE_11NG_HT20);
|
|
|
|
break;
|
2003-06-23 17:01:19 +00:00
|
|
|
default:
|
2004-12-08 17:34:36 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid mode %u\n",
|
|
|
|
__func__, mode);
|
2003-06-23 17:01:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2006-02-09 21:31:48 +00:00
|
|
|
sc->sc_rates[mode] = rt;
|
2006-12-27 19:07:09 +00:00
|
|
|
return (rt != NULL);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode)
|
|
|
|
{
|
2005-01-18 19:03:04 +00:00
|
|
|
#define N(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
/* NB: on/off times from the Atheros NDIS driver, w/ permission */
|
|
|
|
static const struct {
|
|
|
|
u_int rate; /* tx/rx 802.11 rate */
|
|
|
|
u_int16_t timeOn; /* LED on time (ms) */
|
|
|
|
u_int16_t timeOff; /* LED off time (ms) */
|
|
|
|
} blinkrates[] = {
|
|
|
|
{ 108, 40, 10 },
|
|
|
|
{ 96, 44, 11 },
|
|
|
|
{ 72, 50, 13 },
|
|
|
|
{ 48, 57, 14 },
|
|
|
|
{ 36, 67, 16 },
|
|
|
|
{ 24, 80, 20 },
|
|
|
|
{ 22, 100, 25 },
|
|
|
|
{ 18, 133, 34 },
|
|
|
|
{ 12, 160, 40 },
|
|
|
|
{ 10, 200, 50 },
|
|
|
|
{ 6, 240, 58 },
|
|
|
|
{ 4, 267, 66 },
|
|
|
|
{ 2, 400, 100 },
|
|
|
|
{ 0, 500, 130 },
|
2007-01-15 01:15:57 +00:00
|
|
|
/* XXX half/quarter rates */
|
2005-01-18 19:03:04 +00:00
|
|
|
};
|
2003-06-23 17:01:19 +00:00
|
|
|
const HAL_RATE_TABLE *rt;
|
2005-01-18 19:03:04 +00:00
|
|
|
int i, j;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
|
|
|
memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
|
|
|
|
rt = sc->sc_rates[mode];
|
|
|
|
KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
|
2008-10-27 18:02:47 +00:00
|
|
|
for (i = 0; i < rt->rateCount; i++) {
|
|
|
|
uint8_t ieeerate = rt->info[i].dot11Rate & IEEE80211_RATE_VAL;
|
|
|
|
if (rt->info[i].phy != IEEE80211_T_HT)
|
|
|
|
sc->sc_rixmap[ieeerate] = i;
|
|
|
|
else
|
|
|
|
sc->sc_rixmap[ieeerate | IEEE80211_RATE_MCS] = i;
|
|
|
|
}
|
2003-08-19 21:24:16 +00:00
|
|
|
memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
|
2008-10-27 18:22:44 +00:00
|
|
|
for (i = 0; i < N(sc->sc_hwmap); i++) {
|
|
|
|
if (i >= rt->rateCount) {
|
2005-01-18 19:03:04 +00:00
|
|
|
sc->sc_hwmap[i].ledon = (500 * hz) / 1000;
|
|
|
|
sc->sc_hwmap[i].ledoff = (130 * hz) / 1000;
|
2004-12-31 20:32:40 +00:00
|
|
|
continue;
|
2005-01-18 19:03:04 +00:00
|
|
|
}
|
|
|
|
sc->sc_hwmap[i].ieeerate =
|
2008-10-27 18:22:44 +00:00
|
|
|
rt->info[i].dot11Rate & IEEE80211_RATE_VAL;
|
|
|
|
if (rt->info[i].phy == IEEE80211_T_HT)
|
2008-10-27 18:05:26 +00:00
|
|
|
sc->sc_hwmap[i].ieeerate |= IEEE80211_RATE_MCS;
|
2005-01-24 20:31:24 +00:00
|
|
|
sc->sc_hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
|
2008-10-27 18:22:44 +00:00
|
|
|
if (rt->info[i].shortPreamble ||
|
|
|
|
rt->info[i].phy == IEEE80211_T_OFDM)
|
2005-01-24 20:31:24 +00:00
|
|
|
sc->sc_hwmap[i].txflags |= IEEE80211_RADIOTAP_F_SHORTPRE;
|
2009-05-20 20:00:40 +00:00
|
|
|
sc->sc_hwmap[i].rxflags = sc->sc_hwmap[i].txflags;
|
2005-01-18 19:03:04 +00:00
|
|
|
for (j = 0; j < N(blinkrates)-1; j++)
|
|
|
|
if (blinkrates[j].rate == sc->sc_hwmap[i].ieeerate)
|
|
|
|
break;
|
|
|
|
/* NB: this uses the last entry if the rate isn't found */
|
|
|
|
/* XXX beware of overlow */
|
|
|
|
sc->sc_hwmap[i].ledon = (blinkrates[j].timeOn * hz) / 1000;
|
|
|
|
sc->sc_hwmap[i].ledoff = (blinkrates[j].timeOff * hz) / 1000;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
sc->sc_currates = rt;
|
|
|
|
sc->sc_curmode = mode;
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* All protection frames are transmited at 2Mb/s for
|
|
|
|
* 11g, otherwise at 1Mb/s.
|
|
|
|
*/
|
2006-02-09 21:17:28 +00:00
|
|
|
if (mode == IEEE80211_MODE_11G)
|
2009-05-07 00:35:32 +00:00
|
|
|
sc->sc_protrix = ath_tx_findrix(sc, 2*2);
|
2006-02-09 21:17:28 +00:00
|
|
|
else
|
2009-05-07 00:35:32 +00:00
|
|
|
sc->sc_protrix = ath_tx_findrix(sc, 2*1);
|
2010-02-19 18:23:45 +00:00
|
|
|
/* NB: caller is responsible for resetting rate control state */
|
2005-01-18 19:03:04 +00:00
|
|
|
#undef N
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
static void
|
2009-03-09 23:10:19 +00:00
|
|
|
ath_watchdog(void *arg)
|
2004-12-08 17:34:36 +00:00
|
|
|
{
|
2009-03-09 23:10:19 +00:00
|
|
|
struct ath_softc *sc = arg;
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
int do_reset = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2009-03-09 23:10:19 +00:00
|
|
|
if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) {
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2008-11-30 18:34:27 +00:00
|
|
|
uint32_t hangs;
|
|
|
|
|
|
|
|
if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) &&
|
|
|
|
hangs != 0) {
|
|
|
|
if_printf(ifp, "%s hang detected (0x%x)\n",
|
2010-02-19 18:23:45 +00:00
|
|
|
hangs & 0xff ? "bb" : "mac", hangs);
|
2008-11-30 18:34:27 +00:00
|
|
|
} else
|
|
|
|
if_printf(ifp, "device timeout\n");
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
do_reset = 1;
|
Update 802.11 wireless support:
o major overhaul of the way channels are handled: channels are now
fully enumerated and uniquely identify the operating characteristics;
these changes are visible to user applications which require changes
o make scanning support independent of the state machine to enable
background scanning and roaming
o move scanning support into loadable modules based on the operating
mode to enable different policies and reduce the memory footprint
on systems w/ constrained resources
o add background scanning in station mode (no support for adhoc/ibss
mode yet)
o significantly speedup sta mode scanning with a variety of techniques
o add roaming support when background scanning is supported; for now
we use a simple algorithm to trigger a roam: we threshold the rssi
and tx rate, if either drops too low we try to roam to a new ap
o add tx fragmentation support
o add first cut at 802.11n support: this code works with forthcoming
drivers but is incomplete; it's included now to establish a baseline
for other drivers to be developed and for user applications
o adjust max_linkhdr et. al. to reflect 802.11 requirements; this eliminates
prepending mbufs for traffic generated locally
o add support for Atheros protocol extensions; mainly the fast frames
encapsulation (note this can be used with any card that can tx+rx
large frames correctly)
o add sta support for ap's that beacon both WPA1+2 support
o change all data types from bsd-style to posix-style
o propagate noise floor data from drivers to net80211 and on to user apps
o correct various issues in the sta mode state machine related to handling
authentication and association failures
o enable the addition of sta mode power save support for drivers that need
net80211 support (not in this commit)
o remove old WI compatibility ioctls (wicontrol is officially dead)
o change the data structures returned for get sta info and get scan
results so future additions will not break user apps
o fixed tx rate is now maintained internally as an ieee rate and not an
index into the rate set; this needs to be extended to deal with
multi-mode operation
o add extended channel specifications to radiotap to enable 11n sniffing
Drivers:
o ath: add support for bg scanning, tx fragmentation, fast frames,
dynamic turbo (lightly tested), 11n (sniffing only and needs
new hal)
o awi: compile tested only
o ndis: lightly tested
o ipw: lightly tested
o iwi: add support for bg scanning (well tested but may have some
rough edges)
o ral, ural, rum: add suppoort for bg scanning, calibrate rssi data
o wi: lightly tested
This work is based on contributions by Atheros, kmacy, sephe, thompsa,
mlaier, kevlo, and others. Much of the scanning work was supported by
Atheros. The 11n work was supported by Marvell.
2007-06-11 03:36:55 +00:00
|
|
|
ifp->if_oerrors++;
|
|
|
|
sc->sc_stats.ast_watchdog++;
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't hold the lock across the ath_reset() call.
|
2012-02-25 19:12:54 +00:00
|
|
|
*
|
|
|
|
* And since this routine can't hold a lock and sleep,
|
|
|
|
* do the reset deferred.
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
*/
|
|
|
|
if (do_reset) {
|
2012-02-25 19:12:54 +00:00
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask);
|
Flesh out some slightly dirty reset/channel change serialisation code
for the ath(4) driver.
Currently, there's nothing stopping reset, channel change and general
TX/RX from overlapping with each other. This wasn't a big deal with
pre-11n traffic as it just results in some dropped frames.
It's possible this may have also caused some inconsistencies and
badly-setup hardware.
Since locks can't be held across all of this (the Linux solution)
due to LORs with the network stack locks, some state counter
variables are used to track what parts of the code the driver is
currently in.
When the hardware is being reset, it disables the taskqueue and
waits for pending interrupts, tx, rx and tx completion before
it begins the reset or channel change.
TX and RX both abort if called during an active reset or channel
change.
Finally, the reset path now doesn't flush frames if ATH_RESET_NOLOSS
is set. Instead, completed TX and RX frames are passed back up to
net80211 before the reset occurs.
This is not without problems:
* Raw frame xmit are just dropped, rather than placed on a queue.
The net80211 stack should be the one which queues these frames
rather than the driver.
* It's all very messy. It'd be better if these hardware operations
were serialised on some kind of work queue, rather than hoping
they can be run in parallel.
* The taskqueue block/unblock may occur in parallel with the
newstate() function - which shuts down the taskqueue and restarts
it once the new state is known. It's likely these operations should
be refcounted so the taskqueue is restored once no other areas
in the code wish to suspend operations.
* .. interrupt disable/enable should likely be refcounted as well.
With this work, the driver does not drop frames during stuck beacon
or fatal errors and thus 11n traffic continues to run correctly.
Default and full resets however do still drop frames and it's possible
this may occur, causing traffic loss and session stalls.
Sponsored by: Hobnob, Inc.
2011-11-18 05:06:30 +00:00
|
|
|
}
|
|
|
|
|
2009-03-09 23:10:19 +00:00
|
|
|
callout_schedule(&sc->sc_wd_ch, hz);
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2012-07-20 01:36:46 +00:00
|
|
|
/*
|
|
|
|
* Fetch the rate control statistics for the given node.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_ioctl_ratestats(struct ath_softc *sc, struct ath_rateioctl *rs)
|
|
|
|
{
|
|
|
|
struct ath_node *an;
|
|
|
|
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
/* Perform a lookup on the given node */
|
|
|
|
ni = ieee80211_find_node(&ic->ic_sta, rs->is_u.macaddr);
|
|
|
|
if (ni == NULL) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock the ath_node */
|
|
|
|
an = ATH_NODE(ni);
|
|
|
|
ATH_NODE_LOCK(an);
|
|
|
|
|
|
|
|
/* Fetch the rate control stats for this node */
|
|
|
|
error = ath_rate_fetch_node_stats(sc, an, rs);
|
|
|
|
|
|
|
|
/* No matter what happens here, just drop through */
|
|
|
|
|
|
|
|
/* Unlock the ath_node */
|
|
|
|
ATH_NODE_UNLOCK(an);
|
|
|
|
|
|
|
|
/* Unref the node */
|
|
|
|
ieee80211_node_decref(ni);
|
|
|
|
|
|
|
|
bad:
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2006-04-03 18:14:02 +00:00
|
|
|
#ifdef ATH_DIAGAPI
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Diagnostic interface to the HAL. This is used by various
|
|
|
|
* tools to do things like retrieve register contents for
|
|
|
|
* debugging. The mechanism is intentionally opaque so that
|
|
|
|
* it can change frequently w/o concern for compatiblity.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad)
|
|
|
|
{
|
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
|
|
|
u_int id = ad->ad_id & ATH_DIAG_ID;
|
|
|
|
void *indata = NULL;
|
|
|
|
void *outdata = NULL;
|
|
|
|
u_int32_t insize = ad->ad_in_size;
|
|
|
|
u_int32_t outsize = ad->ad_out_size;
|
|
|
|
int error = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
if (ad->ad_id & ATH_DIAG_IN) {
|
|
|
|
/*
|
|
|
|
* Copy in data.
|
|
|
|
*/
|
|
|
|
indata = malloc(insize, M_TEMP, M_NOWAIT);
|
|
|
|
if (indata == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
error = copyin(ad->ad_in_data, indata, insize);
|
|
|
|
if (error)
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (ad->ad_id & ATH_DIAG_DYN) {
|
|
|
|
/*
|
|
|
|
* Allocate a buffer for the results (otherwise the HAL
|
|
|
|
* returns a pointer to a buffer where we can read the
|
|
|
|
* results). Note that we depend on the HAL leaving this
|
|
|
|
* pointer for us to use below in reclaiming the buffer;
|
|
|
|
* may want to be more defensive.
|
|
|
|
*/
|
|
|
|
outdata = malloc(outsize, M_TEMP, M_NOWAIT);
|
|
|
|
if (outdata == NULL) {
|
|
|
|
error = ENOMEM;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) {
|
|
|
|
if (outsize < ad->ad_out_size)
|
|
|
|
ad->ad_out_size = outsize;
|
|
|
|
if (outdata != NULL)
|
|
|
|
error = copyout(outdata, ad->ad_out_data,
|
|
|
|
ad->ad_out_size);
|
|
|
|
} else {
|
|
|
|
error = EINVAL;
|
|
|
|
}
|
|
|
|
bad:
|
|
|
|
if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
|
|
|
|
free(indata, M_TEMP);
|
|
|
|
if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
|
|
|
|
free(outdata, M_TEMP);
|
|
|
|
return error;
|
|
|
|
}
|
2006-04-03 18:14:02 +00:00
|
|
|
#endif /* ATH_DIAGAPI */
|
2004-12-08 17:34:36 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|
|
|
{
|
|
|
|
#define IS_RUNNING(ifp) \
|
2005-08-09 10:20:02 +00:00
|
|
|
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_softc *sc = ifp->if_softc;
|
2008-04-20 20:35:46 +00:00
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
2008-10-27 17:51:24 +00:00
|
|
|
const HAL_RATE_TABLE *rt;
|
2004-12-08 17:34:36 +00:00
|
|
|
int error = 0;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
switch (cmd) {
|
|
|
|
case SIOCSIFFLAGS:
|
|
|
|
if (IS_RUNNING(ifp)) {
|
|
|
|
/*
|
|
|
|
* To avoid rescanning another access point,
|
|
|
|
* do not call ath_init() here. Instead,
|
|
|
|
* only reflect promisc mode settings.
|
|
|
|
*/
|
2014-03-20 04:47:34 +00:00
|
|
|
ATH_LOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_mode_init(sc);
|
2014-03-20 04:47:34 +00:00
|
|
|
ATH_UNLOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
} else if (ifp->if_flags & IFF_UP) {
|
|
|
|
/*
|
|
|
|
* Beware of being called during attach/detach
|
|
|
|
* to reset promiscuous mode. In that case we
|
|
|
|
* will still be marked UP but not RUNNING.
|
|
|
|
* However trying to re-init the interface
|
|
|
|
* is the wrong thing to do as we've already
|
|
|
|
* torn down much of our state. There's
|
|
|
|
* probably a better way to deal with this.
|
|
|
|
*/
|
2008-04-20 20:35:46 +00:00
|
|
|
if (!sc->sc_invalid)
|
2005-06-10 16:49:24 +00:00
|
|
|
ath_init(sc); /* XXX lose error */
|
2008-05-29 00:10:48 +00:00
|
|
|
} else {
|
2014-03-20 04:47:34 +00:00
|
|
|
ATH_LOCK(sc);
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_stop_locked(ifp);
|
2008-05-29 00:10:48 +00:00
|
|
|
#ifdef notyet
|
|
|
|
/* XXX must wakeup in places like ath_vap_delete */
|
|
|
|
if (!sc->sc_invalid)
|
|
|
|
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
|
|
|
|
#endif
|
2014-03-20 04:47:34 +00:00
|
|
|
ATH_UNLOCK(sc);
|
2008-05-29 00:10:48 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
2008-04-20 20:35:46 +00:00
|
|
|
case SIOCGIFMEDIA:
|
|
|
|
case SIOCSIFMEDIA:
|
|
|
|
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
|
|
|
break;
|
2004-12-08 17:34:36 +00:00
|
|
|
case SIOCGATHSTATS:
|
|
|
|
/* NB: embed these numbers to get a consistent view */
|
|
|
|
sc->sc_stats.ast_tx_packets = ifp->if_opackets;
|
|
|
|
sc->sc_stats.ast_rx_packets = ifp->if_ipackets;
|
2008-10-27 17:51:24 +00:00
|
|
|
sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
|
|
|
|
sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
|
2009-03-30 19:23:49 +00:00
|
|
|
#ifdef IEEE80211_SUPPORT_TDMA
|
2009-01-08 17:12:47 +00:00
|
|
|
sc->sc_stats.ast_tdma_tsfadjp = TDMA_AVG(sc->sc_avgtsfdeltap);
|
|
|
|
sc->sc_stats.ast_tdma_tsfadjm = TDMA_AVG(sc->sc_avgtsfdeltam);
|
|
|
|
#endif
|
2008-10-27 17:51:24 +00:00
|
|
|
rt = sc->sc_currates;
|
2008-10-27 18:22:44 +00:00
|
|
|
sc->sc_stats.ast_tx_rate =
|
|
|
|
rt->info[sc->sc_txrix].dot11Rate &~ IEEE80211_RATE_BASIC;
|
2011-03-22 22:59:09 +00:00
|
|
|
if (rt->info[sc->sc_txrix].phy & IEEE80211_T_HT)
|
|
|
|
sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS;
|
2004-12-08 17:34:36 +00:00
|
|
|
return copyout(&sc->sc_stats,
|
2008-05-01 04:55:00 +00:00
|
|
|
ifr->ifr_data, sizeof (sc->sc_stats));
|
2012-06-10 06:42:18 +00:00
|
|
|
case SIOCGATHAGSTATS:
|
|
|
|
return copyout(&sc->sc_aggr_stats,
|
|
|
|
ifr->ifr_data, sizeof (sc->sc_aggr_stats));
|
2009-02-13 05:38:03 +00:00
|
|
|
case SIOCZATHSTATS:
|
|
|
|
error = priv_check(curthread, PRIV_DRIVER);
|
2012-04-10 07:23:37 +00:00
|
|
|
if (error == 0) {
|
2009-02-13 05:38:03 +00:00
|
|
|
memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
|
2012-04-10 07:27:42 +00:00
|
|
|
memset(&sc->sc_aggr_stats, 0,
|
|
|
|
sizeof(sc->sc_aggr_stats));
|
2012-04-10 07:23:37 +00:00
|
|
|
memset(&sc->sc_intr_stats, 0,
|
|
|
|
sizeof(sc->sc_intr_stats));
|
|
|
|
}
|
2009-02-13 05:38:03 +00:00
|
|
|
break;
|
2006-04-03 18:14:02 +00:00
|
|
|
#ifdef ATH_DIAGAPI
|
2004-12-08 17:34:36 +00:00
|
|
|
case SIOCGATHDIAG:
|
|
|
|
error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
|
|
|
|
break;
|
2011-07-21 14:25:12 +00:00
|
|
|
case SIOCGATHPHYERR:
|
|
|
|
error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr);
|
|
|
|
break;
|
2006-04-03 18:14:02 +00:00
|
|
|
#endif
|
2013-01-02 03:59:02 +00:00
|
|
|
case SIOCGATHSPECTRAL:
|
|
|
|
error = ath_ioctl_spectral(sc,(struct ath_diag*) ifr);
|
|
|
|
break;
|
2012-07-20 01:36:46 +00:00
|
|
|
case SIOCGATHNODERATESTATS:
|
|
|
|
error = ath_ioctl_ratestats(sc, (struct ath_rateioctl *) ifr);
|
|
|
|
break;
|
2008-05-01 04:55:00 +00:00
|
|
|
case SIOCGIFADDR:
|
2008-04-20 20:35:46 +00:00
|
|
|
error = ether_ioctl(ifp, cmd, data);
|
2003-06-23 17:01:19 +00:00
|
|
|
break;
|
2008-05-01 04:55:00 +00:00
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2004-12-08 17:34:36 +00:00
|
|
|
return error;
|
2004-12-31 20:35:05 +00:00
|
|
|
#undef IS_RUNNING
|
2004-12-08 17:34:36 +00:00
|
|
|
}
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2004-12-08 17:34:36 +00:00
|
|
|
/*
|
|
|
|
* Announce various information on device/driver attach.
|
|
|
|
*/
|
2003-06-23 17:01:19 +00:00
|
|
|
static void
|
2004-12-08 17:34:36 +00:00
|
|
|
ath_announce(struct ath_softc *sc)
|
2003-06-23 17:01:19 +00:00
|
|
|
{
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
2004-12-08 17:34:36 +00:00
|
|
|
struct ath_hal *ah = sc->sc_ah;
|
2003-06-23 17:01:19 +00:00
|
|
|
|
2009-02-23 23:41:12 +00:00
|
|
|
if_printf(ifp, "AR%s mac %d.%d RF%s phy %d.%d\n",
|
|
|
|
ath_hal_mac_name(ah), ah->ah_macVersion, ah->ah_macRev,
|
|
|
|
ath_hal_rf_name(ah), ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
|
2011-12-15 00:55:27 +00:00
|
|
|
if_printf(ifp, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n",
|
|
|
|
ah->ah_analog2GhzRev, ah->ah_analog5GhzRev);
|
2004-12-08 17:34:36 +00:00
|
|
|
if (bootverbose) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i <= WME_AC_VO; i++) {
|
|
|
|
struct ath_txq *txq = sc->sc_ac2q[i];
|
|
|
|
if_printf(ifp, "Use hw queue %u for %s traffic\n",
|
|
|
|
txq->axq_qnum, ieee80211_wme_acnames[i]);
|
|
|
|
}
|
|
|
|
if_printf(ifp, "Use hw queue %u for CAB traffic\n",
|
|
|
|
sc->sc_cabq->axq_qnum);
|
|
|
|
if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq);
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2006-02-09 21:03:25 +00:00
|
|
|
if (ath_rxbuf != ATH_RXBUF)
|
|
|
|
if_printf(ifp, "using %u rx buffers\n", ath_rxbuf);
|
|
|
|
if (ath_txbuf != ATH_TXBUF)
|
|
|
|
if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
|
2010-02-08 20:23:20 +00:00
|
|
|
if (sc->sc_mcastkey && bootverbose)
|
|
|
|
if_printf(ifp, "using multicast key search\n");
|
2003-06-23 17:01:19 +00:00
|
|
|
}
|
2009-01-08 17:12:47 +00:00
|
|
|
|
2011-06-01 20:09:49 +00:00
|
|
|
static void
|
|
|
|
ath_dfs_tasklet(void *p, int npending)
|
|
|
|
{
|
|
|
|
struct ath_softc *sc = (struct ath_softc *) p;
|
|
|
|
struct ifnet *ifp = sc->sc_ifp;
|
|
|
|
struct ieee80211com *ic = ifp->if_l2com;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If previous processing has found a radar event,
|
|
|
|
* signal this to the net80211 layer to begin DFS
|
|
|
|
* processing.
|
|
|
|
*/
|
|
|
|
if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) {
|
|
|
|
/* DFS event found, initiate channel change */
|
2012-01-28 21:37:33 +00:00
|
|
|
/*
|
|
|
|
* XXX doesn't currently tell us whether the event
|
|
|
|
* XXX was found in the primary or extension
|
|
|
|
* XXX channel!
|
|
|
|
*/
|
|
|
|
IEEE80211_LOCK(ic);
|
2011-06-01 20:09:49 +00:00
|
|
|
ieee80211_dfs_notify_radar(ic, sc->sc_curchan);
|
2012-01-28 21:37:33 +00:00
|
|
|
IEEE80211_UNLOCK(ic);
|
2011-06-01 20:09:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 23:23:45 +00:00
|
|
|
/*
|
|
|
|
* Enable/disable power save. This must be called with
|
|
|
|
* no TX driver locks currently held, so it should only
|
|
|
|
* be called from the RX path (which doesn't hold any
|
|
|
|
* TX driver locks.)
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_node_powersave(struct ieee80211_node *ni, int enable)
|
|
|
|
{
|
2012-11-07 06:29:45 +00:00
|
|
|
#ifdef ATH_SW_PSQ
|
2012-10-03 23:23:45 +00:00
|
|
|
struct ath_node *an = ATH_NODE(ni);
|
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
|
|
|
|
|
|
|
/* XXX and no TXQ locks should be held here */
|
|
|
|
|
2013-05-13 19:52:35 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE, "%s: %6D: enable=%d\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
!! enable);
|
2012-10-03 23:23:45 +00:00
|
|
|
|
|
|
|
/* Suspend or resume software queue handling */
|
|
|
|
if (enable)
|
|
|
|
ath_tx_node_sleep(sc, an);
|
|
|
|
else
|
|
|
|
ath_tx_node_wakeup(sc, an);
|
|
|
|
|
|
|
|
/* Update net80211 state */
|
|
|
|
avp->av_node_ps(ni, enable);
|
2012-11-07 06:29:45 +00:00
|
|
|
#else
|
|
|
|
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
|
|
|
|
|
|
|
/* Update net80211 state */
|
|
|
|
avp->av_node_ps(ni, enable);
|
|
|
|
#endif/* ATH_SW_PSQ */
|
2012-10-03 23:23:45 +00:00
|
|
|
}
|
|
|
|
|
2012-10-28 21:13:12 +00:00
|
|
|
/*
|
|
|
|
* Notification from net80211 that the powersave queue state has
|
|
|
|
* changed.
|
|
|
|
*
|
|
|
|
* Since the software queue also may have some frames:
|
|
|
|
*
|
|
|
|
* + if the node software queue has frames and the TID state
|
|
|
|
* is 0, we set the TIM;
|
|
|
|
* + if the node and the stack are both empty, we clear the TIM bit.
|
|
|
|
* + If the stack tries to set the bit, always set it.
|
|
|
|
* + If the stack tries to clear the bit, only clear it if the
|
|
|
|
* software queue in question is also cleared.
|
|
|
|
*
|
|
|
|
* TODO: this is called during node teardown; so let's ensure this
|
|
|
|
* is all correctly handled and that the TIM bit is cleared.
|
|
|
|
* It may be that the node flush is called _AFTER_ the net80211
|
|
|
|
* stack clears the TIM.
|
|
|
|
*
|
|
|
|
* Here is the racy part. Since it's possible >1 concurrent,
|
|
|
|
* overlapping TXes will appear complete with a TX completion in
|
|
|
|
* another thread, it's possible that the concurrent TIM calls will
|
|
|
|
* clash. We can't hold the node lock here because setting the
|
|
|
|
* TIM grabs the net80211 comlock and this may cause a LOR.
|
|
|
|
* The solution is either to totally serialise _everything_ at
|
|
|
|
* this point (ie, all TX, completion and any reset/flush go into
|
|
|
|
* one taskqueue) or a new "ath TIM lock" needs to be created that
|
|
|
|
* just wraps the driver state change and this call to avp->av_set_tim().
|
|
|
|
*
|
|
|
|
* The same race exists in the net80211 power save queue handling
|
|
|
|
* as well. Since multiple transmitting threads may queue frames
|
|
|
|
* into the driver, as well as ps-poll and the driver transmitting
|
|
|
|
* frames (and thus clearing the psq), it's quite possible that
|
|
|
|
* a packet entering the PSQ and a ps-poll being handled will
|
|
|
|
* race, causing the TIM to be cleared and not re-set.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ath_node_set_tim(struct ieee80211_node *ni, int enable)
|
|
|
|
{
|
2012-11-07 06:29:45 +00:00
|
|
|
#ifdef ATH_SW_PSQ
|
2012-10-28 21:13:12 +00:00
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
struct ath_node *an = ATH_NODE(ni);
|
|
|
|
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
|
|
|
int changed = 0;
|
|
|
|
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_LOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_stack_psq = enable;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This will get called for all operating modes,
|
|
|
|
* even if avp->av_set_tim is unset.
|
|
|
|
* It's currently set for hostap/ibss modes; but
|
|
|
|
* the same infrastructure is used for both STA
|
|
|
|
* and AP/IBSS node power save.
|
|
|
|
*/
|
|
|
|
if (avp->av_set_tim == NULL) {
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If setting the bit, always set it here.
|
|
|
|
* If clearing the bit, only clear it if the
|
|
|
|
* software queue is also empty.
|
|
|
|
*
|
|
|
|
* If the node has left power save, just clear the TIM
|
|
|
|
* bit regardless of the state of the power save queue.
|
|
|
|
*
|
|
|
|
* XXX TODO: although atomics are used, it's quite possible
|
|
|
|
* that a race will occur between this and setting/clearing
|
|
|
|
* in another thread. TX completion will occur always in
|
|
|
|
* one thread, however setting/clearing the TIM bit can come
|
|
|
|
* from a variety of different process contexts!
|
|
|
|
*/
|
|
|
|
if (enable && an->an_tim_set == 1) {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: enable=%d, tim_set=1, ignoring\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
enable);
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
} else if (enable) {
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: enable=%d, enabling TIM\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
enable);
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_tim_set = 1;
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
changed = avp->av_set_tim(ni, enable);
|
2013-05-13 19:03:12 +00:00
|
|
|
} else if (an->an_swq_depth == 0) {
|
2012-10-28 21:13:12 +00:00
|
|
|
/* disable */
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: enable=%d, an_swq_depth == 0, disabling\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
enable);
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_tim_set = 0;
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
changed = avp->av_set_tim(ni, enable);
|
|
|
|
} else if (! an->an_is_powersave) {
|
|
|
|
/*
|
|
|
|
* disable regardless; the node isn't in powersave now
|
|
|
|
*/
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: enable=%d, an_pwrsave=0, disabling\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
enable);
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_tim_set = 0;
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
changed = avp->av_set_tim(ni, enable);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* psq disable, node is currently in powersave, node
|
|
|
|
* software queue isn't empty, so don't clear the TIM bit
|
|
|
|
* for now.
|
|
|
|
*/
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_UNLOCK(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: enable=%d, an_swq_depth > 0, ignoring\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
enable);
|
2012-10-28 21:13:12 +00:00
|
|
|
changed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (changed);
|
2012-11-07 06:29:45 +00:00
|
|
|
#else
|
|
|
|
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
|
|
|
|
|
2012-11-11 21:58:18 +00:00
|
|
|
/*
|
2012-12-28 21:59:47 +00:00
|
|
|
* Some operating modes don't set av_set_tim(), so don't
|
2012-11-11 21:58:18 +00:00
|
|
|
* update it here.
|
|
|
|
*/
|
|
|
|
if (avp->av_set_tim == NULL)
|
|
|
|
return (0);
|
|
|
|
|
2012-11-07 06:29:45 +00:00
|
|
|
return (avp->av_set_tim(ni, enable));
|
|
|
|
#endif /* ATH_SW_PSQ */
|
2012-10-28 21:13:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set or update the TIM from the software queue.
|
|
|
|
*
|
|
|
|
* Check the software queue depth before attempting to do lock
|
|
|
|
* anything; that avoids trying to obtain the lock. Then,
|
|
|
|
* re-check afterwards to ensure nothing has changed in the
|
|
|
|
* meantime.
|
|
|
|
*
|
|
|
|
* set: This is designed to be called from the TX path, after
|
|
|
|
* a frame has been queued; to see if the swq > 0.
|
|
|
|
*
|
|
|
|
* clear: This is designed to be called from the buffer completion point
|
|
|
|
* (right now it's ath_tx_default_comp()) where the state of
|
|
|
|
* a software queue has changed.
|
|
|
|
*
|
|
|
|
* It makes sense to place it at buffer free / completion rather
|
|
|
|
* than after each software queue operation, as there's no real
|
|
|
|
* point in churning the TIM bit as the last frames in the software
|
|
|
|
* queue are transmitted. If they fail and we retry them, we'd
|
|
|
|
* just be setting the TIM bit again anyway.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni,
|
|
|
|
int enable)
|
|
|
|
{
|
2012-11-07 06:29:45 +00:00
|
|
|
#ifdef ATH_SW_PSQ
|
2012-10-28 21:13:12 +00:00
|
|
|
struct ath_node *an;
|
|
|
|
struct ath_vap *avp;
|
|
|
|
|
|
|
|
/* Don't do this for broadcast/etc frames */
|
|
|
|
if (ni == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
an = ATH_NODE(ni);
|
|
|
|
avp = ATH_VAP(ni->ni_vap);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And for operating modes without the TIM handler set, let's
|
|
|
|
* just skip those.
|
|
|
|
*/
|
|
|
|
if (avp->av_set_tim == NULL)
|
|
|
|
return;
|
|
|
|
|
2013-05-13 18:56:04 +00:00
|
|
|
ATH_TX_LOCK_ASSERT(sc);
|
2012-10-28 21:13:12 +00:00
|
|
|
|
|
|
|
if (enable) {
|
|
|
|
if (an->an_is_powersave &&
|
|
|
|
an->an_tim_set == 0 &&
|
2013-05-13 19:03:12 +00:00
|
|
|
an->an_swq_depth != 0) {
|
2012-10-28 21:13:12 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
2013-05-13 19:52:35 +00:00
|
|
|
"%s: %6D: swq_depth>0, tim_set=0, set!\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":");
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_tim_set = 1;
|
|
|
|
(void) avp->av_set_tim(ni, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Don't bother grabbing the lock unless the queue is empty.
|
|
|
|
*/
|
2013-05-13 19:03:12 +00:00
|
|
|
if (&an->an_swq_depth != 0)
|
2012-10-28 21:13:12 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (an->an_is_powersave &&
|
|
|
|
an->an_stack_psq == 0 &&
|
|
|
|
an->an_tim_set == 1 &&
|
2013-05-13 19:03:12 +00:00
|
|
|
an->an_swq_depth == 0) {
|
2012-10-28 21:13:12 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
"%s: %6D: swq_depth=0, tim_set=1, psq_set=0,"
|
2012-10-28 21:13:12 +00:00
|
|
|
" clear!\n",
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":");
|
2012-10-28 21:13:12 +00:00
|
|
|
an->an_tim_set = 0;
|
|
|
|
(void) avp->av_set_tim(ni, 0);
|
|
|
|
}
|
|
|
|
}
|
2012-11-07 06:29:45 +00:00
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif /* ATH_SW_PSQ */
|
2012-10-28 21:13:12 +00:00
|
|
|
}
|
2012-10-03 23:23:45 +00:00
|
|
|
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
/*
|
|
|
|
* Received a ps-poll frame from net80211.
|
|
|
|
*
|
|
|
|
* Here we get a chance to serve out a software-queued frame ourselves
|
|
|
|
* before we punt it to net80211 to transmit us one itself - either
|
|
|
|
* because there's traffic in the net80211 psq, or a NULL frame to
|
|
|
|
* indicate there's nothing else.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
|
|
|
|
{
|
|
|
|
#ifdef ATH_SW_PSQ
|
|
|
|
struct ath_node *an;
|
|
|
|
struct ath_vap *avp;
|
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
|
|
|
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
|
|
|
int tid;
|
|
|
|
|
|
|
|
/* Just paranoia */
|
|
|
|
if (ni == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unassociated (temporary node) station.
|
|
|
|
*/
|
|
|
|
if (ni->ni_associd == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We do have an active node, so let's begin looking into it.
|
|
|
|
*/
|
|
|
|
an = ATH_NODE(ni);
|
|
|
|
avp = ATH_VAP(ni->ni_vap);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For now, we just call the original ps-poll method.
|
|
|
|
* Once we're ready to flip this on:
|
|
|
|
*
|
|
|
|
* + Set leak to 1, as no matter what we're going to have
|
|
|
|
* to send a frame;
|
|
|
|
* + Check the software queue and if there's something in it,
|
|
|
|
* schedule the highest TID thas has traffic from this node.
|
|
|
|
* Then make sure we schedule the software scheduler to
|
|
|
|
* run so it picks up said frame.
|
|
|
|
*
|
|
|
|
* That way whatever happens, we'll at least send _a_ frame
|
|
|
|
* to the given node.
|
|
|
|
*
|
|
|
|
* Again, yes, it's crappy QoS if the node has multiple
|
|
|
|
* TIDs worth of traffic - but let's get it working first
|
|
|
|
* before we optimise it.
|
|
|
|
*
|
|
|
|
* Also yes, there's definitely latency here - we're not
|
|
|
|
* direct dispatching to the hardware in this path (and
|
|
|
|
* we're likely being called from the packet receive path,
|
|
|
|
* so going back into TX may be a little hairy!) but again
|
|
|
|
* I'd like to get this working first before optimising
|
|
|
|
* turn-around time.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ATH_TX_LOCK(sc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Legacy - we're called and the node isn't asleep.
|
|
|
|
* Immediately punt.
|
|
|
|
*/
|
|
|
|
if (! an->an_is_powersave) {
|
2013-10-17 01:53:07 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
"%s: %6D: not in powersave?\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":");
|
|
|
|
ATH_TX_UNLOCK(sc);
|
|
|
|
avp->av_recv_pspoll(ni, m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We're in powersave.
|
|
|
|
*
|
|
|
|
* Leak a frame.
|
|
|
|
*/
|
|
|
|
an->an_leak_count = 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now, if there's no frames in the node, just punt to
|
|
|
|
* recv_pspoll.
|
|
|
|
*
|
|
|
|
* Don't bother checking if the TIM bit is set, we really
|
|
|
|
* only care if there are any frames here!
|
|
|
|
*/
|
|
|
|
if (an->an_swq_depth == 0) {
|
|
|
|
ATH_TX_UNLOCK(sc);
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
|
|
|
"%s: %6D: SWQ empty; punting to net80211\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":");
|
|
|
|
avp->av_recv_pspoll(ni, m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Ok, let's schedule the highest TID that has traffic
|
|
|
|
* and then schedule something.
|
|
|
|
*/
|
|
|
|
for (tid = IEEE80211_TID_SIZE - 1; tid >= 0; tid--) {
|
|
|
|
struct ath_tid *atid = &an->an_tid[tid];
|
|
|
|
/*
|
|
|
|
* No frames? Skip.
|
|
|
|
*/
|
|
|
|
if (atid->axq_depth == 0)
|
|
|
|
continue;
|
|
|
|
ath_tx_tid_sched(sc, atid);
|
|
|
|
/*
|
|
|
|
* XXX we could do a direct call to the TXQ
|
|
|
|
* scheduler code here to optimise latency
|
|
|
|
* at the expense of a REALLY deep callstack.
|
|
|
|
*/
|
|
|
|
ATH_TX_UNLOCK(sc);
|
|
|
|
taskqueue_enqueue(sc->sc_tq, &sc->sc_txqtask);
|
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
|
|
|
"%s: %6D: leaking frame to TID %d\n",
|
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":",
|
|
|
|
tid);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ATH_TX_UNLOCK(sc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX nothing in the TIDs at this point? Eek.
|
|
|
|
*/
|
2013-10-17 01:53:07 +00:00
|
|
|
DPRINTF(sc, ATH_DEBUG_NODE_PWRSAVE,
|
|
|
|
"%s: %6D: TIDs empty, but ath_node showed traffic?!\n",
|
Implement my first cut at "correct" node power-save and
PS-POLL support.
This implements PS-POLL awareness i nthe
* Implement frame "leaking", which allows for a software queue
to be scheduled even though it's asleep
* Track whether a frame has been leaked or not
* Leak out a single non-AMPDU frame when transmitting aggregates
* Queue BAR frames if the node is asleep
* Direct-dispatch the rest of control and management frames.
This allows for things like re-association to occur (which involves
sending probe req/resp as well as assoc request/response) when
the node is asleep and then tries reassociating.
* Limit how many frames can set in the software node queue whilst
the node is asleep. net80211 is already buffering frames for us
so this is mostly just paranoia.
* Add a PS-POLL method which leaks out a frame if there's something
in the software queue, else it calls net80211's ps-poll routine.
Since the ath PS-POLL routine marks the node as having a single frame
to leak, either a software queued frame would leak, OR the next queued
frame would leak. The next queued frame could be something from the
net80211 power save queue, OR it could be a NULL frame from net80211.
TODO:
* Don't transmit further BAR frames (eg via a timeout) if the node is
currently asleep. Otherwise we may end up exhausting management frames
due to the lots of queued BAR frames.
I may just undo this bit later on and direct-dispatch BAR frames
even if the node is asleep.
* It would be nice to burst out a single A-MPDU frame if both ends
support this. I may end adding a FreeBSD IE soon to negotiate
this power save behaviour.
* I should make STAs timeout of power save mode if they've been in power
save for more than a handful of seconds. This way cards that get
"stuck" in power save mode don't stay there for the "inactivity" timeout
in net80211.
* Move the queue depth check into the driver layer (ath_start / ath_transmit)
rather than doing it in the TX path.
* There could be some naughty corner cases with ps-poll leaking.
Specifically, if net80211 generates a NULL data frame whilst another
transmitter sends a normal data frame out net80211 output / transmit,
we need to ensure that the NULL data frame goes out first.
This is one of those things that should occur inside the VAP/ic TX lock.
Grr, more investigations to do..
Tested:
* STA: AR5416, AR9280
* AP: AR5416, AR9280, AR9160
2013-05-15 18:33:05 +00:00
|
|
|
__func__,
|
|
|
|
ni->ni_macaddr,
|
|
|
|
":");
|
|
|
|
avp->av_recv_pspoll(ni, m);
|
|
|
|
#else
|
|
|
|
avp->av_recv_pspoll(ni, m);
|
|
|
|
#endif /* ATH_SW_PSQ */
|
|
|
|
}
|
|
|
|
|
2011-03-31 08:07:13 +00:00
|
|
|
MODULE_VERSION(if_ath, 1);
|
|
|
|
MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */
|
2012-03-16 23:12:40 +00:00
|
|
|
#if defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ)
|
|
|
|
MODULE_DEPEND(if_ath, alq, 1, 1, 1);
|
|
|
|
#endif
|