Commit Graph

992 Commits

Author SHA1 Message Date
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
781e7eaffd As I thought, this is a bad idea. When forming aggregates, the RTS/CTS
stuff and rate control lookup is only done on the first frame.
2012-04-07 05:46:00 +00:00
Adrian Chadd
045bc7882e Enforce the RTS aggregation limit if RTS/CTS protection is enabled;
if any subframes in an aggregate have different protection from the
first frame in the formed aggregate, don't add that frame to the
aggregate.

This is likely a suboptimal method (I think we'll mostly be OK marking
frames that have seqno's with the same protection as normal data frames)
but I'll just be cautious for now.
2012-04-07 03:22:11 +00:00
Adrian Chadd
ce656facf3 Store away the RTS aggregate limit from the HAL.
This will be used by some upcoming code to ensure that aggregates
are enforced to be a certain size.  The AR5416 has a limitation on
RTS protected aggregates (8KiB).
2012-04-07 02:51:53 +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
084c471979 Track and optionally log the actual sync interrupt cause.
These are involved in tracking host interface issues (ie, PCI/PCIe/AHB
interface.)
2012-04-04 22:51:50 +00:00
Adrian Chadd
d6b2002327 Disable the HWQ contents upon a TX queue reset, rather than a TX queue flush.
This is designed to assist in figuring out what the hardware state is
when something like a queue hang has occured.
2012-04-04 22:24:11 +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
2fe1131c7b Add a threadid to the ah_decode API.
This adds the current thread ID to each logged register and mark entry,
allowing for easier debugging of concurrent/overlapping NIC operations.
2012-04-04 20:46:20 +00:00
Adrian Chadd
7961e32527 Disable a specific Merlin hardware workaround which may cause hangs on some
PCIe controllers.

Obtained from:	Atheros / Linux
2012-04-04 20:42:32 +00:00
Adrian Chadd
b5a9dfd57c oops, add a missing lock. 2012-03-29 21:54:19 +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
e7200579b8 Add the new channel width change field to the ath(4) driver.
This is not entirely correct as it simply resets the channel, flushing
whatever is in the TX/RX queue.  This can and will break aggregation
BAW tracking.  But the alternative (HT40 frames being sent with the hardware
in HT20 mode) is even worse.

There's still a small window between the htinfo being received (and the ni_chw
field being updated) which could cause problems.  I'll look at fleshing this
out in follow-up commits.

PR:		kern/166286
2012-03-25 03:14:31 +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
d780702e8b Sprinkle some style(9) things around. 2012-03-22 21:47:14 +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
a66d508971 Fix a couple of debugging outputs.
* printf -> device_printf
* print the buffer pointer and sequence number for any buffer that wasn't
  correctly tidied up before it was freed.  This is to aid in some
  current SMP TX debugging stalls.

PR:		kern/166190
2012-03-16 23:24:27 +00:00
Adrian Chadd
58816f3f1b Add a dependency on ALQ if IEEE80211_ALQ and/or AH_DEBUG_ALQ is included. 2012-03-16 23:12:40 +00:00
Adrian Chadd
e4e7938ae5 Stick the if_drv_flags access (check and modify) behind the ifq lock.
Although access to the flags to check/set OACTIVE is racy due to how
the default if_start() function works, this should remove any races
with read/modify/write between threads.
2012-03-10 20:09:02 +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
91d92caece Should the mcast queue be locked here? In case more multicast traffic
comes along?

This commit was brought to you via an Atheros AR5210, associated to an 3x3
HT40 11na access point.  Yes, this driver still works with it.
2012-03-09 22:41:09 +00:00
Adrian Chadd
e86fd7a715 Insert extra paranoia into the ath(4) driver.
This function must be called with both the source and destination TXQs
locked or things will get hairy.

I added this as part of some debugging in a PR but it turned out to not
be the cause.  I still think it's -correct- so, here it is.
2012-03-09 08:36:30 +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
a887b1e359 Wrap another ATH_LOCK around the scanning flag.
PR:		kern/163318
2012-03-02 03:11:53 +00:00
Adrian Chadd
c98cefc5db Wrap the scan code state change stuff behind ATH_LOCK and the PCU fiddling
behind the PCU lock.

sc_scanning is being checked without ATH_LOCK behind held and could
in theory run from multiple threads.
2012-03-02 02:57:10 +00:00
Gavin Atkinson
1748d1e513 Correct capitalization of "Hz" in user-visible text (manpages, printf(),
etc).

