522 Commits

Author SHA1 Message Date
Adrian Chadd
bd0edcac7c Since we're now using the ah pointer, always declare it.
This fixes non-DEBUG builds.
2013-05-19 00:53:06 +00:00
Adrian Chadd
9be82a4209 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
Adrian Chadd
f2f6761490 Re-add some code to exclude transmitting if we're in reset.
This fixes some "transmitting during reset" bugs that crept in after
I messed around with this part of the transmit path.
2013-05-18 13:58:07 +00:00
Adrian Chadd
dfaf8de927 Dump out the holding buffer descriptor contents and addresses stopping DMA. 2013-05-16 17:45:01 +00:00
Adrian Chadd
22a3aee637 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
Adrian Chadd
370f81fab6 Add ALQ beacon debugging. 2013-05-13 21:18:00 +00:00
Adrian Chadd
9b48fb4b32 Improve the debugging output - use the MAC address rather than various
pointer values everywhere.
2013-05-13 19:52:35 +00:00
Adrian Chadd
ba83edd45c Since the node state is 100% back under the TX lock, just kill the use
of atomics.

I'll re-think this nonsense later.
2013-05-13 19:03:12 +00:00
Adrian Chadd
4bed2b67ca Begin tidying up the reassociation and node sleep/wakeup paths.
* Move the node sleep/wake state under the TX lock rather than the
  node lock.  Let's leave the node lock protecting rate control only
  for now.

* When reassociating, various state needs to be cleared.  For example,
  the aggregate session needs to be torn down, including any pending
  aggregation negotiation and BAR TX waiting.

* .. and we need to do a "cleanup" pass since frames in the hardware
  TX queue need to be transmitted.

Modify ath_tx_tid_cleanup() to be called with the TX lock held and push
frames into a completion list.  This allows for the cleanup to be
done atomically for all TIDs in a node rather than grabbing and
releasing the TX lock each time.
2013-05-13 18:56:04 +00:00
Adrian Chadd
8328d6e4d4 Make sure the holding descriptor and link pointer are both freed during
a non-loss reset.

When the drain functions are called, the holding descriptor and link pointers
are NULLed out.

But when the processq function is called during a non-loss reset, this
doesn't occur.  So the next time a DMA occurs, it's chained to a descriptor
that no longer exists and the hardware gets angry.

Tested:

* AR5416, STA mode; use sysctl dev.ath.X.forcebstuck=1 to force a non-loss
  reset.

TODO:

* Further AR9380 testing just to check that the behaviour for the EDMA
  chips is sane.

PR:		kern/178477
2013-05-10 10:06:45 +00:00
Adrian Chadd
5e0185081d Fix the holding descriptor logic to actually be "right" (for values
of "right".)

Flip back on the "always continue TX DMA using the holding descriptor"
code - by always setting ATH_BUF_BUSY and never setting axq_link to NULL.

Since the holding descriptor is accessed via txq->axq_link and _that_
is done behind the TXQ lock rather than the TX path lock, the holding
descriptor stuff itself needs to be behind the TXQ lock.

So, do the mental gymnastics needed to do this.

I've not seen any of the hardware failures that I was seeing when
I last tried to do this.

Tested:

* AR5416, STA mode
2013-05-08 21:23:51 +00:00
Adrian Chadd
d3731e4b21 Revert a previous commit - this is causing hardware errors.
I'm not sure why this is failing.  The holding descriptor should be being
re-read when starting DMA of the next frame.  Obviously something here
isn't totally correct.

I'll review the TX queue handling and see if I can figure out why this
is failing.  I'll then re-revert this patch out and use the holding
descriptor again.
2013-05-08 07:30:33 +00:00
Adrian Chadd
7dcb2bea01 Re-work how transmit buffer limits are enforced - partly to fix the PR,
but partly to just tidy up things.

The problem here - there are too many TX buffers in the queue! By the
time one needs to transmit an EAPOL frame (for this PR, it's the response
to the group rekey notification from the AP) there are no ath_buf entries
free and the EAPOL frame doesn't go out.

Now, the problem!

* Enforcing the TX buffer limitation _before_ we dequeue the frame?
  Bad idea. Because..
* .. it means I can't check whether the mbuf has M_EAPOL set.

The solution(s):

* De-queue the frame first
* Don't bother doing the TX buffer minimum free check until after
  we know whether it's an EAPOL frame or not.
* If it's an EAPOL frame, allocate the buffer from the mgmt pool
  rather than the default pool.

Whilst I'm here:

