Commit Graph

145 Commits

Author SHA1 Message Date
Adrian Chadd
0eb8162623 Pause and unpause the software queues for a given node based on the
net80211 node power save state.

* Add an ATH_NODE_UNLOCK_ASSERT() check
* Add a new node field - an_is_powersave
* Pause/unpause the queue based on the node state
* Attempt to handle net80211 concurrency issues so the queue
  doesn't get paused/unpaused more than once at a time from
  the net80211 power save code.

Whilst here (and breaking my usual rule), set CLRDMASK when a queue
is unpaused, regardless of whether the queue has some pending traffic.
This means the first frame from that TID (now or later) will hvae
CLRDMASK set.

Also whilst here, bump the swretrymax counters whenever the
filtered frames code expires a frame.  Again, breaking my rule, but
this is just a statistics thing rather than a functional change.

This doesn't fix ps-poll (but it doesn't break it too much worse
than it is at the present) or correcting the TID updates.
That's next on the list.

Tested:
	* AR9220 AP (Atheros AP96 reference design)
	* Macbook Pro and LG Optimus 1 Android phone, both setting
	  and clearing power save state (but not using PS-POLL.)
2012-10-03 23:23:45 +00:00
Adrian Chadd
7403d1b9b2 Map the non-QoS TID to the voice queue, in order to ensure important
things like EAPOL frames make it out.

After a whole bunch of hacking/testing, I discovered that they weren't
being early-dropped by the stack (but I should look at ensuring that
later..) but were even making to the hardware transmit queue.
They were mostly even being received by the remote end.  However, the
remote end was completely ignoring them.

This didn't happen under 150-170MBit TCP tests as I'm guessing the TX
queue stayed very busy and the STA didn't do any scanning. However, when
doing 100Mbit/s of TCP traffic, the STA would do background scanning -
which involves it coming in and out of powersave mode with the AP.

Now, this is a total and utter hack around the real problems, which are:

* I need to implement proper power save handling and integrate it into
  the filtered frames support, so the driver/stack doesn't send frames
  whilst the station is actually in sleep;

* .. but frames were actually making it to the STA (macbook pro) and
  the AP did receive an ACK; but a tcpdump on the receiving side showed
  the EAPOL frame never made it. So the stack was dropping it for
  some reason;

* Importantly - the EAPOL frames are currently going into the non-QoS
  TID, which maps to the BE queue and is susceptible to that queue being
  busy doing other things, but;

* There's other traffic going on in the non-QoS TID from other contexts
  when scanning is going on and it's possible there's some races causing
  sequence number/IV issues, but;

* Importantly importantlly, I think the interaction with TID 16 multicast
  traffic in power save mode is causing issues - since I -believe- the
  sequence number space being used by the EAPOL frames on TID 16 overlaps
  with the multicast frames that have sequence numbers allocated and
  are then stuffed on the cabq.  Since with EAPOL frames being in TID 16
  and queued to the BE queue, it's going to be waiting to be serviced
  with all of the aggregate traffic going on - and if the CABQ gets
  emptied beforehand, those TID 16 multicast frames with sequence numbers
  will go out beforehand.

Now, there's quite likely a bunch of "stuff happening slightly out of
sequence" going on due to the nature of the TX path (read: lots of
overlapping and concurrent ath_start() and ath_raw_xmit() calls going
on, sigh) but I thought I had caught them all and stuffed each TID TX
behind a lock (that lasted as long as it needed to in order to get
the frame onto the relevant destination queue - thus keeping things
in order.)

Unfortunately the last problem is the big one and I'm going to stare at
it some more.  If it _is_

So this is a work around for now to ensure that EAPOL frames actually
make it out before any other stuff in the non-QoS TID and HOPEFULLY
before the CABQ gets active.

I'm now going to spend a little time in the TX path figuring out exactly
why the sender is rejecting things. There's two (well, three if you count
EAPOL contents invalid) possibilities:

* The sequence number is out of order (ie, something else like the multicast
  traffic on CABQ) is going out first on TID 16;
* The CCMP IV is out of order (similar to above - but less likely,  as the
  TX key for multicast traffic is different to unicast traffic);
* EAPOL contents strangely invalid.

AP: Ubiquiti RSPRO, AR9160/AR9220 NICs
STA: Macbook Pro, Broadcom 11n NIC
2012-09-26 03:45:42 +00:00
Adrian Chadd
0a54471901 Oops - don't do the clrdmask check in ath_tx_xmit_normal() - the wrong
lock may be held.

Kim reported that the TID lock wasn't held when ath_tx_update_clrdmask()
was called. Well, the underlying hardware TXQ for that TID.

I'm betting it's the cabq stuff. ath_tx_xmit_normal() can be called
for both real and software cabq.  For software cabq, the real destination
txq is different to the txq. So, the lock check will fail.

Reported by:	Kim Culhan <w8hdkim@gmail.com>
2012-09-25 20:41:43 +00:00
Adrian Chadd
23f44d2b30 Call ath_tx_tid_unsched() after the node has been flushed, so the
state can be printed correctly.
2012-09-25 05:56:59 +00:00
Adrian Chadd
0368251456 Migrate the ath(4) KTR logging to use an ATH_KTR() macro.
This should eventually be unified with ATH_DEBUG() so I can get both
from one macro; that may take some time.

Add some new probes for TX and TX completion.
2012-09-24 20:35:56 +00:00
Adrian Chadd
0c54de88e6 Prepare for software retransmission of non-aggregate frames but ensure
it's disabled.

The previous commit to enable CLRDMASK setting didn't do it at all
correctly for non-aggregate sessions - so the CLRDMASK bit would be
cleared and never re-set.

* move ath_tx_update_clrdmask() to be called by functions that setup
  descriptors and queue frames to the hardware, rather than scattered
  everywhere.

* Force CLRDMASK to be set on all non-aggregate session frames being
  transmitted.

* Use ath_tx_normal_comp() now on non-aggregate sessoin frames
  that are queued via ath_tx_xmit_normal().  That way the TID hwq is
  updated and they can trigger (eventual) filter frame queue resets
  and software retransmits.

There's still a bit more work to do in this area to reverse the silly
short-sightedness on my part, however it's likely going to be better
to fix this now than just reverting the patch.

Thanks to people on the freebsd-wireless@ mailing list for promptly
pointing this out.
2012-09-24 06:42:20 +00:00
Adrian Chadd
94eefcf1dc In (eventual) preparation for supporting disabling the whole 11n/software
retry path - add some code to make it obvious (to me!) how to disable
the software tx path.
2012-09-24 06:00:51 +00:00
Adrian Chadd
4e81f27c59 Introduce the CLRDMASK gating based on tid->clrdmask, enabling filtered
frames to occur.

* Create a new function which will set the bf_flags CLRDMASK bit
  if required.
* For raw frames, always set CLRDMASK.
* For BAR, ADDBA frames, always set CLRDMASK.
* For everything else, check if CLRDMASK needs to be set before
  calling tx_setds() or tx_setds11n().
* When unpausing a queue or drain/resetting it, set tid->clrdmask=1
  just to ensure traffic starts flowing.