MFC after:	3 days
2012-02-28 13:19:34 +00:00
Adrian Chadd
cc86f1ea4d Add in some debugging code to check whether the current rate table has
been bait-and-switched from the rate control code.

This will avoid the panic that I saw and will avoid sending invalid rates
(eg 11a/11g OFDM rates when in 11b, on 11b-only NICs (AR5211)) where the
rate table is not "big".

It also will point out situations where this occurs for the 11n NICs
which will have sufficiently large rate tables that "invalid rix" doesn't
occur.

I'll try to follow this up with a commit that adds a current operating mode
check. The "rix" is only relevant to the current operating mode and rate
table.

PR:	kern/165475
2012-02-26 06:04:44 +00:00
Adrian Chadd
d52f713265 Attempt to further fix some of the concurrency/reset issues that occur.
* ath_reset() is being called in softclock context, which may have the
  thing sleep on a lock.  To avoid this, since we really _shouldn't_
  be sleeping on any locks, break out the no-loss reset path into a tasklet
  and call that from:

  + ath_calibrate()
  + ath_watchdog()

  This has the added advantage that it'll end up also doing the frame
  RX cleanup from within the taskqueue context, rather than the softclock
  context.

* Shuffle around the taskqueue_block() call to be before we grab the lock
  and disable interrupts.

  The trouble here is that taskqueue_block() doesn't block currently
  queued (but not yet running) tasks so calling it doesn't guarantee
  no further tasks (that weren't running on _A_ CPU at the time of this
  call) will complete.  Calling taskqueue_drain() on these tasks won't
  work because if any _other_ thread calls taskqueue_enqueue() for whatever
  reason, everything gets very angry and stops working.

  This slightly changes the race condition enough to let ath_rx_tasklet()
  run before we try disabling it, and thus quietens the warnings a bit.

  The (more) true solution will be doing something like the following:

  * having a taskqueue_blocked mask in ath_softc;
  * having an interrupt_blocked mask in ath_softc;
  * only calling taskqueue_drain() on each individual task _after_ the
    lock has been acquired - that way no further tasklet scheduling
    is going to occur.
  * Then once the tasks have been blocked _and_ the interrupt has been
    disabled, call taskqueue_drain() on each, ensuring that anything
    that _was_ scheduled or running is removed.

  The trouble is if something calls taskqueue_enqueue() on a task
  after taskqueue_blocked() has been called but BEFORE taskqueue_drain()
  has been called, ta_pending will be set to 1 and taskqueue_drain()
  will sit there stuck in msleep() until you hard-kill the machine.

PR: kern/165382
PR: kern/165220
2012-02-25 19:12:54 +00:00
Adrian Chadd
398bca2e5e Use the passed-in channel rather than ic->ic_curchan.
I'm not sure _why_ the ic is NULL here, but I've seen it occasionally do
this after I've been tinkering with things for a while.  It ends up
crashing in a call to ath_chan_set() via the net80211 scan code and scan
task.
2012-02-23 08:32:54 +00:00
Adrian Chadd
7b1144d245 Break out the radar code into a separate source file.
This mirrors the internal HAL organisation and reduces the differences
between the HAL codebases slightly.

Obtained from:	Atheros
2012-02-20 03:07:07 +00:00
Adrian Chadd
107fdf9681 Try to ensure that ieee80211_newstate() and the vap_newstate methods
hold the lock.

This is part of my series of work to try and capture when net80211
locking isn't.

ObNote: it'd be nice to be able to mark a lock as "assert if the lock
is dropped", so I could capture functions which decide that dropping
and reacquiring the lock is a good idea (without re-checking the
sanity of the state protected by the lock.)
2012-02-18 09:18:06 +00:00
Adrian Chadd
2a4106cfef Fix the return type.
Submitted by:	arundel
Found by:	clang/llvm
2012-02-17 08:45:08 +00:00
Adrian Chadd
e78719adf9 Enforce some consistent ordering and handling of interrupt disable/enable
with RX/TX halting.

* Always disable/enable interrupts during a channel change, just to simply
  things.

* Ensure that the ath taskqueue has completed and is paused before
  continuing.

This dramatically reduces the instances of overlapping RX and reset
conditions.

PR:	kern/165220
2012-02-17 03:46:38 +00:00
Adrian Chadd
21008bf10d Begin breaking out the txrx stop code into a locked and unlocked variant.
PR:	kern/165220
2012-02-17 03:23:01 +00:00
Adrian Chadd
5a86e1369c Fix the usefir128 config bit flipping. 2012-02-14 20:06:28 +00:00
Adrian Chadd
cfa5ef068f Improve the radar register config API.
* Fix the "enabled" flag to actually reflect whether radar detection is
  enabled or not.
