mirror of
https://github.com/opnsense/src.git
synced 2026-03-16 23:55:19 -04:00
The list-based DMA engine has the following behaviour:
* When the DMA engine is in the init state, you can write the first
descriptor address to the QCU TxDP register and it will work.
* Then when it hits the end of the list (ie, it either hits a NULL
link pointer, OR it hits a descriptor with VEOL set) the QCU
stops, and the TxDP points to the last descriptor that was transmitted.
* Then when you want to transmit a new frame, you can then either:
+ write the head of the new list into TxDP, or
+ you write the head of the new list into the link pointer of the
last completed descriptor (ie, where TxDP points), then kick
TxE to restart transmission on that QCU>
* The hardware then will re-read the descriptor to pick up the link
pointer and then jump to that.
Now, the quirks:
* If you write a TxDP when there's been no previous TxDP (ie, it's 0),
it works.
* If you write a TxDP in any other instance, the TxDP write may actually
fail. Thus, when you start transmission, it will re-read the last
transmitted descriptor to get the link pointer, NOT just start a new
transmission.
So the correct thing to do here is:
* ALWAYS use the holding descriptor (ie, the last transmitted descriptor
that we've kept safe) and use the link pointer in _THAT_ to transmit
the next frame.
* NEVER write to the TxDP after you've done the initial write.
* .. also, don't do this whilst you're also resetting the NIC.
With this in mind, the following patch does basically the above.
* Since this encapsulates Sam's issues with the QCU behaviour w/ TDMA,
kill the TDMA special case and replace it with the above.
* Add a new TXQ flag - PUTRUNNING - which indicates that we've started
DMA.
* Clear that flag when DMA has been shutdown.
* Ensure that we're not restarting DMA with PUTRUNNING enabled.
* Fix the link pointer logic during TXQ drain - we should always ensure
the link pointer does point to something if there's a list of frames.
Having it be NULL as an indication that DMA has finished or during
a reset causes trouble.
Now, given all of this, i want to nuke axq_link from orbit. There's now HAL
methods to get and set the link pointer of a descriptor, so what we
should do instead is to update the right link pointer.
* If there's a holding descriptor and an empty TXQ list, set the
link pointer of said holding descriptor to the new frame.
* If there's a non-empty TXQ list, set the link pointer of the
last descriptor in the list to the new frame.
* Nuke axq_link from orbit.
Note:
* The AR9380 doesn't need this. FIFO TX writes are atomic. As long as
we don't append to a list of frames that we've already passed to the
hardware, all of the above doesn't apply. The holding descriptor stuff
is still needed to ensure the hardware can re-read a completed
descriptor to move onto the next one, but we restart DMA by pushing in
a new FIFO entry into the TX QCU. That doesn't require any real
gymnastics.
Tested:
* AR5210, AR5211, AR5212, AR5416, AR9380 - STA mode.
|
||
|---|---|---|
| .. | ||
| ath_dfs/null | ||
| ath_hal | ||
| ath_rate | ||
| ah_osdep.c | ||
| ah_osdep.h | ||
| if_ath.c | ||
| if_ath_ahb.c | ||
| if_ath_alq.c | ||
| if_ath_alq.h | ||
| if_ath_beacon.c | ||
| if_ath_beacon.h | ||
| if_ath_debug.c | ||
| if_ath_debug.h | ||
| if_ath_keycache.c | ||
| if_ath_keycache.h | ||
| if_ath_led.c | ||
| if_ath_led.h | ||
| if_ath_misc.h | ||
| if_ath_pci.c | ||
| if_ath_rx.c | ||
| if_ath_rx.h | ||
| if_ath_rx_edma.c | ||
| if_ath_rx_edma.h | ||
| if_ath_spectral.c | ||
| if_ath_spectral.h | ||
| if_ath_sysctl.c | ||
| if_ath_sysctl.h | ||
| if_ath_tdma.c | ||
| if_ath_tdma.h | ||
| if_ath_tsf.h | ||
| if_ath_tx.c | ||
| if_ath_tx.h | ||
| if_ath_tx_edma.c | ||
| if_ath_tx_edma.h | ||
| if_ath_tx_ht.c | ||
| if_ath_tx_ht.h | ||
| if_athdfs.h | ||
| if_athioctl.h | ||
| if_athrate.h | ||
| if_athvar.h | ||