What I need to do:

* Modify that function to _clear_ the CLRDMASK if it's not required,
  or retried frames may have CLRDMASK set when they don't need to.
  (Which isn't a huge deal, but..)

Whilst I'm here:

* ath_tx_normal_xmit() should really act like the AMPDU session TX
  functions - any incomplete frames will end up being assigned
  ath_tx_normal_comp() which will decrement tid->hwq_depth - but that
  won't have been incremented.

  So whilst I'm here, add a comment to do that.

* Fix the debug print function to be slightly clearer about things;
  it's not a good sign when I can't interpret my own debugging output.

I've done some testing on AR9280/AR5416/AR9160 STA and AP modes.
2012-09-20 03:13:20 +00:00
Adrian Chadd
d05b576d61 Place the comment where it should be. 2012-09-20 03:04:19 +00:00
Adrian Chadd
088d8b81f3 Add a work-around for some strange net80211 BAR races in the wireless
stack.

There are unfortunately quite a few odd cases in BAR TX and BAR TX
retransmission that I haven't yet fully diagnosed.  So for now, add
this work-around so the resume() function isn't called too often,
decrementing pause to -1 (and causing things to stay paused.)
2012-09-20 03:03:01 +00:00
Adrian Chadd
0aa5c1bbf5 Oops - take a copy of ath_tx_status from the buffer before the TX processing
is done.

The aggregate path was definitely accessing 'ts' before it was actually
being assigned.

This had the side effect of over-filtering frames, since occasionally that
bit would be '1'.

Whilst here, do the same thing in the non-aggregate completion function -
as calling the filter function may also invalidate bf.

Pointy hat to: adrian, for not noticing this over many, many code reviews.
2012-09-18 20:33:04 +00:00
Adrian Chadd
f1bc738ece Implement my first cut at filtered frames in aggregation sessions.
The hardware can optionally "filter" frames if successive transmissions
to a given node (ie, "entry in the keycache") fail.  That way the hardware
can implement a kind of early abort of all the other frames queued to
that destination, rather than simply trying to TX each frame to that
destination (and failing.)

The background:

* If a frame comes back as being filtered, the hardware didn't try to
  TX it (or it was outside the TX burst opportunity.) So, take it as a hint
  that some (but not all, see below) frames to the destination may be
  filtered.

* If the CLRDMASK bit is set in a TX descriptor, the "filter to this
  destination" bit in the keycache entry is cleared and TX to that host
  will be unconditionally retried.

* Right now everything has the CLRDMASK bit set, so filtered frames
  tend to be aggregates and frames that fall outside of the WME burst
  window. It was a bit worse in the past as I had messed up the TX
  flags and CLRDMASK wasn't being set on aggregate frames.

The annoying bits:

* It's easy (ish) to do for aggregate session frames - firstly, they
  can be retried in any order as long as they're within the BAW, and
  there's already a bunch of infrastructure tracking how many frames
  the TID has queued to the hardware (tid->hwq_depth.) However, for
  frames that bypassed the software queue, hwq_depth doesn't get
  incremented. I'll fix that in a subsequent commit.

* For non-aggregate session frames, the only retries that can occur
  are ones for sequence numbers that hvaen't successfully been TXed yet.
  Since there's no re-ordering going on in non-aggregate sessions, if any
  subsequent seqno frames make it out, any filtered frames before that
  seqno need to be dropped.

  Hence why this initially is just for aggregate session frames.

* Since there may be intermediary frames to the destination that
  have CLRDMASK set - for example, any directly dispatched management
  frames to that destination - it's possible that there will be some
  filtered frames followed up by some non filtered frames.  Thus,
  it can't be assumed that once you see a filtered frame for the given
  destination node, all subsequent frames for all TIDs will be filtered.

Ok, with that in mind:

* Create a per-TID filtered frame queue for frames that the hardware
  returns as filtered.

* Track filtered frames per-tid, rather than per-node.  It just makes
  the locking much easier.

* When a filtered frame appears in the completion function, the node
  transitions to "filtered", and all subsequent completed error frames
  (filtered or otherwise) are put on the filtered frame queue.  The TID
  is paused once (during the transition from non-filtered to filtered).

* If a filtered frame retry count exceeds SWMAX_RETRIES, a BAR should be
  sent.

* Once all the frames queued to the hardware for the given filtered frame
  TID, transition back from filtered frame to non-filtered frame, which
  means pre-pending all the filtered frames onto the head of the software
  queue, clearing the filtered frame state and unpausing the TID.

Things get quite hairy around handling completion (aggr, non-aggr, norm,
direct-dispatched frames to a hardware queue); whether it's an "error",
"cleanup" or "BAR" state as well as filtered, which order to do things
in (eg do filtered BEFORE checking for BAR, as the filter completion
may be needed to actually transmit a BAR frame.)

This work has definitely reminded me that I have to tidy up all the locking
and remove some of the ridiculous lock/unlock/lock/unlock going on in the
completion functions.

It's also reminded me that I should really split out TID versus hardware TXQ
locking, even if the underlying locking is still the destination hardware TXQ.

Finally, this is all pre-requisite for working on AP mode power save support
(PS-POLL, uAPSD) as well as improving performance to misbehaving nodes (as
they can transition into filter mode, stopping any TX until everything has
caught up.)

Finally (ish) - this should also be done for non-aggregate sessions as
there are still plenty of laptops and mobile devices that don't speak
802.11n but do wish for stable, useful power save AP support where packets
aren't simply dropped.  This requires software retransmission for
non-aggregate sessions to be implemented, which includes the caveats I've
mentioned above.

Finally finally - this doesn't yet do anything about the CLRDMASK bit in the
TX descriptor.  That's still unconditionally set to 1.  I'll debug the
current work (mostly ensuring I haven't busted up the hairy transitions
between BAR, filtered, error (all frames in an aggregate failing) and
cleanup (when transitioning from aggregation -> non-aggregation.))

Finally finally finally - this is all original work by yours truely, rather
than ported from the Atheros internal driver codebase or Linux ath9k.

Tested:
 * AR9280, AR5416 in STA mode
 * AR9280, AR9130 in hostap mode
 * Lots and lots of iperf testing in very marginal and non-marginal conditions,
   complete with inducing filtered frames + BAR TX conditions.
2012-09-18 10:14:17 +00:00
Adrian Chadd
c6e9cee205 Take credit for the work I've done in this source file. 2012-09-17 03:17:42 +00:00
Adrian Chadd
5d9b19f731 Clear the correct descriptor when going through the chained together
gather DMA descriptor list.

Pointy hat to: adrian@, for even USING bf->bf_desc here instead of 'ds'.
2012-09-11 04:11:42 +00:00
Adrian Chadd
21840808c8 Make sure the aggregate fields are properly cleared - both in the
ath_buf and when forming a non-aggregate frame.

The non-11n setds function is called when TXing aggregate frames (and
yes, I should fix this!) and the non-11n TX aggregation code doesn't clear
the delimiter field.  I figure it's nicer to do that.
2012-09-09 05:06:16 +00:00
Adrian Chadd
2a9f83af64 Ensure that single-frame aggregate session frames are retransmitted
with the correct configuration.

Occasionally an aggregate TX would fail and the first frame would be
retransmitted as a non-AMPDU frame.  Since bfs_aggr=1 and bfs_nframes > 1
(from the previous AMPDU attempt), the aggr completion function would be
called and be very confused about what's going on.

Noticed by:	Kim <w8hdkim@gmail.com>
PR:		kern/171394
2012-09-07 00:24:27 +00:00
Adrian Chadd
79b5235666 Fix a build issue when ATH_DEBUG isn't defined - just initialise and use
qnum.
2012-08-20 18:57:41 +00:00
Adrian Chadd
0f8423a27a Wrap debugging in #ifdef ATH_DEBUG 2012-08-20 15:30:26 +00:00
Adrian Chadd
42083b3d66 Advance the descriptor pointer by sc->sc_tx_desclen bytes, rather than
sizeof(struct ath_desc).  This isn't correct for EDMA TX descriptors.

This popped up during iperf tests. Ping tests never created frames that
had enough segments to overflow into a second descriptor.  However,
an iperf TCP test would do that after a few seconds; the second descriptor
would almost always certainly have garbage.

Tested:

* AR9380, STA mode
* AR9280, STA mode (802.11n TX, legacy TX)
2012-08-20 06:02:09 +00:00
Adrian Chadd
e2137b86d6 When assembling the descriptor list, make sure that the "first" descriptor
is marked correctly.

The existing logic assumed that the first descriptor is i == 0, which
doesn't hold for EDMA TX.  In this instance, the first time filltxdesc()
is called can be up to i == 3.

So for a two-buffer descriptor:

* firstSeg is set to 0;
* lastSeg is set to 1;
* the ath_hal_filltxdesc() code will treat it as the last segment in
  a descriptor chain and blank some of the descriptor fields, causing
  the TX to stop.

When firstSeg is set to 1 (regardless of lastSeg), it overrides the
lastSeg setting.  Thus, ath_hal_filltxdesc() won't blank out these
fields.

Tested: AR9380, STA mode.  With this, association is successful.
2012-08-19 02:16:22 +00:00
Adrian Chadd
2b200bb4ce Extend the non-aggregate TX descriptor chain routine to be aware of:
* the descriptor ID, and
* the multi-buffer support that the EDMA chips support.

This is required for successful MAC transmission of multi-descriptor
frames.  The MAC simply hangs if there are NULL buffers + 0 length pointers,
but the descriptor did have TxMore set.

This won't be done for the 11n aggregate path, as that will be modified
to use the newer API (ie, ath_hal_filltxdesc() and then set first|middle|
last_aggr), which will deprecate some of the current code.

TODO:

* Populate the numTxMaps field in the HAL, then make sure that's fetched
  by the driver.  Then I can undo that hack.

Tested:

* AR9380, AP mode, TX'ing non-aggregate 802.11n frames;
* AR9280, STA/AP mode, doing aggregate and non-aggregate traffic.
2012-08-15 08:14:16 +00:00
Adrian Chadd
1762ec944a Revert the ath_tx_draintxq() method, and instead teach it the minimum
necessary to "do" EDMA.

It was just using the TX completion status for logging information about
the descriptor completion.  Since with EDMA we don't know this without
checking the TX completion FIFO, we can't provide this information.
So don't.
2012-08-12 00:46:15 +00:00
Adrian Chadd
788e6aa99c Break out ath_draintxq() into a method and un-methodize ath_tx_processq().
Now that I understand what's going on with this, I've realised that
it's going to be quite difficult to implement a processq method in
the EDMA case.  Because there's a separate TX status FIFO, I can't
just run processq() on each EDMA TXQ to see what's finished.
i have to actually run the TX status queue and handle individual
TXQs.

So:

* unmethodize ath_tx_processq();
* leave ath_tx_draintxq() as a method, as it only uses the completion status
  for debugging rather than actively completing the frames (ie, all frames
  here are failed);
* Methodize ath_draintxq().

The EDMA ath_draintxq() will have to take care of running the TX
completion FIFO before (potentially) freeing frames in the queue.

The only two places where ath_tx_draintxq() (on a single TXQ) are used:

* ath_draintxq(); and
* the CABQ handling in the beacon setup code - it drains the CABQ before
  populating the CABQ with frames for a new beacon (when doing multi-VAP
  operation.)

So it's quite possible that once I methodize the CABQ and beacon handling,
I can just drop ath_tx_draintxq() in its entirety.

Finally, it's also quite possible that I can remove ath_tx_draintxq()
in the future and just "teach" it to not check the status when doing
EDMA.
2012-08-12 00:37:29 +00:00
Adrian Chadd
4ddf2cc38c Add the AR9300 HAL ID in to the 11n check routine.
I was having TX hang issues, which I root caused to having the
legacy ath_hal_setupxtxdesc() called, rather than the 11n rate scenario
setup code.  This meant that rate control information wasn't being
put into frames, causing the MAC to stall/hang.
2012-08-11 22:25:28 +00:00
Adrian Chadd
d2da554492 Correct re-initialise the link pointer to be the final descriptor in
the last buffer.

This fixes traffic stalls that were occuring with stuck beacon events.

PR:		kern/170433
2012-08-07 00:42:46 +00:00
Adrian Chadd
fffbec8618 Migrate the 802.11n ath_hal_chaintxdesc() API to use a buffer/segment
array, similar to what filltxdesc() uses.

This removes the last reference to ds_data in the TX path outside of
debugging statements.  These need to be adjusted/fixed.

Tested:

* AR9280 STA/AP with iperf TCP traffic
2012-08-05 11:24:21 +00:00
Adrian Chadd
46634305f4 Migrate the ath_hal_filltxdesc() API to take a list of buffer/seglen values.
The existing API only exposes 'seglen' (the current buffer (segment) length)
with the data buffer pointer set in 'ds_data'.  This is fine for the legacy
DMA engine but it won't work for the EDMA engines.

The EDMA engine has a significantly different TX descriptor layout.

* The legacy DMA engine had a ds_data pointer at the same offset in the
  descriptor for both TX and RX buffers;
* The EDMA engine has no ds_data for RX - the data is DMAed after the
  descriptor;
* The EDMA engine has support for 4 TX buffer/segment pairs in the TX
  DMA descriptor;
* The EDMA TX completion is in a different FIFO, and the driver will
  'link' the status completion entry to a QCU by a "QCU ID".
  I don't know why it's just not filled in by the hardware, alas.

So given that, here are the changes:

* Instead of directly fondling 'ds_data' in ath_desc, change the
  ath_hal_filltxdesc() to take an array of buffer pointers as well
  as segment len pointers;
* The EDMA TX completion status wants a descriptor and queue id.
  This (for now) uses bf_state.bfs_txq and will extract the hardware QCU
  ID from that.
* .. and this is ugly and wasteful; it should change to just store
  the QCU in the bf_state and save 3/7 bytes in the process.

Now, the weird crap:

* The aggregate TX path was using bf_state->bfs_txq for the TXQ, rather than
  taking a function argument.  I've tidied that up.
* The multicast queue frames get put on a software TXQ and then that is
  appended to the hardware CABQ when appropriate.  So for now, make sure
  that bf_state->bfs_txq points at the CABQ when adding frames to the
  multicast queue.
* .. but the multicast queue TX path for now doesn't use the software
  queue and instead
  (a) directly sets up the descriptor contents at that point;
  (b) the frames on the vap->avp_mcastq are then just appended wholesale
      to the CABQ.
  So for now, I don't have to worry about making the multicast path
  work with aggregation or the per-TID software queue. Phew.

What's left to do:

* I need to modify the 11n ath_hal_chaintxdesc() API to do the same.
  I'll do that in a subsequent commit.
* Remove bf_state.bfs_txq entirely and store the QCU as appropriate.
* .. then do the runtime "is this going on the right HWQ?" checks using
  that, rather than comparing pointer values.

Tested on:

* AR9280 STA/AP
* AR5416 STA/AP
2012-08-05 10:12:27 +00:00
Adrian Chadd
a6e829596d Fix an issue that crept in with the previous descriptor tidyup.
When forming aggregates, the last descriptor was now not being
correctly setup - instead, the "setuplasttxdesc" call was being
handed the first descriptor in the last subframe, rather than the
last descriptor in the last subframe.

This showed up as "bad series0 hwrate" messages, as the final
descriptor just didn't have any of the rate control information
squirreled away.

Tested:
	* AR9280 STA -> 11n AP, iperf TCP
2012-08-02 20:14:45 +00:00
Adrian Chadd
af01710118 Allow 802.11n hardware to support multi-rate retry when RTS/CTS is
enabled.

The legacy (pre-802.11n) hardware doesn't support this - although
the AR5212 era hardware supports MRR, it doesn't have all the bits
needed to support MRR + RTS/CTS.  The AR5416 and later support
a packet duration and RTS/CTS flags per rate scenario, so we should
support it.

Tested:

* AR9280, STA

PR:		kern/170302
2012-07-31 23:54:15 +00:00
Adrian Chadd
8c08c07ac4 Shuffle the call to ath_hal_setuplasttxdesc() to _after_ the rate control
code is called and remove it from ath_buf_set_rate().

For the legacy (non-11n API) TX routines, ath_hal_filltxdesc() takes care
of setting up the intermediary and final descriptors right, complete
with copying the rate control info into the final descriptor so the
rate modules can grab it.

The 11n version doesn't do this - ath_hal_chaintxdesc() doesn't
copy the rate control bits over, nor does it clear isaggr/moreaggr/
pad delimiters.  So the call to setuplasttxdesc() is needed here.

So:

* legacy NICs - never call the 11n rate control stuff, so filltxdesc
  copies the rate control info right;
* 11n NICs transmitting legacy or 11n non-aggregate frames -
  ath_hal_set11nratescenario() is called to setup rate control and
  then ath_hal_filltxdesc() chains them together - so the rate control
  info is right;
* 11n aggregate frames - set11nratescenario() is called, then
  ath_hal_chaintxdesc() is called to chain a list of aggregate and subframes
  together. This requires a call to ath_hal_setuplasttxdesc() to complete
  things.

Tested:

* AR9280 in station mode

TODO:

* I really should make sure that the descriptor contents get blanked
  out correctly or garbage left over from aggregate frames may show
  up in non-aggregate frames, leading to badness.
2012-07-31 17:08:29 +00:00
Adrian Chadd
d34a73472a Push the rate control and descriptor chaining into the descriptor "set"
functions, for both legacy and 802.11n.

This will simplify supporting the EDMA chipsets as these two descriptor
setup functions can just be overridden in their entirety, hiding all of
the subtle differences in setting things up.

It's not a permanent solution, as eventually the AR5416 HAL should grow
similar versions of the 11n descriptor functions and then those can be
used.

TODO:

* Push the "clr11naggr" call into the legacy setds, just to ensure
  that retried frames don't end up with the aggregate bits set
  inappropriately;
* Remove the "setlasttxdesc" call from the 11n TX path and push it
  into setds_11n.
* Ensure that setds_11n will work correctly for non-aggregate frames;
* .. and then when it does, just unconditionally call "setds_11n" for
  11n NICs and "setds" for non-11n NICs.
2012-07-31 16:41:09 +00:00
Adrian Chadd
f8418db57e Migrate some more TX side setup routines to be methods. 2012-07-31 03:09:48 +00:00
Adrian Chadd
746bab5b7f Break out the hardware handoff and TX DMA restart code into methods.
These (and a few others) will differ based on the underlying DMA
implementation.

For the EDMA NICs, simply stub them out in a fashion which will let
me focus on implementing the necessary descriptor API changes.
2012-07-31 02:28:32 +00:00
Adrian Chadd
0f4a46b376 Shuffle the rate control call to be consistent with non-aggregate TX.
The correct ordering for non-aggregate TX is:

* call ath_hal_setuptxdesc() to setup the first TX descriptor complete
  with the first TX rate/try count;
* call ath_hal_setupxtxdesc() to setup the multi-rate retry;
* .. or for 802.11n NICs, call ath_hal_set11nratescenario() for MRR and
  802.11n flags;
* then call ath_hal_filltxdesc() to setup intermediary descriptors
  in a multi-descriptor single frame.

The call to ath_hal_filltxdesc() routines seem to correctly (consistently?)
handle the intermediary descriptor flags, including copying the rate
control information to the final descriptor in the frame.  That's used
by the rate control module rather than the hardware.

Tested:

* Only on AR9280 STA mode, however it should work on other chips in
  both STA and AP mode.
2012-07-29 09:23:32 +00:00
Adrian Chadd
1006fc0c3b Modify ath_descdma_setup() to take a descriptor size parameter.
The AR9300 and later descriptors are 128 bytes, however I'd like to make
sure that isn't used for earlier chips.

* Populate the TX descriptor length field in the softc with
  sizeof(ath_desc)

* Use this field when allocating the TX descriptors

* Pre-AR93xx TX/RX descriptors will use the ath_desc size; newer ones will
  query the HAL for these sizes.
2012-07-23 23:40:13 +00:00
Adrian Chadd
3fdfc33024 Begin separating out the TX DMA setup in preparation for TX EDMA support.
* Introduce TX DMA setup/teardown methods, mirroring what's done in
  the RX path.

  Although the TX DMA descriptor is setup via ath_desc_alloc() /
  ath_desc_free(), there TX status descriptor ring will be allocated
  in this path.

* Remove some of the TX EDMA capability probing from the RX path and
  push it into the new TX EDMA path.
2012-07-23 03:52:18 +00:00
Adrian Chadd
3d9b15965e Begin modifying the descriptor allocation functions to support a variable
sized TX descriptor.

This is required for the AR93xx EDMA support which requires 128 byte
TX descriptors (which is significantly larger than the earlier
hardware.)
2012-07-23 02:26:33 +00:00
Adrian Chadd
bb06995571 Convert the TX path to use the new HAL methods for accessing the
TX descriptor link pointers.

This is required for the AR93xx and later chipsets.

The RX path is slightly different - the legacy RX path directly
accesses ath_desc->ds_link for now, however this isn't at all done
for EDMA (FIFO) RX.

Now, for those performing a little software archeology here:

This is all a bit sub-optimal. "struct ath_desc" is only really relevant
for the pre-AR93xx NICs - where ds_link and ds_data is always in the
same location.

The AR93xx and later NICs have different descriptor layouts altogether.

Now, for AR93xx and later NICs, you should never directly reference
ds_link and ds_data, as:

* the RX descriptors don't have either - the data is _after_ the RX
  descriptor.  They're just one large buffer.  There's also no need for
  a per-descriptor RX buffer size as they're all fixed sizes.

* the TX descriptors have 4 buffer and 4 length fields _and_ a link
  pointer.  Each frame takes up one TX FIFO pointer, but it can contain
  multiple subframes (either multiple frames in a buffer, and/or
  multiple frames in an aggregate/RIFS burst.)

* .. so, when TX frames are queued to a hardware queue, the link
  pointer is ONLY for buffers in that frame/aggregate.  The next frame
  starts in a new FIFO pointer.

* Finally, descriptor completion status is in a different ring.
  I'll write something up about that when its time to do so.

This was inspired by Linux ath9k and the reference driver but is a
reimplementation.

Obtained from:	Linux ath9k, Qualcomm Atheros
2012-07-19 03:51:16 +00:00
John Baldwin
0f078d635e Fix build when ATH_DEBUG is not defined. 2012-07-10 18:57:05 +00:00
Adrian Chadd
6abbbae5d3 Print the TX buffer if this error condition is asserted.
I need to figure out why this is occuring.  Hopefully I can get enough
descriptor dumps to figure it out.
2012-07-10 06:10:49 +00:00
Adrian Chadd
8405fe8662 Make sure the BAR TX session pause is correctly unpaused when a node
is reassociating.

PR:		kern/169432
2012-06-26 07:56:15 +00:00
Adrian Chadd
447fd44a6f Disable this warning debug for now, as I'm now aware of the particular
situation where it's occuring.

Whilst I'm here, flesh out a more descriptive description.
2012-06-14 04:01:25 +00:00
Adrian Chadd
af33d486ab Implement a separate, smaller pool of ath_buf entries for use by management
traffic.

* Create sc_mgmt_txbuf and sc_mgmt_txdesc, initialise/free them appropriately.
* Create an enum to represent buffer types in the API.
* Extend ath_getbuf() and _ath_getbuf_locked() to take the above enum.
* Right now anything sent via ic_raw_xmit() allocates via ATH_BUFTYPE_MGMT.
  This may not be very useful.
* Add ATH_BUF_MGMT flag (ath_buf.bf_flags) which indicates the current buffer
  is a mgmt buffer and should go back onto the mgmt free list.
* Extend 'txagg' to include debugging output for both normal and mgmt txbufs.
* When checking/clearing ATH_BUF_BUSY, do it on both TX pools.

Tested:

* STA mode, with heavy UDP injection via iperf.  This filled the TX queue
  however BARs were still going out successfully.

TODO:

* Initialise the mgmt buffers with ATH_BUF_MGMT and then ensure the right
  type is being allocated and freed on the appropriate list.  That'd save
  a write operation (to bf->bf_flags) on each buffer alloc/free.

* Test on AP mode, ensure that BAR TX and probe responses go out nicely
  when the main TX queue is filled (eg with paused traffic to a TID,
  awaiting a BAR to complete.)

PR:		kern/168170
2012-06-13 06:57:55 +00:00
Adrian Chadd
32c387f76a Oops, return the newly allocated buffer to the queue, not the completed
buffer.

PR:	kern/168170
2012-06-13 05:41:00 +00:00
Adrian Chadd
e1a50456b6 Replace the direct sc_txbuf manipulation with a pair of functions.
This is preparation work for having a separate ath_buf queue for
management traffic.

PR:		kern/168170
2012-06-13 05:39:16 +00:00
Adrian Chadd
c7c073413b Fix uninitialised reference.
Noticed by:	John Hay <jhay@meraka.org.za>
2012-06-11 12:26:23 +00:00
Adrian Chadd
7561cb5c8b Wrap the whole (software) TX path from ifnet dequeue to software queue
(or direct dispatch) behind the TXQ lock (which, remember, is doubling
as the TID lock too for now.)

This ensures that:

 (a) the sequence number and the CCMP PN allocation is done together;
 (b) overlapping transmit paths don't interleave frames, so we don't
     end up with the original issue that triggered kern/166190.

     Ie, that we don't end up with seqno A, B in thread 1, C, D in
     thread 2, and they being queued to the software queue as "A C D B"
     or similar, leading to the BAW stalls.

This has been tested:

* both STA and AP modes with INVARIANTS and WITNESS;
* TCP and UDP TX;
* both STA->AP and AP->STA.

STA is a Routerstation Pro (single CPU MIPS) and the AP is a dual-core
Centrino.

PR:		kern/166190
2012-06-11 07:44:16 +00:00
Adrian Chadd
4b6db4043f Add another TID lock. 2012-06-11 07:35:24 +00:00
Adrian Chadd
ba0e58f4fa Make sure the frames are queued to the head of the list, not the tail.
See previous commit.

PR:		kern/166190
2012-06-11 07:31:50 +00:00
Adrian Chadd
39f24578fb When scheduling frames in an aggregate session, the frames should be
scheduled from the head of the software queue rather than trying to
queue the newly given frame.

This leads to some rather unfortunate out of order (but still valid
as it's inside the BAW) frame TX.

This now:

* Always queues the frame at the end of the software queue;
* Tries to direct dispatch the frame at the head of the software queue,
  to try and fill up the hardware queue.

TODO:

* I should likely try to queue as many frames to the hardware as I can
  at this point, rather than doing one at a time;
* ath_tx_xmit_aggr() may fail and this code assumes that it'll schedule
  the TID.  Otherwise TX may stall.

PR:		kern/166190
2012-06-11 07:29:25 +00:00
Adrian Chadd
4547f047ba Retried frames need to be inserted in the head of the list, not the tail.
This is an unfortunate byproduct of how the routine is used - it's called
with the head frame on the queue, but if the frame is failed, it's inserted
into the tail of the queue.

Because of this, the sequence numbers would get all shuffled around and
the BAW would be bumped past this sequence number, that's now at the
end of the software queue.  Then, whenever it's time for that frame
to be transmitted, it'll be immediately outside of the BAW and TX will
stall until the BAW catches up.

It can also result in all kinds of weird duplicate BAW frames, leading
to hilarious panics.

PR:		kern/166190
2012-06-11 07:15:48 +00:00
Adrian Chadd
42f4d0618a Finish undoing the previous commit - this part of the code is no longer
required.

PR:		kern/166190
2012-06-11 07:08:40 +00:00
Adrian Chadd
c2ac9655c3 Introduce a new lock debug which is specifically for making sure the
_TID_ lock is held.

For now the TID lock is also the TXQ lock. This is just to make sure
that the right TXQ lock is held for the given TID.
2012-06-11 07:06:49 +00:00
Adrian Chadd
a108d2d6c6 Revert r233227 and followup commits as it breaks CCMP PN replay detection.
This showed up when doing heavy UDP throughput on SMP machines.

The problem with this is because the 802.11 sequence number is being
allocated separately to the CCMP PN replay number (which is assigned
during ieee80211_crypto_encap()).

Under significant throughput (200+ MBps) the TX path would be stressed
enough that frame TX/retry would force sequence number and PN allocation
to be out of order.  So once the frames were reordered via 802.11 seqnos,
the CCMP PN would be far out of order, causing most frames to be discarded
by the receiver.

I've fixed this in some local work by being forced to:

  (a) deal with the issues that lead to the parallel TX causing out of
      order sequence numbers in the first place;
  (b) fix all the packet queuing issues which lead to strange (but mostly
      valid) TX.

I'll begin fixing these in a subsequent commit or five.

PR:		kern/166190
2012-06-11 06:59:28 +00:00
Adrian Chadd
b815538dec Avoid using hard-coded numbers here. 2012-05-26 01:35:11 +00:00
Adrian Chadd
d3a6425b7c Fix up some corner cases with aggregation handling.
I've come across a weird scenario in net80211 where two TX streams will
happily attempt to setup an aggregation session together.
If we're very lucky, it happens concurrently on separate CPUs and the
total lack of locking in the net80211 aggregation code causes this stuff
to race. Badly.

So >1 call would occur to the ath(4) addba start, but only one call would
complete to addba complete or timeout.  The TID would thus stay paused.

The real fix is to implement some proper per-node (or maybe per-TID)
locking in net80211, which then could be leveraged by the ath(4) TX
aggregation code.

Whilst I'm at it, shuffle around the debugging messages a bit.
I like to keep people on their toes.
2012-05-22 06:31:03 +00:00
Adrian Chadd
6deb7f3271 For now, add a quick debugging patch to log when the hw TXQ != the TID/AC. 2012-05-21 22:43:38 +00:00
Adrian Chadd
4dfd450768 Rename ath_tx_cleanup() -> ath_tx_tid_cleanup() in order to not clash
with a symbol in if_ath.c
2012-05-21 22:39:13 +00:00
Adrian Chadd
e60c4fc2c9 Migrate the bulk of the RX routines out from if_ath.c to if_ath_rx.[ch].
* migrate the rx processing out into if_ath_rx.c
* migrate the TSF functions into if_ath_tsf.h, as inlines

This is in prepration for supporting the EDMA RX routines, required to
support the AR93xx series NICs.

TODO:

* ath_start() shouldn't be private, but it's called as part of
  the RX path. I should likely migrate ath_rx_tasklet() back into
  if_ath.c and then return this to be 'static'.  The RX code really
  shouldn't need to see TX routines (and vice versa.)

* ath_beacon_* should be in if_ath_beacon.[ch].

* ath_tdma_* should be in if_ath_tdma.[ch] ...
2012-05-20 02:05:10 +00:00
Adrian Chadd
0e22ed0eb2 Migrate ath_debug and sc_debug from an int to a uint64_t / QUAD;
add some more BAR debugging logic.

* Change the definition of ath_debug and ath_softc.sc_debug  from
  int to uint64_t;
* Change the relevant sysctls;
* Add a new BAR TX debugging field;
* Use this in if_ath_tx.

This has been tested by using the sysctl program, which happily allows
for fields > 32 bits to be configured.
2012-05-15 23:39:37 +00:00
Adrian Chadd
e9a6408e07 Handle non-xretry errors the same as xretry errors for now.
Although I _should_ handle the other errors in various ways (specifically
errors like FILT), treating them as having transmitted successfully
is completely wrong.  Here, they'd be counted as successful and the BAW
would be advanced.. but the RX side wouldn't have received them.

The specific errors I've been seeing here are HAL_TXERR_FILT.

This patch does fix the issue - I've tested it using -i 0.001 pings
(enough to start aggregation) and now the behaviour is correct:

* The RX side never sees a "moved window" error, and
* The TX side sends BARs as needed, with the RX side correctly handling
  them.

PR:		kern/167902
2012-05-15 04:55:15 +00:00
Adrian Chadd
96ff26ff5d Fix a couple of sc_ac2q[] mappings that were using the TID, not the AC.
PR:		kern/167588
2012-05-04 20:31:27 +00:00
Adrian Chadd
39da9d42bd Remove some of the redundant locking done in the TX completion path,
when checking whether BAR frames need to be checked.
2012-04-26 23:57:24 +00:00
Adrian Chadd
2aa563dfeb Migrate the net80211 TX aggregation state to be from per-AC to per-TID.
TODO:

* Test mwl(4) more thoroughly!

Reviewed by:	bschmidt (for iwn)
2012-04-15 20:29:39 +00:00
Adrian Chadd
b43facbff3 After reviewing the mcast/sleep station code a little, undo some brain
damage which I committed when I had less clue about such things.

Don't ever put normal data frames on the mcast software queue.
Just put mcast frames there if needed.

Pass the txq decision into ath_tx_normal_setup(), as we've already made
the decision.  Don't re-do it.

Whilst i'm here, add another random debugging statement.
2012-04-08 00:40:16 +00:00
Adrian Chadd
4d7f883711 Do a dma sync before the descriptors are chained together.
I need to find a better place to do this..
2012-04-07 05:51:43 +00:00
Adrian Chadd
e2e4a2c2a1 Break out the legacy duration and protection code into routines,
call these after rate control selection is done.

The duration/protection code wasn't working - it expected the rix to
be valid.  Unfortunately after I moved the rate control selection into
late in the process, the rix value isn't valid and thus the protection/
duration code would get things wrong.

HT frames are now correctly protected with an RTS and for the AR5416,
this involves having the aggregate frames be limited to 8K.

TODO:

* Fix up the DMA sync to occur just before the frame is queued to the
  hardware.  I'm adjusting the duration here but not doing the DMA
  flush.

* Doubly/triply ensure that the aggregate frames are being limited to
  the correct size, or the AR5416 will get unhappy when TXing RTS-protected
  aggregates.
2012-04-07 05:48:26 +00:00
Adrian Chadd
875a9451d9 Remove duplicate txflags field from ath_buf.
rename bf_state.bfs_flags to bf_state.bfs_txflags, as that is what
it effectively is.
2012-04-07 02:01:26 +00:00
Adrian Chadd
88b3d48316 Implement BAR TX.
A BAR frame must be transmitted when an frame in an A-MPDU session fails
to transmit - it's retried too often, or it can't be cloned for
re-transmission.  The BAR frame tells the remote side to advance the
left edge of the block-ack window (BAW) to a new value.

In order to do this:

* TX for that particular node/TID must be paused;
* The existing frames in the hardware queue needs to be completed, whether
  they're TXed successfully or otherwise;
* The new left edge of the BAW is then communicated to the remote side
  via a BAR frame;
* Once the BAR frame has been sucessfully TXed, aggregation can resume;
* If the BAR frame can't be successfully TXed, the aggregation session
  is torn down.

This is a first pass that implements the above.  What needs to be done/
tested:

* What happens during say, a channel reset / stuck beacon _and_ BAR
  TX.  It _should_ be correctly buffered and retried once the
  reset has completed.  But if a bgscan occurs (and they shouldn't,
  grr) the BAR frame will be forcibly failed and the aggregation session
  will be torn down.

  Yes, another reason to disable bgscan until I've figured this out.

* There's way too much locking going on here.  I'm going to do a couple
  of further passes of sanitising and refactoring so the (re) locking
  isn't so heavy.  Right now I'm going for correctness, not speed.

* The BAR TX can fail if the hardware TX queue is full.  Since there's
  no "free" space kept for management frames, a full TX queue (from eg
  an iperf test) can race with your ability to allocate ath_buf/mbufs
  and cause issues.  I'll knock this on the head with a subsequent
  commit.

* I need to do some _much_ more thorough testing in hostap mode to ensure
  that many concurrent traffic streams to different end nodes are correctly
  handled.  I'll find and squish whichever bugs show up here.

But, this is an important step to being able to flip on 802.11n by default.
The last issue (besides bug fixes, of course) is HT frame protection and
I'll address that in a subsequent commit.
2012-04-04 23:45:15 +00:00
Adrian Chadd
d743debcbf Now that I've fixed the BAW TX hangs, disable this verbose debugging
again.
2012-04-04 22:22:50 +00:00
Adrian Chadd
33d340324a Correctly handle AR_MoreAggr when assembling multi-descriptor final frames.
Linux ath9k doesn't have this issue as it doesn't try queuing multi-
descriptor frames to the hardware.

Before, I was only setting the first and last descriptor in the final
frame correctly - and that was done by accident. The first descriptor in
the last sub-frame was being correctly updated by ath_tx_setds_11n();
the last descriptor in the last sub-frame was being correctly updated
by ath_buf_set_rate(). But both of those are "incorrect".

The correct behaviour is:

* AR_IsAggr is set for all descriptors for all subframes in an aggregate.
* AR_MoreAggr is set for all descriptors for all non-final sub-frames
  in an aggregate.

Ie, all descriptors in the last sub-frame of an aggregate must have this
field set to 0.

I still need to do a couple of extra passes to ensure the pad delimiter
field is being correctly handled in all descriptors in the last sub-frame.
2012-04-04 21:49:49 +00:00
Adrian Chadd
03e9308f0a Defer the rescheduling of TID -> TXQ frames in some instances.
Right now ath_txq_sched() is mainly called from the TX ath_tx_processq()
routine, which is (mostly) done as part of the taskqueue.  It shouldn't
be called outside the taskqueue.

But now that I'm about to flip back on BAR TX, I'm going to start
stressing the ath_tx_tid_pause() and ath_tx_tid_resume() paths.
What I don't want to have happen is a reschedule of the TID traffic
_during_ the completion of TX frames.

Ideally I'd like to have a way to flag back up to the processing code
that the current hardware queue should be rechecked for software TID
queue frames.  But for now, this should suffice for the BAR TX case.

I may eventually delete this code once I've brought some further
sanity to the general TX queue/completion path.
2012-03-29 17:39:18 +00:00
Adrian Chadd
091e146cf6 Use the assigned sequence number when checking if a retried packet is
within the BAW.

This regression was introduced in ane earlier commit by me to fix the
BAW seqno allocation-but-not-insertion-into-BAW race.  Since it was only
ever using the to-be allocated sequence number, any frame retries
with the first frame in the BAW still in the software queue would
have constantly failed, as ni_txseqs[tid] would always be outside
the BAW.

TODO:

* Extract out the mostly common code here in the agg and non-agg ADDBA
  case and stuff it into a single function.

PR:		kern/166357
2012-03-26 16:05:19 +00:00
Adrian Chadd
0f04c5a211 Add some more debugging to try and nail down exactly what's going on when
I see traffic stalls.

It turns out that the bug isn't because the first and last frame in the
BAW is in the software queue.  It is more likely that it's because
the first frame in the BAW is still in the software queue and thus there's
no more room to allocate and do subsequent TX.

PR:		kern/166357
2012-03-25 23:50:34 +00:00
Adrian Chadd
12be5b9c59 Add some further debugging to try and aid tracking down what the state of
things were just before a full software queue is drained.
2012-03-22 21:48:36 +00:00
Adrian Chadd
0b96ef630b Delay sequence number allocation for A-MPDU until just before the frame
is queued to the hardware.

Because multiple concurrent paths can execute ath_start(), multiple
concurrent paths can push frames into the software/hardware TX queue
and since preemption/interrupting can occur, there's the possibility
that a gap in time will occur between allocating the sequence number
and queuing it to the hardware.

Because of this, it's possible that a thread will have allocated a
sequence number and then be preempted by another thread doing the same.
If the second thread sneaks the frame into the BAW, the (earlier) sequence
number of the first frame will be now outside the BAW and will result
in the frame being constantly re-added to the tail of the queue.
There it will live until the sequence numbers cycle around again.

This also creates a hole in the RX BAW tracking which can also cause
issues.

This patch delays the sequence number allocation to occur only just before
the frame is going to be added to the BAW.  I've been wanting to do this
anyway as part of a general code tidyup but I've not gotten around to it.
This fixes the PR.

However, it still makes it quite difficult to try and ensure in-order
queuing and dequeuing of frames. Since multiple copies of ath_start()
can be run at the same time (eg one TXing process thread, one TX completion
task/one RX task) the driver may end up having frames dequeued and pushed
into the hardware slightly/occasionally out of order.

And, to make matters more annoying, net80211 may have the same behaviour -
in the non-aggregation case, the TX code allocates sequence numbers
before it's thrown to the driver.  I'll open another PR to investigate
this and potentially introduce some kind of final-pass TX serialisation
before frames are thrown to the hardware.  It's also very likely worthwhile
adding some debugging code into ath(4) and net80211 to catch when/if this
does occur.

PR:		kern/166190
2012-03-20 04:50:25 +00:00
Adrian Chadd
b09e37a185 Fix a panic introduced in a previous commit - non-beaconing modes (eg STA)
don't setup the avp mcast queue.

This is a bit annoying though - it turns out the mcast queue isn't
initialised for STA mode but it's then touched to see whether anything
is in it.  That should be fixed in a subsequent commit.

Noticed by:	gperez@entel.upc.edu
PR:		kern/165895
2012-03-10 19:58:23 +00:00
Adrian Chadd
9c85ff9164 Don't flood the cabq/mcastq with frames.
In a very noisy 2.4GHz environment (with HT/40 enabled, making it worse)
I saw the following occur:

* the air was considered "busy" a lot of the time;
* the cabq time is quite short due to staggered beacons being enabled;
* it just wasn't able to keep up TX'ing CABQ frames;
* .. and the cabq would swallow up all the TX ath_buf's.

This patch introduces a twiddle which allows the maximum cabq depth to be
set, forcing further frames to be dropped.

It defaults to the TX buffer count at the moment, so the default behaviour
isn't changed.

I've also started fleshing out a similar setup for the data path, so
it doesn't swallow up all the available TX buffers and preventing management
frames (such as ADDBA) out.

PR:		kern/165895
2012-03-10 04:14:04 +00:00
Adrian Chadd
c5940c30a7 Document that we may end up with some suboptimal handling of data
frames with stations in power saving mode.

I'm not (yet) sure how to handle TX'ing aggregates frames to stations
that are in power saving mode, or whether that's even a feasible thing
to do. So in order to (mostly) not forget, leave a couple of comments
in the code.

The code presently assumes that the aggregation TID state for an ath_node
is locked not by the ath_node lock or a node+TID lock, but behind the
hardware queue said TID maps to.  This assumption is going to be
incorrect for stations in power saving mode as we'll be TX'ing frames
on the multicast queue.

In any case, I'm afraid its a "later problem". :/
2012-03-09 22:58:34 +00:00
Adrian Chadd
b1f3262c73 Correctly initialise the TXQ link pointer to the last descriptor in
the last buffer in the list.

The current behaviour (due to me, so pointy hat is firmly on my head here)
was incorrect - it was setting the link pointer to the last descriptor
of the _first_ buffer in the TXQ.  Instead, it should have set it to the
last descriptor in the _last_ buffer in the TXQ.

This showed up as occasional TX stalls with frames in the TXQ but no
TX progress being made.  Further inspection showed the TXQ looked like
it contained multiple "lists" of frames - there'd be a list of correct
frames, then a NULL link pointer, but there'd be a next buffer in the
list.

Since this code is only called upon an interface reset, it's likely
this only began showing up when I started doing stress testing
in environments which annoy the radios enough to cause lockups.

I've not yet any TX stalls with this patch applied.

PR:		kern/165866
2012-03-08 23:53:38 +00:00
Adrian Chadd
d4365d165b style(9) changes. This shouldn't change functionality. 2012-01-11 00:16:44 +00:00
Adrian Chadd
c0711b9756 If frames are dumped out of the queue, let's at least see what they are.
This shows that the majority of the weird traffic I see here are probe
frames that haven't been sent out, but I can also trigger this condition
by doing ICMP w/ -i 0.3 - enough to trigger the TX during actual scanning,
but not fast enough to stop scanning from occuring.

PR:		kern/163689
2012-01-01 01:08:51 +00:00
Adrian Chadd
2d3d4776cd Flesh out the TX aggregation completion statistics.
* Failall is now named just that.
* Add TX ok and TX fail, for aggregate frame sub-frames.

This will break athstats; a followup commit wil resolve this.

Sponsored by:	Hobnob, Inc.
2011-11-23 05:00:25 +00:00
Adrian Chadd
ef27340c5b 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
Adrian Chadd
38962489b3 If software retransmit occurs with an ath_buf marked ATH_BUF_BUSY,
it's cloned and that clone is retransmitted. This means that the
ath_buf pointer squirreled away on the baw window array is suddenly
wrong and was causing all kinds of console output.

This updates the pointer in that particular BAW slot to the new
ath_buf after ensuring that:

* the new and old buffers have the same seqno;
* the current slot pointer matches the old buffer pointer.

This quietens the debugging output (again), restoring said debugging
to only signify when a broken condition has occured.

Sponsored by:	Hobnob, Inc.
2011-11-09 18:24:20 +00:00
Adrian Chadd
eb6f0de09d 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
Adrian Chadd
6edf1dc729 Change the descriptor logic to use bf_lastds to point to the last
descriptor, rather than using the maths involving bf_desc[bf_nseg - 1].

When doing TX aggregation, the status will be updated in the -final-
descriptor of the -final- subframe in an aggregate. Thus bf_lastds
may point to the last descriptor in a completely different ath_buf.

Sponsored by:	Hobnob, Inc.
2011-11-08 21:25:36 +00:00
Adrian Chadd
6b349e5a86 Migrate the STAILQ lists to TAILQs.
A bunch of the 11n TX aggregation logic wants to traverse lists of buffers
in various ways. In order to provide O(1) behaviour in this instance,
use TAILQs.

This does blow out the memory footprint and CPU cycles slightly for some
of these operations. I may convert some of these back to STAILQs once
the rest of the software transmit queue handling has been stabilised.

Sponsored by:	Hobnob, Inc.
2011-11-08 17:08:12 +00:00
Adrian Chadd
4f545a2c3d Add in HT protection but disable it by default.
I'll clear how it's supposed to work with Bernhard and then look
at enabling this in the correct situations.

But this -does- enable HT RTS protection (using the appropriate legacy
rates) if this bit of code is enabled.
2011-03-28 11:48:49 +00:00
Adrian Chadd
e42b5dba51 Shuffle around the RTS/CTS rate/duration logic.
* Turn ath_tx_calc_ctsduration() into a function that
  returns the ctsduration, or -1 for HT rates;
* add a printf() to ath_tx_calc_ctsduration() which will be
  very loud if somehow that function is called with an MCS
  rate;
* Add ath_tx_get_rtscts_rate() which returns the RTS/CTS
  rate to use for the given data rate, incl. the short
  preamble flag;
* Only call ath_tx_calc_ctsduration() for non-11n chipsets;
  11n chipsets don't require the rtscts duration to be
  calculated.
2011-02-22 00:37:53 +00:00
Adrian Chadd
bf26df3693 The current code used the fields in ath_set11nratescenario() . Use them
correctly:

* pass in whether to allow the hardware to override the duration field
  in the main data frame (durupdate_en) - PS_POLL frames in particular
  don't have the duration bit overriden;
* there's no rts/cts duration here; that's done elsehwere
2011-02-12 02:14:19 +00:00
Adrian Chadd
c1782ce034 Modify the TX path to set and use the 11n rate scenario bits.
This isn't strictly required to TX (at least non-agg and non-HT40,
non-short-GI) frames; but as it needs to be done anyway, just get
it done.

Linux ath9k uses the rate scenario style path for -all- packets,
legacy or otherwise. This code does much the same.

Beacon TX still uses the legacy, non-rate-scenario TX descriptor
setup. Ath9k also does this.

This 11n rate scenario path is only called for chips in the AR5416
HAL; legacy chips use the previous interface for TX'ing.
2011-02-03 20:30:17 +00:00
Adrian Chadd
79f02dbfed Refator the common code which calculates the 802.11g protection duration. 2011-02-01 07:50:26 +00:00
Adrian Chadd
81a826882a * Add a rather hacky "does this speak the 11n TX descriptor format"
function; which will be later used by the TX path to determine
  whether to use the extended features or not.

* Break out the descriptor chaining logic into a separate function;
  again so it can be switched out later on for the 11n version when
  needed.

* Refactor out the encryption-swizzling code that's common in the
  raw and normal TX path.
2011-02-01 06:59:44 +00:00
Adrian Chadd
b8e788a53a Migrate the TX path code out of if_ath and into a separate source file.
There's two reasons for this:

* the raw and non-raw TX path shares a lot of duplicate code which should be
  refactored;
* the 11n-ready chip TX path needs a little reworking.
2011-01-29 11:35:23 +00:00