freebsd-dev/sys/dev/ath/ath_hal/ar5416/ar5416_interrupts.c

350 lines
9.7 KiB
C
Raw Normal View History

2008-11-28 00:03:41 +00:00
/*
* Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
* Copyright (c) 2002-2008 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD$
2008-11-28 00:03:41 +00:00
*/
#include "opt_ah.h"
#include "ah.h"
#include "ah_internal.h"
#include "ar5416/ar5416.h"
#include "ar5416/ar5416reg.h"
/*
* Checks to see if an interrupt is pending on our NIC
*
* Returns: TRUE if an interrupt is pending
* FALSE if not
*/
HAL_BOOL
ar5416IsInterruptPending(struct ath_hal *ah)
{
uint32_t isr;
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (AR_SREV_HOWL(ah))
return AH_TRUE;
2008-11-28 00:03:41 +00:00
/*
* Some platforms trigger our ISR before applying power to
* the card, so make sure the INTPEND is really 1, not 0xffffffff.
*/
isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE);
if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0)
return AH_TRUE;
isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT))
return AH_TRUE;
return AH_FALSE;
}
/*
* Reads the Interrupt Status Register value from the NIC, thus deasserting
* the interrupt line, and returns both the masked and unmasked mapped ISR
* values. The value returned is mapped to abstract the hw-specific bit
* locations in the Interrupt Status Register.
*
Fix a corner-case of interrupt handling which resulted in potentially spurious (and fatal) interrupt errors. One user reported seeing this: Apr 22 18:04:24 ceres kernel: ar5416GetPendingInterrupts: fatal error, ISR_RAC 0x0 SYNC_CAUSE 0x2000 SYNC_CAUSE of 0x2000 is AR_INTR_SYNC_LOCAL_TIMEOUT which is a bus timeout; this shouldn't cause HAL_INT_FATAL to be set. After checking out ath9k, ath9k_ar9002_hw_get_isr() clears (*masked) before continuing, regardless of whether any bits in the ISR registers are set. So if AR_INTR_SYNC_CAUSE is set to something that isn't treated as fatal, and AR_ISR isn't read or is read and is 0, then (*masked) wouldn't be cleared. Thus any of the existing bits set that were passed in would be preserved in the output. The caller in if_ath - ath_intr() - wasn't setting the masked value to 0 before calling ath_hal_getisr(), so anything that was present in that uninitialised variable would be preserved in the case above of AR_ISR=0, AR_INTR_SYNC_CAUSE != 0; and if the HAL_INT_FATAL bit was set, a fatal condition would be interpreted and the chip was reset. This patch does the following: * ath_intr() - set masked to 0 before calling ath_hal_getisr(); * ar5416GetPendingInterrupts() - clear (*masked) before processing continues; so if the interrupt source is AR_INTR_SYNC_CAUSE and it isn't fatal, the hardware isn't reset via returning HAL_INT_FATAL. This doesn't fix any underlying errors which trigger AR_INTR_SYNC_LOCAL_TIMEOUT - which is a bus timeout of some sort - so that likely should be further investigated.
2011-04-23 06:37:09 +00:00
* (*masked) is cleared on initial call.
*
2008-11-28 00:03:41 +00:00
* Returns: A hardware-abstracted bitmap of all non-masked-out
* interrupts pending, as well as an unmasked value
*/
HAL_BOOL
ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
{
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
uint32_t isr, isr0, isr1, sync_cause = 0;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
2008-11-28 00:03:41 +00:00
/*
* Verify there's a mac interrupt and the RTC is on.
*/
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (AR_SREV_HOWL(ah)) {
*masked = 0;
2008-11-28 00:03:41 +00:00
isr = OS_REG_READ(ah, AR_ISR);
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
} else {
if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) &&
(OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
isr = OS_REG_READ(ah, AR_ISR);
else
isr = 0;
sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
sync_cause &= AR_INTR_SYNC_DEFAULT;
*masked = 0;
Fix a corner-case of interrupt handling which resulted in potentially spurious (and fatal) interrupt errors. One user reported seeing this: Apr 22 18:04:24 ceres kernel: ar5416GetPendingInterrupts: fatal error, ISR_RAC 0x0 SYNC_CAUSE 0x2000 SYNC_CAUSE of 0x2000 is AR_INTR_SYNC_LOCAL_TIMEOUT which is a bus timeout; this shouldn't cause HAL_INT_FATAL to be set. After checking out ath9k, ath9k_ar9002_hw_get_isr() clears (*masked) before continuing, regardless of whether any bits in the ISR registers are set. So if AR_INTR_SYNC_CAUSE is set to something that isn't treated as fatal, and AR_ISR isn't read or is read and is 0, then (*masked) wouldn't be cleared. Thus any of the existing bits set that were passed in would be preserved in the output. The caller in if_ath - ath_intr() - wasn't setting the masked value to 0 before calling ath_hal_getisr(), so anything that was present in that uninitialised variable would be preserved in the case above of AR_ISR=0, AR_INTR_SYNC_CAUSE != 0; and if the HAL_INT_FATAL bit was set, a fatal condition would be interpreted and the chip was reset. This patch does the following: * ath_intr() - set masked to 0 before calling ath_hal_getisr(); * ar5416GetPendingInterrupts() - clear (*masked) before processing continues; so if the interrupt source is AR_INTR_SYNC_CAUSE and it isn't fatal, the hardware isn't reset via returning HAL_INT_FATAL. This doesn't fix any underlying errors which trigger AR_INTR_SYNC_LOCAL_TIMEOUT - which is a bus timeout of some sort - so that likely should be further investigated.
2011-04-23 06:37:09 +00:00
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (isr == 0 && sync_cause == 0)
return AH_FALSE;
}
2008-11-28 00:03:41 +00:00
if (isr != 0) {
struct ath_hal_5212 *ahp = AH5212(ah);
uint32_t mask2;
mask2 = 0;
if (isr & AR_ISR_BCNMISC) {
uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);
if (isr2 & AR_ISR_S2_TIM)
mask2 |= HAL_INT_TIM;
if (isr2 & AR_ISR_S2_DTIM)
mask2 |= HAL_INT_DTIM;
if (isr2 & AR_ISR_S2_DTIMSYNC)
mask2 |= HAL_INT_DTIMSYNC;
if (isr2 & (AR_ISR_S2_CABEND ))
mask2 |= HAL_INT_CABEND;
if (isr2 & AR_ISR_S2_GTT)
mask2 |= HAL_INT_GTT;
if (isr2 & AR_ISR_S2_CST)
mask2 |= HAL_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= HAL_INT_TSFOOR;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
/*
* Don't mask out AR_BCNMISC; instead mask
* out what causes it.
*/
OS_REG_WRITE(ah, AR_ISR_S2, isr2);
isr &= ~AR_ISR_BCNMISC;
2008-11-28 00:03:41 +00:00
}
if (isr == 0xffffffff) {
*masked = 0;
return AH_FALSE;
2008-11-28 00:03:41 +00:00
}
*masked = isr & HAL_INT_COMMON;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= HAL_INT_RX;
if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
*masked |= HAL_INT_TX;
/*
* When doing RX interrupt mitigation, the RXOK bit is set
* in AR_ISR even if the relevant bit in AR_IMR is clear.
* Since this interrupt may be due to another source, don't
* just automatically set HAL_INT_RX if it's set, otherwise
* we could prematurely service the RX queue.
*
* In some cases, the driver can even handle all the RX
* frames just before the mitigation interrupt fires.
* The subsequent RX processing trip will then end up
* processing 0 frames.
*/
#ifdef AH_AR5416_INTERRUPT_MITIGATION
if (isr & AR_ISR_RXERR)
*masked |= HAL_INT_RX;
#else
2008-11-28 00:03:41 +00:00
if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
*masked |= HAL_INT_RX;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
#endif
if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
AR_ISR_TXEOL)) {
2008-11-28 00:03:41 +00:00
*masked |= HAL_INT_TX;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
isr0 = OS_REG_READ(ah, AR_ISR_S0);
OS_REG_WRITE(ah, AR_ISR_S0, isr0);
isr1 = OS_REG_READ(ah, AR_ISR_S1);
OS_REG_WRITE(ah, AR_ISR_S1, isr1);
/*
* Don't clear the primary ISR TX bits, clear
* what causes them (S0/S1.)
*/
isr &= ~(AR_ISR_TXOK | AR_ISR_TXDESC |
AR_ISR_TXERR | AR_ISR_TXEOL);
2008-11-28 00:03:41 +00:00
ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
}
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
if ((isr & AR_ISR_GENTMR) || (! pCap->halAutoSleepSupport)) {
uint32_t isr5;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
isr5 = OS_REG_READ(ah, AR_ISR_S5);
OS_REG_WRITE(ah, AR_ISR_S5, isr5);
isr &= ~AR_ISR_GENTMR;
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
if (! pCap->halAutoSleepSupport)
if (isr5 & AR_ISR_S5_TIM_TIMER)
*masked |= HAL_INT_TIM_TIMER;
}
2008-11-28 00:03:41 +00:00
*masked |= mask2;
}
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
Various interrupt handling and RX interrupt mitigation fixes. * The AR_ISR_RAC interrupt processing method has a subtle bug in all the MAC revisions (including pre-11n NICs) until AR9300v2. If you're unlucky, the clear phase clears an update to one of the secondary registers, which includes TX status. This shows up as a "watchdog timeout" if you're doing very low levels of TX traffic. If you're doing a lot of non-11n TX traffic, you'll end up receiving a TX interrupt from some later traffic anyway. But when TX'ing 11n aggregation session traffic (which -HEAD isn't yet doing), you may find that you're only able to TX one frame (due to BAW restrictions) and this may end up hitting this race condition. The only solution is to not use RAC and instead use AR_ISR and the AR_ISR_Sx registers. The bit in AR_ISR which represents the secondary registers are not cleared; only the AR_ISR_Sx bits are. This way any updates which occur between the read and subsequent write will stay asserted and (correctly) trigger a subsequent interrupt. I've tested this on the AR5416, AR9160, AR9280. I will soon test the AR9285 and AR9287. * The AR_ISR TX and RX bits (and all others!) are set regardless of whether the contents of the AR_IMR register. So if RX mitigation is enabled, RXOK is going to be set in AR_ISR and it would normally set HAL_INT_RX. Fix the code to not set HAL_INT_RX when RXOK is set and RX mitigation is compiled in. That way the RX path isn't prematurely called. I would see: * An interrupt would come in (eg a beacon, or TX completion) where RXOK was set but RXINTM/RXMINT wasn't; * ath_rx_proc() be called - completing RX frames; * RXINTM/RXMINT would then fire; * ath_rx_proc() would then be called again but find no frames in the queue. This fixes the RX mitigation behaviour to not overly call ath_rx_proc(). * Start to flesh out more correct timer interrupt handling - it isn't kite/merlin specific. It's actually based on whether autosleep support is enabled or not. This is sourced from my 11n TX branch and has been tested for a few weeks. Finally, the interrupt handling change should likely be implemented for AR5210, AR5211 and AR5212.
2011-10-02 14:08:56 +00:00
/*
* Since we're not using AR_ISR_RAC, clear the status bits
* for handled interrupts here. For bits whose interrupt
* source is a secondary register, those bits should've been
* masked out - instead of those bits being written back,
* their source (ie, the secondary status registers) should
* be cleared. That way there are no race conditions with
* new triggers coming in whilst they've been read/cleared.
*/
OS_REG_WRITE(ah, AR_ISR, isr);
/* Flush previous write */
OS_REG_READ(ah, AR_ISR);
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (AR_SREV_HOWL(ah))
return AH_TRUE;
2008-11-28 00:03:41 +00:00
if (sync_cause != 0) {
if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) {
*masked |= HAL_INT_FATAL;
}
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n",
__func__);
OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
OS_REG_WRITE(ah, AR_RC, 0);
*masked |= HAL_INT_FATAL;
}
/*
* On fatal errors collect ISR state for debugging.
*/
if (*masked & HAL_INT_FATAL) {
AH_PRIVATE(ah)->ah_fatalState[0] = isr;
AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause;
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n",
__func__, isr, sync_cause);
}
OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
/* NB: flush write */
(void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
}
return AH_TRUE;
}
/*
* Atomically enables NIC interrupts. Interrupts are passed in
* via the enumerated bitmask in ints.
*/
HAL_INT
ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints)
{
struct ath_hal_5212 *ahp = AH5212(ah);
uint32_t omask = ahp->ah_maskReg;
uint32_t mask, mask2;
2008-11-28 00:03:41 +00:00
HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
__func__, omask, ints);
if (omask & HAL_INT_GLOBAL) {
HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) OS_REG_READ(ah, AR_IER);
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (! AR_SREV_HOWL(ah)) {
OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
(void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE);
2008-11-28 00:03:41 +00:00
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
(void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE);
}
2008-11-28 00:03:41 +00:00
}
mask = ints & HAL_INT_COMMON;
mask2 = 0;
#ifdef AH_AR5416_INTERRUPT_MITIGATION
/*
* Overwrite default mask if Interrupt mitigation
* is specified for AR5416
*/
if (ints & HAL_INT_RX)
mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM;
#else
if (ints & HAL_INT_RX)
mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
#endif
2008-11-28 00:03:41 +00:00
if (ints & HAL_INT_TX) {
if (ahp->ah_txOkInterruptMask)
mask |= AR_IMR_TXOK;
if (ahp->ah_txErrInterruptMask)
mask |= AR_IMR_TXERR;
if (ahp->ah_txDescInterruptMask)
mask |= AR_IMR_TXDESC;
if (ahp->ah_txEolInterruptMask)
mask |= AR_IMR_TXEOL;
}
if (ints & (HAL_INT_BMISC)) {
mask |= AR_IMR_BCNMISC;
if (ints & HAL_INT_TIM)
mask2 |= AR_IMR_S2_TIM;
if (ints & HAL_INT_DTIM)
mask2 |= AR_IMR_S2_DTIM;
if (ints & HAL_INT_DTIMSYNC)
mask2 |= AR_IMR_S2_DTIMSYNC;
if (ints & HAL_INT_CABEND)
mask2 |= (AR_IMR_S2_CABEND );
if (ints & HAL_INT_CST)
mask2 |= AR_IMR_S2_CST;
if (ints & HAL_INT_TSFOOR)
mask2 |= AR_IMR_S2_TSFOOR;
}
if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
mask |= AR_IMR_BCNMISC;
if (ints & HAL_INT_GTT)
mask2 |= AR_IMR_S2_GTT;
if (ints & HAL_INT_CST)
mask2 |= AR_IMR_S2_CST;
}
2008-11-28 00:03:41 +00:00
/* Write the new IMR and store off our SW copy. */
HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
OS_REG_WRITE(ah, AR_IMR, mask);
mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
AR_IMR_S2_DTIM |
AR_IMR_S2_DTIMSYNC |
AR_IMR_S2_CABEND |
AR_IMR_S2_CABTO |
AR_IMR_S2_TSFOOR |
AR_IMR_S2_GTT |
AR_IMR_S2_CST);
OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2);
ahp->ah_maskReg = ints;
/* Re-enable interrupts if they were enabled before. */
if (ints & HAL_INT_GLOBAL) {
HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
Introduce AR9130 (HOWL) WMAC support to the FreeBSD HAL. The AR9130 is an AR9160/AR5416 family WMAC which is glued directly to the AR913x SoC peripheral bus (APB) rather than via a PCI/PCIe bridge. The specifics: * A new build option is required to use the AR9130 - AH_SUPPORT_AR9130. This is needed due to the different location the RTC registers live with this chip; hopefully this will be undone in the future. This does currently mean that enabling this option will break non-AR9130 builds, so don't enable it unless you're specifically building an image for the AR913x SoC. * Add the new probe, attach, EEPROM and PLL methods specific to Howl. * Add a work-around to ah_eeprom_v14.c which disables some of the checks for endian-ness and magic in the EEPROM image if an eepromdata block is provided. This'll be fixed at a later stage by porting the ath9k probe code and making sure it doesn't break in other setups (which my previous attempt at this did.) * Sprinkle Howl modifications throughput the interrupt path - it doesn't implement the SYNC interrupt registers, so ignore those. * Sprinkle Howl chip powerup/down throughout the reset path; the RTC methods were * Sprinkle some other Howl workarounds in the reset path. * Hard-code an alternative setup for the AR_CFG register for Howl, that sets up things suitable for Big-Endian MIPS (which is the only platform this chip is glued to.) This has been tested on the AR913x based TP-Link WR-1043nd mode, in legacy, HT/20 and HT/40 modes. Caveats: * 2ghz has only been tested. I've not seen any 5ghz radios glued to this chipset so I can't test it. * AR5416_INTERRUPT_MITIGATION is not supported on the AR9130. At least, it isn't implemented in ath9k. Please don't enable this. * This hasn't been tested in MBSS mode or in RX/TX block-aggregation mode.
2011-04-28 12:47:40 +00:00
if (! AR_SREV_HOWL(ah)) {
mask = AR_INTR_MAC_IRQ;
if (ints & HAL_INT_GPIO)
mask |= SM(AH5416(ah)->ah_gpioMask,
AR_INTR_ASYNC_MASK_GPIO);
OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask);
OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask);
mask = AR_INTR_SYNC_DEFAULT;
if (ints & HAL_INT_GPIO)
mask |= SM(AH5416(ah)->ah_gpioMask,
AR_INTR_SYNC_MASK_GPIO);
OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask);
OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask);
}
2008-11-28 00:03:41 +00:00
}
return omask;
}