* Add a tweak to limit how many buffers a single node can acquire.
* Don't enforce that for EAPOL frames.
* .. set that to default to 1/4 of the available buffers, or 32,
  whichever is more sane.

This doesn't fix issues due to a sleeping node or a very poor performing
node; but this doesn't make it worse.

Tested:

* AR5416 STA, TX'ing 100+ mbit UDP to an AP, but only 50mbit being received
  (thus the TX queue fills up.)
* .. with CCMP / WPA2 encryption configured
* .. and the group rekey time set to 10 seconds, just to elicit the
  behaviour very quickly.

PR:		kern/138379
2013-05-07 07:52:18 +00:00
Adrian Chadd
4136c09143 The holding buffer logic needs to be used for _all_ transmission, not
just "when the queue is busy."

After talking with the MAC team, it turns out that the linked list
implementation sometimes will not accept a TxDP update and will
instead re-read the link pointer.  So even if the hardware has
finished transmitting a chain and has hit EOL/VEOL, it may still
re-read the link pointer to begin transmitting again.

So, always set ATH_BUF_BUSY on the last buffer in the chain (to
mark the last descriptor as the holding descriptor) and never
blank the axq_link pointer.

Tested:

* AR5416, STA mode

TODO:

* much more thorough testing with the pre-11n NICs, just to verify
  that they behave the same way.
* test TDMA on the 11n and non-11n hardware.
2013-05-04 04:03:50 +00:00
Adrian Chadd
8d06054291 Debugging changes!
* That lock isn't actually held during reset - just the whole TX/RX path
  is paused.  So, remove the assertion.

* Log the TX queue status - how many hardware frames are active in the
  MAC and whether the queue is active.
2013-04-29 07:28:29 +00:00
Adrian Chadd
07187d1109 Conditionally compile this only if ATH_DEBUG is defined. 2013-04-26 22:22:38 +00:00
Adrian Chadd
ed261a611b Dump the entire TXQ descriptor contents during a reset, rather than only
completed descriptors.
2013-04-26 21:51:17 +00:00
Adrian Chadd
ff5b563430 Initialise the chainmask fields regardless of whether 11n support
is compiled in or not.

This fixes issues with people running -HEAD but who build modules
without doing a "make buildkernel KERNCONF=XXX", thus picking up
opt_*.h.  The resulting module wouldn't have 11n enabled and the
chainmask configuration would just be plain wrong.
2013-04-19 21:49:11 +00:00
Adrian Chadd
7904f51655 Add a debug statement to log the currently chosen chainmask configuration. 2013-04-19 08:06:45 +00:00
Adrian Chadd
b0bf95ff15 .. don't know how this snuck into this commit. Sorry.
Fix compile build before anyone notices.
2013-04-19 08:01:34 +00:00
Adrian Chadd
b661bd2e52 Print out the chainmask configuration. 2013-04-19 07:56:22 +00:00
Adrian Chadd
6f4fb2d8e6 Use uint32_t for fields that are fetched via ath_hal_getcapability(). 2013-04-19 06:59:10 +00:00
Adrian Chadd
5d4dedadb6 Use a per-RX-queue deferred list, rather than a single deferred list for
both queues.

Since ath_rx_pkt() does multi-mbuf frame recombining based on the RX queue,
this needs to occur.

Tested:

* AR9380 (XB112), hostap mode
2013-04-16 20:21:02 +00:00
Adrian Chadd
6961e9eda4 Always enable TXOK interrupts when setting up TX queues for EDMA NICs. 2013-04-11 22:02:35 +00:00
Adrian Chadd
a91ab3c099 Some TX dmamap cleanups.
* Don't use BUS_DMA_ALLOCNOW for descriptor DMA maps; we never use
  bounce buffers for the descriptors themselves.

* Add some XXX's to mark where the ath_buf has its mbuf ripped from
  underneath it without actually cleaning up the dmamap.  I haven't
  audited those particular code paths to see if the DMA map is guaranteed
  to be setup there; I'll do that later.

* Print out a warning if the descdma tidyup code is given some descriptors
  w/ maps to free.  Ideally the owner will free the mbufs and unmap
  the descriptors before freeing the descriptor/ath_buf pairs, but
  right now that's not guaranteed to be done.

Reviewed by:	scottl (BUS_DMA_ALLOCNOW tag)
2013-04-02 06:24:22 +00:00
Adrian Chadd
3f3a5dbd2c Ensure that we only call the busdma unmap/flush routines once, when
the buffer is being freed.

