Commit b5c80475 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k: Add Rx EDMA support

Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarVasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c38d4d2e
...@@ -72,6 +72,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, ...@@ -72,6 +72,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
return -EINPROGRESS; return -EINPROGRESS;
if (!rxs)
return 0;
rxs->rs_status = 0; rxs->rs_status = 0;
rxs->rs_flags = 0; rxs->rs_flags = 0;
......
...@@ -223,6 +223,12 @@ struct ath_tx { ...@@ -223,6 +223,12 @@ struct ath_tx {
struct ath_descdma txdma; struct ath_descdma txdma;
}; };
struct ath_rx_edma {
struct sk_buff_head rx_fifo;
struct sk_buff_head rx_buffers;
u32 rx_fifo_hwsize;
};
struct ath_rx { struct ath_rx {
u8 defant; u8 defant;
u8 rxotherant; u8 rxotherant;
...@@ -232,6 +238,8 @@ struct ath_rx { ...@@ -232,6 +238,8 @@ struct ath_rx {
spinlock_t rxbuflock; spinlock_t rxbuflock;
struct list_head rxbuf; struct list_head rxbuf;
struct ath_descdma rxdma; struct ath_descdma rxdma;
struct ath_buf *rx_bufptr;
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
}; };
int ath_startrecv(struct ath_softc *sc); int ath_startrecv(struct ath_softc *sc);
...@@ -240,7 +248,7 @@ void ath_flushrecv(struct ath_softc *sc); ...@@ -240,7 +248,7 @@ void ath_flushrecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs); int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc); void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush); int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype); int ath_tx_setup(struct ath_softc *sc, int haltype);
......
...@@ -246,6 +246,8 @@ struct ath9k_ops_config { ...@@ -246,6 +246,8 @@ struct ath9k_ops_config {
enum ath9k_int { enum ath9k_int {
ATH9K_INT_RX = 0x00000001, ATH9K_INT_RX = 0x00000001,
ATH9K_INT_RXDESC = 0x00000002, ATH9K_INT_RXDESC = 0x00000002,
ATH9K_INT_RXHP = 0x00000001,
ATH9K_INT_RXLP = 0x00000002,
ATH9K_INT_RXNOFRM = 0x00000008, ATH9K_INT_RXNOFRM = 0x00000008,
ATH9K_INT_RXEOL = 0x00000010, ATH9K_INT_RXEOL = 0x00000010,
ATH9K_INT_RXORN = 0x00000020, ATH9K_INT_RXORN = 0x00000020,
......
...@@ -401,6 +401,7 @@ void ath9k_tasklet(unsigned long data) ...@@ -401,6 +401,7 @@ void ath9k_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
u32 status = sc->intrstatus; u32 status = sc->intrstatus;
u32 rxmask;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
...@@ -410,9 +411,21 @@ void ath9k_tasklet(unsigned long data) ...@@ -410,9 +411,21 @@ void ath9k_tasklet(unsigned long data)
return; return;
} }
if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN);
else
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
if (status & rxmask) {
spin_lock_bh(&sc->rx.rxflushlock); spin_lock_bh(&sc->rx.rxflushlock);
ath_rx_tasklet(sc, 0);
/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false);
spin_unlock_bh(&sc->rx.rxflushlock); spin_unlock_bh(&sc->rx.rxflushlock);
} }
...@@ -445,6 +458,8 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -445,6 +458,8 @@ irqreturn_t ath_isr(int irq, void *dev)
ATH9K_INT_RXORN | \ ATH9K_INT_RXORN | \
ATH9K_INT_RXEOL | \ ATH9K_INT_RXEOL | \
ATH9K_INT_RX | \ ATH9K_INT_RX | \
ATH9K_INT_RXLP | \
ATH9K_INT_RXHP | \
ATH9K_INT_TX | \ ATH9K_INT_TX | \
ATH9K_INT_BMISS | \ ATH9K_INT_BMISS | \
ATH9K_INT_CST | \ ATH9K_INT_CST | \
...@@ -496,7 +511,8 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -496,7 +511,8 @@ irqreturn_t ath_isr(int irq, void *dev)
* If a FATAL or RXORN interrupt is received, we have to reset the * If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately. * chip immediately.
*/ */
if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
goto chip_reset; goto chip_reset;
if (status & ATH9K_INT_SWBA) if (status & ATH9K_INT_SWBA)
...@@ -505,6 +521,13 @@ irqreturn_t ath_isr(int irq, void *dev) ...@@ -505,6 +521,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN) if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true); ath9k_hw_updatetxtriglevel(ah, true);
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (status & ATH9K_INT_RXEOL) {
ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah, ah->imask);
}
}
if (status & ATH9K_INT_MIB) { if (status & ATH9K_INT_MIB) {
/* /*
* Disable interrupts until we service the MIB * Disable interrupts until we service the MIB
...@@ -1162,9 +1185,14 @@ static int ath9k_start(struct ieee80211_hw *hw) ...@@ -1162,9 +1185,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
} }
/* Setup our intr mask. */ /* Setup our intr mask. */
ah->imask = ATH9K_INT_RX | ATH9K_INT_TX ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
| ATH9K_INT_RXEOL | ATH9K_INT_RXORN ATH9K_INT_RXORN | ATH9K_INT_FATAL |
| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; ATH9K_INT_GLOBAL;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP;
else
ah->imask |= ATH9K_INT_RX;
if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
ah->imask |= ATH9K_INT_GTT; ah->imask |= ATH9K_INT_GTT;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment