ath9k: fix getting tx duration for dynack
On AR9003, tx control and tx status are in separate descriptor rings. Tx duration is extracted from the tx control descriptor data, which ar9003_hw_proc_txdesc cannot access. Fix getting the duration by adding a separate callback for it. Acked-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4d9f634b02
commit
315dd1149b
|
@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||||
ts->evm1 = ads->AR_TxEVM1;
|
ts->evm1 = ads->AR_TxEVM1;
|
||||||
ts->evm2 = ads->AR_TxEVM2;
|
ts->evm2 = ads->AR_TxEVM2;
|
||||||
|
|
||||||
status = ACCESS_ONCE(ads->ds_ctl4);
|
|
||||||
ts->duration[0] = MS(status, AR_PacketDur0);
|
|
||||||
ts->duration[1] = MS(status, AR_PacketDur1);
|
|
||||||
status = ACCESS_ONCE(ads->ds_ctl5);
|
|
||||||
ts->duration[2] = MS(status, AR_PacketDur2);
|
|
||||||
ts->duration[3] = MS(status, AR_PacketDur3);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
|
||||||
|
{
|
||||||
|
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0);
|
||||||
|
case 1:
|
||||||
|
return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1);
|
||||||
|
case 2:
|
||||||
|
return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2);
|
||||||
|
case 3:
|
||||||
|
return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3);
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||||
u32 size, u32 flags)
|
u32 size, u32 flags)
|
||||||
{
|
{
|
||||||
|
@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
|
||||||
ops->get_isr = ar9002_hw_get_isr;
|
ops->get_isr = ar9002_hw_get_isr;
|
||||||
ops->set_txdesc = ar9002_set_txdesc;
|
ops->set_txdesc = ar9002_set_txdesc;
|
||||||
ops->proc_txdesc = ar9002_hw_proc_txdesc;
|
ops->proc_txdesc = ar9002_hw_proc_txdesc;
|
||||||
|
ops->get_duration = ar9002_hw_get_duration;
|
||||||
}
|
}
|
||||||
|
|
|
@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||||
struct ath_tx_status *ts)
|
struct ath_tx_status *ts)
|
||||||
{
|
{
|
||||||
struct ar9003_txs *ads;
|
struct ar9003_txs *ads;
|
||||||
struct ar9003_txc *adc;
|
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
ads = &ah->ts_ring[ah->ts_tail];
|
ads = &ah->ts_ring[ah->ts_tail];
|
||||||
adc = (struct ar9003_txc *)ads;
|
|
||||||
|
|
||||||
status = ACCESS_ONCE(ads->status8);
|
status = ACCESS_ONCE(ads->status8);
|
||||||
if ((status & AR_TxDone) == 0)
|
if ((status & AR_TxDone) == 0)
|
||||||
|
@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||||
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
||||||
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
||||||
|
|
||||||
status = ACCESS_ONCE(adc->ctl15);
|
|
||||||
ts->duration[0] = MS(status, AR_PacketDur0);
|
|
||||||
ts->duration[1] = MS(status, AR_PacketDur1);
|
|
||||||
status = ACCESS_ONCE(adc->ctl16);
|
|
||||||
ts->duration[2] = MS(status, AR_PacketDur2);
|
|
||||||
ts->duration[3] = MS(status, AR_PacketDur3);
|
|
||||||
|
|
||||||
memset(ads, 0, sizeof(*ads));
|
memset(ads, 0, sizeof(*ads));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
|
||||||
|
{
|
||||||
|
const struct ar9003_txc *adc = ds;
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0);
|
||||||
|
case 1:
|
||||||
|
return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1);
|
||||||
|
case 2:
|
||||||
|
return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2);
|
||||||
|
case 3:
|
||||||
|
return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
|
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
|
||||||
{
|
{
|
||||||
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
|
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
|
||||||
|
@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
|
||||||
ops->get_isr = ar9003_hw_get_isr;
|
ops->get_isr = ar9003_hw_get_isr;
|
||||||
ops->set_txdesc = ar9003_set_txdesc;
|
ops->set_txdesc = ar9003_set_txdesc;
|
||||||
ops->proc_txdesc = ar9003_hw_proc_txdesc;
|
ops->proc_txdesc = ar9003_hw_proc_txdesc;
|
||||||
|
ops->get_duration = ar9003_hw_get_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
|
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
|
||||||
|
|
|
@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
|
||||||
ridx = ts->ts_rateindex;
|
ridx = ts->ts_rateindex;
|
||||||
|
|
||||||
da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
|
da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
|
||||||
da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex];
|
da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration;
|
||||||
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
|
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
|
||||||
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
|
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
|
||||||
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
|
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
return ath9k_hw_ops(ah)->get_duration(ah, ds, index);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
|
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
|
||||||
struct ath_hw_antcomb_conf *antconf)
|
struct ath_hw_antcomb_conf *antconf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -691,6 +691,7 @@ struct ath_hw_ops {
|
||||||
struct ath_tx_info *i);
|
struct ath_tx_info *i);
|
||||||
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
|
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
|
||||||
struct ath_tx_status *ts);
|
struct ath_tx_status *ts);
|
||||||
|
int (*get_duration)(struct ath_hw *ah, const void *ds, int index);
|
||||||
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
|
void (*antdiv_comb_conf_get)(struct ath_hw *ah,
|
||||||
struct ath_hw_antcomb_conf *antconf);
|
struct ath_hw_antcomb_conf *antconf);
|
||||||
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
|
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
|
||||||
|
|
|
@ -121,7 +121,7 @@ struct ath_tx_status {
|
||||||
u32 evm0;
|
u32 evm0;
|
||||||
u32 evm1;
|
u32 evm1;
|
||||||
u32 evm2;
|
u32 evm2;
|
||||||
u32 duration[4];
|
u32 duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_rx_status {
|
struct ath_rx_status {
|
||||||
|
|
|
@ -683,6 +683,8 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
|
||||||
if (bf_is_ampdu_not_probing(bf))
|
if (bf_is_ampdu_not_probing(bf))
|
||||||
txq->axq_ampdu_depth--;
|
txq->axq_ampdu_depth--;
|
||||||
|
|
||||||
|
ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
|
||||||
|
ts->ts_rateindex);
|
||||||
if (!bf_isampdu(bf)) {
|
if (!bf_isampdu(bf)) {
|
||||||
if (!flush) {
|
if (!flush) {
|
||||||
info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||||
|
|
Loading…
Reference in New Issue