diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_mac.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 115 |
1 files changed, 72 insertions, 43 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index b363cc06cfd..729ffbf0734 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -13,8 +13,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <linux/export.h> #include "hw.h" #include "ar9003_mac.h" +#include "ar9003_mci.h" static void ar9003_hw_rx_enable(struct ath_hw *hw) { @@ -27,11 +29,14 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) struct ar9003_txc *ads = ds; int checksum = 0; u32 val, ctl12, ctl17; + u8 desc_len; + + desc_len = ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x18 : 0x17); val = (ATHEROS_VENDOR_ID << AR_DescId_S) | (1 << AR_TxRxDesc_S) | (1 << AR_CtrlStat_S) | - (i->qcu << AR_TxQcuNum_S) | 0x17; + (i->qcu << AR_TxQcuNum_S) | desc_len; checksum += val; ACCESS_ONCE(ads->info) = val; @@ -80,6 +85,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ads->ctl20 = 0; ads->ctl21 = 0; ads->ctl22 = 0; + ads->ctl23 = 0; ctl17 = SM(i->keytype, AR_EncrType); if (!i->is_first) { @@ -169,25 +175,33 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) ads->ctl10 |= ar9003_calc_ptr_chksum(ads); } -static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked, + u32 *sync_cause_p) { u32 isr = 0; u32 mask2 = 0; struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 sync_cause = 0; struct ath_common *common = ath9k_hw_common(ah); + u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; + bool fatal_int; + + if (ath9k_hw_mci_is_enabled(ah)) + async_mask |= AR_INTR_ASYNC_MASK_MCI; - if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { + async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); + + if (async_cause & async_mask) { if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) isr = REG_READ(ah, AR_ISR); } + sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; *masked = 0; - if (!isr && !sync_cause) + if (!isr && !sync_cause && !async_cause) return false; if (isr) { @@ -293,7 +307,29 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) ar9003_hw_bb_watchdog_read(ah); } + if (async_cause & AR_INTR_ASYNC_MASK_MCI) + ar9003_mci_get_isr(ah, masked); + if (sync_cause) { + if (sync_cause_p) + *sync_cause_p = sync_cause; + fatal_int = + (sync_cause & + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) + ? true : false; + + if (fatal_int) { + if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { + ath_dbg(common, ANY, + "received PCI FATAL interrupt\n"); + } + if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { + ath_dbg(common, ANY, + "received PCI PERR interrupt\n"); + } + *masked |= ATH9K_INT_FATAL; + } + if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); REG_WRITE(ah, AR_RC, 0); @@ -301,7 +337,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) } if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) - ath_dbg(common, ATH_DBG_INTERRUPT, + ath_dbg(common, INTERRUPT, "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); @@ -314,7 +350,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_status *ts) { - struct ar9003_txc *txc = (struct ar9003_txc *) ds; struct ar9003_txs *ads; u32 status; @@ -324,15 +359,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, if ((status & AR_TxDone) == 0) return -EINPROGRESS; - ts->qid = MS(ads->ds_info, AR_TxQcuNum); - if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid)) - ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; - else - return -ENOENT; + ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || (MS(ads->ds_info, AR_TxRxDesc) != 1)) { - ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, + ath_dbg(ath9k_hw_common(ah), XMIT, "Tx Descriptor error %x\n", ads->ds_info); memset(ads, 0, sizeof(*ads)); return -EIO; @@ -342,6 +373,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_seqnum = MS(status, AR_SeqNum); ts->tid = MS(status, AR_TxTid); + ts->qid = MS(ads->ds_info, AR_TxQcuNum); ts->desc_id = MS(ads->status1, AR_TxDescId); ts->ts_tstamp = ads->status4; ts->ts_status = 0; @@ -428,35 +460,30 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr; unsigned int phyerr; - /* TODO: byte swap on big endian for ar9300_10 */ - - if (!rxs) { - if ((rxsp->status11 & AR_RxDone) == 0) - return -EINPROGRESS; - - if (MS(rxsp->ds_info, AR_DescId) != 0x168c) - return -EINVAL; + if ((rxsp->status11 & AR_RxDone) == 0) + return -EINPROGRESS; - if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) - return -EINPROGRESS; + if (MS(rxsp->ds_info, AR_DescId) != 0x168c) + return -EINVAL; - return 0; - } + if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) + return -EINPROGRESS; rxs->rs_status = 0; rxs->rs_flags = 0; + rxs->flag = 0; rxs->rs_datalen = rxsp->status2 & AR_DataLen; rxs->rs_tstamp = rxsp->status3; /* XXX: Keycache */ rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); - rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00); - rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01); - rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02); - rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10); - rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11); - rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12); + rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00); + rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01); + rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02); + rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10); + rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11); + rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12); if (rxsp->status11 & AR_RxKeyIdxValid) rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); @@ -466,11 +493,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_rate = MS(rxsp->status1, AR_RxRate); rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; + rxs->rs_firstaggr = (rxsp->status11 & AR_RxFirstAggr) ? 1 : 0; rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); - rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0; - rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0; + rxs->flag |= (rxsp->status4 & AR_GI) ? RX_FLAG_SHORT_GI : 0; + rxs->flag |= (rxsp->status4 & AR_2040) ? RX_FLAG_40MHZ : 0; rxs->evm0 = rxsp->status6; rxs->evm1 = rxsp->status7; @@ -498,7 +526,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, */ if (rxsp->status11 & AR_CRCErr) rxs->rs_status |= ATH9K_RXERR_CRC; - else if (rxsp->status11 & AR_PHYErr) { + else if (rxsp->status11 & AR_DecryptCRCErr) + rxs->rs_status |= ATH9K_RXERR_DECRYPT; + else if (rxsp->status11 & AR_MichaelErr) + rxs->rs_status |= ATH9K_RXERR_MIC; + if (rxsp->status11 & AR_PHYErr) { phyerr = MS(rxsp->status11, AR_PHYErrCode); /* * If we reach a point here where AR_PostDelimCRCErr is @@ -520,15 +552,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, rxs->rs_status |= ATH9K_RXERR_PHY; rxs->rs_phyerr = phyerr; } - - } else if (rxsp->status11 & AR_DecryptCRCErr) - rxs->rs_status |= ATH9K_RXERR_DECRYPT; - else if (rxsp->status11 & AR_MichaelErr) - rxs->rs_status |= ATH9K_RXERR_MIC; - if (rxsp->status11 & AR_KeyMiss) - rxs->rs_status |= ATH9K_RXERR_KEYMISS; + } } + if (rxsp->status11 & AR_KeyMiss) + rxs->rs_status |= ATH9K_RXERR_KEYMISS; + return 0; } EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); @@ -540,7 +569,7 @@ void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) memset((void *) ah->ts_ring, 0, ah->ts_size * sizeof(struct ar9003_txs)); - ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, + ath_dbg(ath9k_hw_common(ah), XMIT, "TS Start 0x%x End 0x%x Virt %p, Size %d\n", ah->ts_paddr_start, ah->ts_paddr_end, ah->ts_ring, ah->ts_size); @@ -551,7 +580,7 @@ void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, u32 ts_paddr_start, - u8 size) + u16 size) { ah->ts_paddr_start = ts_paddr_start; |