* When buffers are cloned, the original mapping isn't copied but it
  wasn't freeing the mapping until later.  To be safe, free the
  mapping when the buffer is cloned.

* ath_freebuf() now no longer calls the busdma sync/unmap routines.

* ath_tx_freebuf() now calls sync/unmap.

* Call sync first, before calling unmap.

Tested:

* AR5416, STA mode
2013-04-01 20:57:13 +00:00
Adrian Chadd
587feafb5a Remove an un-needed comment. 2013-04-01 20:44:21 +00:00
Adrian Chadd
09067b6e9a Use ATH_MAX_SCATTER rather than ATH_TXDESC.
ATH_MAX_SCATTER is used to size the ath_buf DMA segment array.
We thus should use it when checking sizes of things.
2013-04-01 20:12:21 +00:00
Adrian Chadd
3feffbd796 Add per-TXQ EDMA FIFO staging queue support.
Each set of frames pushed into a FIFO is represented by a list of
ath_bufs - the first ath_buf in the FIFO list is marked with
ATH_BUF_FIFOPTR; the last ath_buf in the FIFO list is marked with
ATH_BUF_FIFOEND.

Multiple lists of frames are just glued together in the TAILQ as per
normal - except that at the end of a FIFO list, the descriptor link
pointer will be NULL and it'll be tagged with ATH_BUF_FIFOEND.

For non-EDMA chipsets this is a no-op - the ath_txq frame list (axq_q)
stays the same and is treated the same.

For EDMA chipsets the frames are pushed into axq_q and then when
the FIFO is to be (re) filled, frames will be moved onto the FIFO
queue and then pushed into the FIFO.

So:

* Add a new queue in each hardware TXQ (ath_txq) for staging FIFO frame
  lists.  It's a TAILQ (like the normal hardware frame queue) rather than
  the ath9k list-of-lists to represent FIFO entries.

* Add new ath_buf flags - ATH_TX_FIFOPTR and ATH_TX_FIFOEND.

* When allocating ath_buf entries, clear out the flag value before
  returning it or it'll end up having stale flags.

* When cloning ath_buf entries, only clone ATH_BUF_MGMT.  Don't clone
  the FIFO related flags.

* Extend ath_tx_draintxq() to first drain the FIFO staging queue, _then_
  drain the normal hardware queue.

Tested:

* AR9280, hostap
* AR9280, STA
* AR9380/AR9580 - hostap

TODO:

* Test on other chipsets, just to be thorough.
2013-03-26 19:46:51 +00:00
Adrian Chadd
b837332d0a 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
Adrian Chadd
f0db652cf6 Break out the RX completion path into "FIFO check / refill" and
"complete RX frames."

The 128 entry RX FIFO is really easy to fill up and miss refilling
when it's done in the ath taskq - as that gets blocked up doing
RX completion, TX completion and other random things.

So the 128 entry RX FIFO now gets emptied and refilled in the ath_intr()
task (and it grabs / releases locks, so now ath_intr() can't just be
a FAST handler yet!) but the locks aren't held for very long. The
completion part is done in the ath taskqueue context.

Details:

* Create a new completed frame list - sc->sc_rx_rxlist;
* Split the EDMA RX process queue into two halves - one that
  processes the RX FIFO and refills it with new frames; another
  that completes the completed frame list;
* When tearing down the driver, flush whatever is in the deferred
  queue as well as what's in the FIFO;
