#
b69b0dcc |
| 08-Nov-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Add some hooks into the driver to attach, detach and record EDMA descriptor events.
This is primarily for the TX EDMA and TX EDMA completion. I haven't yet tied it into the EDMA RX path or the legac
Add some hooks into the driver to attach, detach and record EDMA descriptor events.
This is primarily for the TX EDMA and TX EDMA completion. I haven't yet tied it into the EDMA RX path or the legacy TX/RX path.
Things that I don't quite like:
* Make the pointer type 'void' in ath_softc and have if_ath_alq*() return a malloc'ed buffer. That would remove the need to include if_ath_alq.h in if_athvar.h. * The sysctl setup needs to be cleaned up.
show more ...
|
#
6e84772f |
| 06-Nov-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Convert the aggregate descriptor path over to use the same API as the non-aggregate path.
I "cheated" by using some TX setup code in our HAL that isn't present in the atheros HAL (or Linux ath9k.)
Convert the aggregate descriptor path over to use the same API as the non-aggregate path.
I "cheated" by using some TX setup code in our HAL that isn't present in the atheros HAL (or Linux ath9k.)
The old path for forming aggregates was:
* setup the rate control in the first descriptor; * call chaintxdesc() on all the frames; * call setupfirsttxdesc() on the first descrpitor in the first frame; * call setuplasttxdesc() on the last descriptor in the last frame.
The new path for forming aggregates looks like the non-aggregate path:
* call setuptxdesc() on the first descriptor in the first frame; * setup the rate control in the first descriptor; * call filltxdesc() on each descriptor in the frame; * if it's an aggregate - call set11n_aggr_{first, middle, last} as appropriate (see the code for a description of what is "appropriate".)
Now, this is done primarily for the AR9300 HAL - it doesn't implement the first set of aggregate functions. It just has the older methods and the "first/middle/last" aggregate methods. So, let's convert the code to use these.
Note: the AR5416 HAL in FreeBSD had that code (from me, a while ago) and a previous commit brought it up to behave the same as the AR9300 HAL routines.
There's some further tidyups to be done - specifically, avoid doing multiple calls to the 11n descriptor functions. I shouldn't call clr11n_aggr(), then set11n_aggr_middle(), then also set11n_aggr_first(). On (at least MIPS) the TX descriptors are in non-cachable memory and this will cause multiple slow writes.
I'll debug/tidy that up in a future commit.
Tested:
* AR9280, STA * AR9280/AR9160, AP * AR9380, STA (using a local, closed source HAL, sorry!)
show more ...
|
#
23090366 |
| 04-Nov-2012 |
Simon J. Gerraty <sjg@FreeBSD.org> |
Sync from head
|
#
1b5c5f5a |
| 31-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
I give up - introduce a TX lock to serialise TX operations.
I've tried serialising TX using queues and such but unfortunately due to how this interacts with the locking going on elsewhere in the net
I give up - introduce a TX lock to serialise TX operations.
I've tried serialising TX using queues and such but unfortunately due to how this interacts with the locking going on elsewhere in the networking stack, the TX task gets delayed, resulting in quite a noticable throughput loss:
* baseline TCP for 2x2 11n HT40 is ~ 170mbit/sec; * TCP for TX task in the ath taskq, with the RX also going on - 80mbit/sec; * TCP for TX task in a separate, second taskq - 100mbit/sec.
So for now I'm going with the Linux wireless stack approach - lock tx early. The linux code does in the wireless stack, before the 802.11 state stuff happens and before it's punted to the driver. But TX locking needs to also occur at the driver layer as the TX completion code _also_ begins to drain the ifnet TX queue.
Whilst I'm here, add some KTR traces for the TX path.
Note:
* This really should be done at the net80211 layer (as well, at least.) But that'll have to wait for a little more thought to happen.
show more ...
|
#
548a605d |
| 28-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Begin fleshing out some software queue awareness for TIM handling with the power save queue.
* introduce some new ATH_NODE lock protected fields, tracking the net80211 psq and TIM state; * when do
Begin fleshing out some software queue awareness for TIM handling with the power save queue.
* introduce some new ATH_NODE lock protected fields, tracking the net80211 psq and TIM state; * when doing buffer transitions - ie, when sending and completing buffers - check the state of the SWQ and update the TIM appropriately. * when clearing the TIM bit, if the SWQ is not empty then delay clearing it.
This is racy, but it's no less racy than the current net80211 power save queue management code. Specifically, with multiple TX threads, it's quite plausible that parallel state updates will race and the TIM will be left in an inconsistent state. I'll address that in a follow-up commit.
show more ...
|
#
9572684a |
| 26-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Since it's not immediately obvious whether the current TX path handles fragment rate lookups correctly, add a comment describing exactly that.
The assumption in the fragment duration code is the dur
Since it's not immediately obvious whether the current TX path handles fragment rate lookups correctly, add a comment describing exactly that.
The assumption in the fragment duration code is the duration of the next fragment will match the rate used by the current fragment. But I think a rate lookup is being done for _each_ fragment. For older pre-sample rate control this would almost always be the case, but for sample it may be incorrect more often then correct.
show more ...
|
#
13aa9ee5 |
| 15-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Stop abusing the ATH_TID_*() queue macros for filtered frames and give them their own macro set.
|
#
b1dddc28 |
| 13-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Fix the non-TDMA build.
|
#
3e6cc97f |
| 08-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Migrate the TID TXQ accesses to a new set of macros, rather than reusing the ATH_TXQ_* macros.
* Introduce the new macros; * rename the TID queue and TID filtered frame queue so the compiler tells
Migrate the TID TXQ accesses to a new set of macros, rather than reusing the ATH_TXQ_* macros.
* Introduce the new macros; * rename the TID queue and TID filtered frame queue so the compiler tells me I'm using the wrong macro.
These should correspond 1:1 to the existing code.
show more ...
|
#
0eb81626 |
| 04-Oct-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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 t
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.)
show more ...
|
#
7403d1b9 |
| 26-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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
show more ...
|
#
0a544719 |
| 25-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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 har
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>
show more ...
|
#
23f44d2b |
| 25-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Call ath_tx_tid_unsched() after the node has been flushed, so the state can be printed correctly.
|
#
03682514 |
| 24-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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 an
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.
show more ...
|
#
0c54de88 |
| 24-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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.
show more ...
|
#
94eefcf1 |
| 24-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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.
|
#
4e81f27c |
| 20-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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.
show more ...
|
#
d05b576d |
| 20-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Place the comment where it should be.
|
#
088d8b81 |
| 20-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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.)
show more ...
|
#
0aa5c1bb |
| 18-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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 effec
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.
show more ...
|
#
f1bc738e |
| 18-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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 w
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.
show more ...
|
#
c6e9cee2 |
| 17-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
Take credit for the work I've done in this source file.
|
#
5d9b19f7 |
| 11-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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'.
|
#
21840808 |
| 09-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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.
show more ...
|
#
2a9f83af |
| 07-Sep-2012 |
Adrian Chadd <adrian@FreeBSD.org> |
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
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
show more ...
|