Commit 994089db authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by John W. Linville

ath9k_hw: Fill descriptor abstrations for AR9003

Signed-off-by: default avatarVasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b622a720
......@@ -168,23 +168,169 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
return true;
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
{
int checksum;
checksum = ads->info + ads->link
+ ads->data0 + ads->ctl3
+ ads->data1 + ads->ctl5
+ ads->data2 + ads->ctl7
+ ads->data3 + ads->ctl9;
return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
}
static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int descid = 0;
ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
(1 << AR_TxRxDesc_S) |
(1 << AR_CtrlStat_S) |
(qcu << AR_TxQcuNum_S) | 0x17;
ads->data0 = buf_addr;
ads->data1 = 0;
ads->data2 = 0;
ads->data3 = 0;
ads->ctl3 = (seglen << AR_BufLen_S);
ads->ctl3 &= AR_BufLen;
/* Fill in pointer checksum and descriptor id */
ads->ctl10 = ar9003_calc_ptr_chksum(ads);
ads->ctl10 |= (descid << AR_TxDescId_S);
if (is_firstseg) {
ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
} else if (is_lastseg) {
ads->ctl11 = 0;
ads->ctl12 = 0;
ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
} else {
/* XXX Intermediate descriptor in a multi-descriptor frame.*/
ads->ctl11 = 0;
ads->ctl12 = AR_TxMore;
ads->ctl13 = 0;
ads->ctl14 = 0;
}
}
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar9003_txs *ads;
ads = &ah->ts_ring[ah->ts_tail];
if ((ads->status8 & AR_TxDone) == 0)
return -EINPROGRESS;
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_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
"Tx Descriptor error %x\n", ads->ds_info);
memset(ads, 0, sizeof(*ads));
return -EIO;
}
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
ts->ts_flags = 0;
if (ads->status3 & AR_ExcessiveRetries)
ts->ts_status |= ATH9K_TXERR_XRETRY;
if (ads->status3 & AR_Filtered)
ts->ts_status |= ATH9K_TXERR_FILT;
if (ads->status3 & AR_FIFOUnderrun) {
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status8 & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
if (ads->status3 & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
if (ads->status3 & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
if (ads->status3 & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status3 & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status2 & AR_TxBaStatus) {
ts->ts_flags |= ATH9K_TX_BA;
ts->ba_low = ads->status5;
ts->ba_high = ads->status6;
}
ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
ts->ts_antenna = 0;
ts->tid = MS(ads->status8, AR_TxTid);
memset(ads, 0, sizeof(*ads));
return 0;
}
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags)
u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
txpower += ah->txpower_indexoffset;
if (txpower > 63)
txpower = 63;
ads->ctl11 = (pktlen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txpower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
ads->ctl12 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ctl17 = SM(keyType, AR_EncrType);
ads->ctl18 = 0;
ads->ctl19 = AR_Not_Sounding;
ads->ctl20 = 0;
ads->ctl21 = 0;
ads->ctl22 = 0;
}
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
......@@ -194,41 +340,119 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
u_int32_t ctl11;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ctl11 = ads->ctl11;
if (flags & ATH9K_TXDESC_RTSENA) {
ctl11 &= ~AR_CTSEnable;
ctl11 |= AR_RTSEnable;
} else {
ctl11 &= ~AR_RTSEnable;
ctl11 |= AR_CTSEnable;
}
ads->ctl11 = ctl11;
} else {
ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ctl13 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ctl14 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ctl15 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ctl16 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ctl18 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
ads->ctl19 = AR_Not_Sounding;
last_ads->ctl13 = ads->ctl13;
last_ads->ctl14 = ads->ctl14;
}
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
ads->ctl17 &= ~AR_AggrLen;
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int ctl17;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
/*
* We use a stack variable to manipulate ctl6 to reduce uncached
* read modify, modfiy, write.
*/
ctl17 = ads->ctl17;
ctl17 &= ~AR_PadDelim;
ctl17 |= SM(numDelims, AR_PadDelim);
ads->ctl17 = ctl17;
}
static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= AR_IsAggr;
ads->ctl12 &= ~AR_MoreAggr;
ads->ctl17 &= ~AR_PadDelim;
}
static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
}
static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
u32 burstDuration)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl13 &= ~AR_BurstDur;
ads->ctl13 |= SM(burstDuration, AR_BurstDur);
}
static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
u32 vmf)
u32 vmf)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
if (vmf)
ads->ctl11 |= AR_VirtMoreFrag;
else
ads->ctl11 &= ~AR_VirtMoreFrag;
}
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
......
......@@ -20,7 +20,25 @@
#define AR_DescId 0xffff0000
#define AR_DescId_S 16
#define AR_CtrlStat 0x00004000
#define AR_CtrlStat_S 14
#define AR_TxRxDesc 0x00008000
#define AR_TxRxDesc_S 15
#define AR_TxQcuNum 0x00000f00
#define AR_TxQcuNum_S 8
#define AR_BufLen 0x0fff0000
#define AR_BufLen_S 16
#define AR_TxDescId 0xffff0000
#define AR_TxDescId_S 16
#define AR_TxPtrChkSum 0x0000ffff
#define AR_TxTid 0xf0000000
#define AR_TxTid_S 28
#define AR_LowRxChain 0x00004000
#define AR_Not_Sounding 0x20000000
#define MAP_ISR_S2_CST 6
#define MAP_ISR_S2_GTT 6
......@@ -30,6 +48,8 @@
#define MAP_ISR_S2_DTIM 7
#define MAP_ISR_S2_TSFOOR 4
#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
struct ar9003_rxs {
u32 ds_info;
u32 status1;
......
......@@ -116,7 +116,10 @@ struct ath_tx_status {
int8_t ts_rssi_ext0;
int8_t ts_rssi_ext1;
int8_t ts_rssi_ext2;
u8 pad[3];
u8 qid;
u16 desc_id;
u8 tid;
u8 pad[2];
u32 ba_low;
u32 ba_high;
u32 evm0;
......@@ -260,7 +263,7 @@ struct ath_desc {
#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
#define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
#define ATH9K_TXDESC_CAB 0x0400
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
#define ATH9K_RXDESC_INTREQ 0x0020
......
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