* Add flags for the relstep/relpwr checks.
2012-02-14 20:05:28 +00:00
Adrian Chadd
807675317e Attempt to address some potential vap->iv_bss race conditions.
There are unfortunately a number of situations where vap->iv_bss is changed
or freed by some code in net80211.  Because multiple threads can concurrently
be doing work (and the vap->iv_bss access isn't at all done behind any kind
of lock), it's quite possible that:

* a change will occur in one thread - eg, by a call through
  ieee80211_sta_join1();
* a state change occurs in another thread - eg an RX is scheduled
  in the ath tasklet and it calls ieee80211_input_mimo_all(), which
  does dereference vap->iv_bss;
* these two executing concurrently, causing things to explode.

Another instance is ath_beacon_alloc() which takes an ieee80211_node *.
It's called with the vap->iv_bss node from ath_newstate(). If the node has
changed in the meantime (say it's been freed elsewhere) the reference
that it grabbed _before_ refcounting it may be stale.

I would _prefer_ that these sorts of things were serialised somewhere but
that may be a bit much to ask.  Instead, the best we can (currently) hope
is that the underlying bss node is still (somewhat) valid.

There is a related PR (kern/164382) described by the first case above.
That should be fixed by properly serialising the RX path and reset path
so an RX can't occur at the same time as the vap free/shutdown path.

This is inspired by some related fixes in r212127.

PR: kern/165060
2012-02-13 00:28:41 +00:00
Adrian Chadd
2af3b95bf2 Enforce the hardware chainmask when allowing the user to override the
chainmask.

This way a disabled radio chain can't be enabled by a user.
2012-02-10 10:10:41 +00:00
Adrian Chadd
dc8552d525 .. oops, use the right chainmask. 2012-02-10 10:09:16 +00:00
Adrian Chadd
a865860d09 Add in a new driver feature to allow the TX and RX chainmask to be
overridden at attach time.

Some 802.11n NICs may only have one physical antenna connected.
The radios will be very upset if you try enabling radios which aren't
connected to antennas.

This allows hints to override the TX and RX chainmask.

These hints are:

hint.ath.X.rx_chainmask
hint.ath.X.tx_chainmask

They can be set at either boot time or in kenv before the module is loaded.

This and the previous HAL commit were sponsored in late 2011 by Hobnob, Inc.

Sponsored by:	Hobnob, Inc.
2012-02-10 10:01:09 +00:00
Adrian Chadd
40ffb20de6 Extend the HAL code to allow the RX and TX chainmask to be overridden
by capabilities.

Add an ar5416SetCapability() function, which contains logic to override
the chainmask and update the relevant stream.

This is designed to be called after the attach function, which presets
the TX/RX chainmask and stream.

TODO: check the chainmask against the hardware chainmask so non-existing
chains aren't enabled.
2012-02-10 09:58:20 +00:00
Adrian Chadd
ab4343580d Contribute some example code which demonstrates how to initialise the
radar parameters for the AR5416 and later NICs.

These parameters have been tested on the following NICs:

* AR5416
* AR9160
* AR9220
* AR9280

And yes, these will return radar pulse parameters and (for AR9160 and later)
radar FFT information as PHY errors.

This is again not enough to do radar detection, it's just here to faciliate
development and validation of radar detection algorithms.

The (pulse, not FFT) decoding code for AR5212, AR5416 and later NICs exist
in the HAL.

This code is disabled for now as generating radar PHY errors can quickly
cause issues in busy environment.s  Some further debugging of the RX path
is needed.

Finally, these parameters are likely not useful for the AR5212 era NICs.
The madwifi-dfs branch should have suitable example parameters for the
11a era NICs.
2012-02-06 20:23:21 +00:00
Adrian Chadd
1db689c583 Support AR9281/AR5B91 - a 1x2 stream device based on the AR9280.
* Override the TX/RX stream count if the EEPROM reports a single RX or
  TX stream, rather than assuming the device will always be a 2x2 strea
  device.

* For AR9280 devices, don't hard-code 2x2 stream.  Instead, allow the
  ar5416FillCapabilityInfo() routine to correctly determine things.

The latter should be done for all 11n chips now that
ar5416FillCapabilityInfo() will set the TX/RX stream count based on the
active TX/RX chainmask in the EEPROM.

Thanks to Maciej Milewski for donating some AR9281 NICs to me for
testing.
2012-01-31 22:31:16 +00:00