* Create two new RX methods - one that processes all RX queues,
  one that processes the given RX queue.  When MSI is implemented,
  we get told which RX queue the interrupt came in on so we can
  specifically schedule that.  (And I can do that with the non-MSI
  path too; I'll figure that out later.)
* Convert the legacy code over to use these new RX methods;
* Replace all the instances of the RX taskqueue enqueue with a call
  to a relevant RX method to enqueue one or all RX queues.

Tested:

* AR9380, STA
* AR9580, STA
* AR5413, STA
2013-03-19 19:32:28 +00:00
Adrian Chadd
5f2f0e616b Add locking around the new holdingbf code.
Since this is being done during buffer free, it's a crap shoot whether
the TX path lock is held or not.  I tried putting the ath_freebuf() code
inside the TX lock and I got all kinds of locking issues - it turns out
that the buffer free path sometimes is called with the lock held and
sometimes isn't. So I'll go and fix that soon.

Hence for now the holdingbf buffers are protected by the TXBUF lock.
2013-03-15 02:52:37 +00:00
Adrian Chadd
629ce2188a 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
Adrian Chadd
9d2a962bf3 Print out the queue flags during a TX DMA shutdown. 2013-03-09 06:11:58 +00:00
Adrian Chadd
6606ba811c Add in the STBC TX/RX capability support into the HAL and driver.
The HAL already included the STBC fields; it just needed to be exposed
to the driver and net80211 stack.

This should allow single-stream STBC TX and RX to be negotiated; however
the driver and rate control code currently don't do anything with it.
2013-02-27 00:25:44 +00:00
Adrian Chadd
6322256b83 Part #2 of the TX chainmask changes:
* Remove ar5416UpdateChainmasks();
* Remove the TX chainmask override code from the ar5416 TX descriptor
  setup routines;
* Write a driver method to calculate the current chainmask based on the
  operating mode and update the driver state;
* Call the HAL chainmask method before calling ath_hal_reset();
* Use the currently configured chainmask in the TX descriptors rather than
  the hardware TX chainmasks.

Tested:

* AR5416, STA/AP mode - legacy and 11n modes
2013-02-25 22:45:02 +00:00
Adrian Chadd
ce597531f2 Disable debugging entries about BAW issues. I haven't seen any issues
to do with BAW tracking in the last 9 months or so.
2013-02-21 21:47:35 +00:00
Adrian Chadd
a54ecf784a Add an option to allow the minimum number of delimiters to be tweaked.
This is primarily for debugging purposes.

Tested:

* AR5416, STA mode
2013-02-21 06:38:49 +00:00
Adrian Chadd
4a502c332a Add a new option to limit the maximum size of aggregates.
The default is to limit them to what the hardware is capable of.

Add sysctl twiddles for both the non-RTS and RTS protected aggregate
generation.

Whilst here, add some comments about stuff that I've discovered during
my exploration of the TX aggregate / delimiter setup path from the
reference driver.
2013-02-21 06:18:40 +00:00
Adrian Chadd
69930f8794 Enable TX FIFO underrun interrupts. This allows the TX FIFO threshold
adjustment code to now run.

Tested:

* AR5416, STA

TODO:

* Much more thorough testing on the other chips, AR5210 -> AR9287
2013-02-20 11:20:51 +00:00
Adrian Chadd
bab336db27 oops, tab! 2013-02-20 11:17:29 +00:00
Adrian Chadd
a26f33276f Post interrupts in the ath alq trace. 2013-02-20 11:17:03 +00:00
Adrian Chadd
158cb431db CFG_ERR, DATA_UNDERRUN and DELIM_UNDERRUN are all flags, rather than
part of ts_status. Thus:

* make sure we decode them from ts_flags, rather than ts_status;
* make sure we decode them regardless of whether there's an error or not.

This correctly exposes descriptor configuration errors, TX delimiter
underruns and TX data underruns.
2013-02-20 11:14:55 +00:00
Adrian Chadd
1a85141ad4 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
Adrian Chadd
a40880ade4 Go back to direct-dispatch of the software queue and frame TX paths
when they're being called from the TX completion handler.

Going (back) through the taskqueue is just adding extra locking and
latency to packet operations.  This improves performance a little bit
on most NICs.

It still hasn't restored the original performance of the AR5416 NIC
but the AR9160, AR9280 and later NICs behave very well with this.

Tested:

* AR5416 STA (still tops out at ~ 70mbit TCP, rather than 150mbit TCP..)
* AR9160 hostap (good for both TX and RX)
* AR9280 hostap (good for both TX and RX)
2013-02-11 07:48:26 +00:00
Adrian Chadd
1b3502e5a1 Create a new TX lock specifically for queuing frames.
This now separates out the act of queuing frames from the act of running
TX and TX completion.
2013-02-07 07:50:16 +00:00
Adrian Chadd
21bca442b9 Methodize the process of adding the software TX queue to the taskqueue.
Move it (for now) to the TX taskqueue.
2013-02-07 02:15:25 +00:00
Adrian Chadd
f28a552089 Migrate the TX sending code out from under the ath0 taskq and into
the separate ath0 TX taskq.

Whilst here, make sure that the TX software scheduler is also
running out of the TX task, rather than the ath0 taskqueue.

Make sure that the tx taskqueue is blocked/unblocked as necessary.

This allows for a little more parallelism on multi-core machines,
as well as (eventually) supporting a higher task priority for TX
tasks, allowing said TX task to preempt an already running RX or
TX completion task.

Tested:

* AR5416, AR9280 hostap and STA modes
2013-01-26 00:14:34 +00:00
Adrian Chadd
a74ebfe59e 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
Adrian Chadd
c5239edb98 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