diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-09-30 05:24:23 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-09-30 13:17:48 -0400 |
commit | 315dd1149b6048cec805667f511726bbe8e5c975 (patch) | |
tree | 6bc8a44734b05bda1b501d820af8d3a675a9912b | |
parent | 4d9f634b02e4240f86719f30e4c9e62f6a4c4d36 (diff) |
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>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9002_mac.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mac.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/dynack.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw-ops.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 2 |
7 files changed, 49 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 669cb3747208..2a93519f4bdf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
381 | ts->evm1 = ads->AR_TxEVM1; | 381 | ts->evm1 = ads->AR_TxEVM1; |
382 | ts->evm2 = ads->AR_TxEVM2; | 382 | ts->evm2 = ads->AR_TxEVM2; |
383 | 383 | ||
384 | status = ACCESS_ONCE(ads->ds_ctl4); | ||
385 | ts->duration[0] = MS(status, AR_PacketDur0); | ||
386 | ts->duration[1] = MS(status, AR_PacketDur1); | ||
387 | status = ACCESS_ONCE(ads->ds_ctl5); | ||
388 | ts->duration[2] = MS(status, AR_PacketDur2); | ||
389 | ts->duration[3] = MS(status, AR_PacketDur3); | ||
390 | |||
391 | return 0; | 384 | return 0; |
392 | } | 385 | } |
393 | 386 | ||
387 | static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index) | ||
388 | { | ||
389 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
390 | |||
391 | switch (index) { | ||
392 | case 0: | ||
393 | return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0); | ||
394 | case 1: | ||
395 | return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1); | ||
396 | case 2: | ||
397 | return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2); | ||
398 | case 3: | ||
399 | return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3); | ||
400 | default: | ||
401 | return -1; | ||
402 | } | ||
403 | } | ||
404 | |||
394 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 405 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
395 | u32 size, u32 flags) | 406 | u32 size, u32 flags) |
396 | { | 407 | { |
@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | |||
413 | ops->get_isr = ar9002_hw_get_isr; | 424 | ops->get_isr = ar9002_hw_get_isr; |
414 | ops->set_txdesc = ar9002_set_txdesc; | 425 | ops->set_txdesc = ar9002_set_txdesc; |
415 | ops->proc_txdesc = ar9002_hw_proc_txdesc; | 426 | ops->proc_txdesc = ar9002_hw_proc_txdesc; |
427 | ops->get_duration = ar9002_hw_get_duration; | ||
416 | } | 428 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index e5f7c11fa144..057b1657c428 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
355 | struct ath_tx_status *ts) | 355 | struct ath_tx_status *ts) |
356 | { | 356 | { |
357 | struct ar9003_txs *ads; | 357 | struct ar9003_txs *ads; |
358 | struct ar9003_txc *adc; | ||
359 | u32 status; | 358 | u32 status; |
360 | 359 | ||
361 | ads = &ah->ts_ring[ah->ts_tail]; | 360 | ads = &ah->ts_ring[ah->ts_tail]; |
362 | adc = (struct ar9003_txc *)ads; | ||
363 | 361 | ||
364 | status = ACCESS_ONCE(ads->status8); | 362 | status = ACCESS_ONCE(ads->status8); |
365 | if ((status & AR_TxDone) == 0) | 363 | if ((status & AR_TxDone) == 0) |
@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
428 | ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); | 426 | ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); |
429 | ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); | 427 | ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); |
430 | 428 | ||
431 | status = ACCESS_ONCE(adc->ctl15); | ||
432 | ts->duration[0] = MS(status, AR_PacketDur0); | ||
433 | ts->duration[1] = MS(status, AR_PacketDur1); | ||
434 | status = ACCESS_ONCE(adc->ctl16); | ||
435 | ts->duration[2] = MS(status, AR_PacketDur2); | ||
436 | ts->duration[3] = MS(status, AR_PacketDur3); | ||
437 | |||
438 | memset(ads, 0, sizeof(*ads)); | 429 | memset(ads, 0, sizeof(*ads)); |
439 | 430 | ||
440 | return 0; | 431 | return 0; |
441 | } | 432 | } |
442 | 433 | ||
434 | static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index) | ||
435 | { | ||
436 | const struct ar9003_txc *adc = ds; | ||
437 | |||
438 | switch (index) { | ||
439 | case 0: | ||
440 | return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0); | ||
441 | case 1: | ||
442 | return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1); | ||
443 | case 2: | ||
444 | return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2); | ||
445 | case 3: | ||
446 | return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3); | ||
447 | default: | ||
448 | return 0; | ||
449 | } | ||
450 | } | ||
451 | |||
443 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | 452 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw) |
444 | { | 453 | { |
445 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); | 454 | struct ath_hw_ops *ops = ath9k_hw_ops(hw); |
@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
449 | ops->get_isr = ar9003_hw_get_isr; | 458 | ops->get_isr = ar9003_hw_get_isr; |
450 | ops->set_txdesc = ar9003_set_txdesc; | 459 | ops->set_txdesc = ar9003_set_txdesc; |
451 | ops->proc_txdesc = ar9003_hw_proc_txdesc; | 460 | ops->proc_txdesc = ar9003_hw_proc_txdesc; |
461 | ops->get_duration = ar9003_hw_get_duration; | ||
452 | } | 462 | } |
453 | 463 | ||
454 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 464 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c index 6ae8e0bc9e1f..22b3cc4c27cd 100644 --- a/drivers/net/wireless/ath/ath9k/dynack.c +++ b/drivers/net/wireless/ath/ath9k/dynack.c | |||
@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb, | |||
202 | ridx = ts->ts_rateindex; | 202 | ridx = ts->ts_rateindex; |
203 | 203 | ||
204 | da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp; | 204 | da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp; |
205 | da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex]; | 205 | da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration; |
206 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1); | 206 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1); |
207 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2); | 207 | ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2); |
208 | 208 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index a47ea8423f1e..8e85efeaeffc 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, | |||
67 | return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); | 67 | return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds, | ||
71 | int index) | ||
72 | { | ||
73 | return ath9k_hw_ops(ah)->get_duration(ah, ds, index); | ||
74 | } | ||
75 | |||
70 | static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | 76 | static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, |
71 | struct ath_hw_antcomb_conf *antconf) | 77 | struct ath_hw_antcomb_conf *antconf) |
72 | { | 78 | { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b9eef3362fbb..975074fc11bc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -691,6 +691,7 @@ struct ath_hw_ops { | |||
691 | struct ath_tx_info *i); | 691 | struct ath_tx_info *i); |
692 | int (*proc_txdesc)(struct ath_hw *ah, void *ds, | 692 | int (*proc_txdesc)(struct ath_hw *ah, void *ds, |
693 | struct ath_tx_status *ts); | 693 | struct ath_tx_status *ts); |
694 | int (*get_duration)(struct ath_hw *ah, const void *ds, int index); | ||
694 | void (*antdiv_comb_conf_get)(struct ath_hw *ah, | 695 | void (*antdiv_comb_conf_get)(struct ath_hw *ah, |
695 | struct ath_hw_antcomb_conf *antconf); | 696 | struct ath_hw_antcomb_conf *antconf); |
696 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, | 697 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index cd05a7791073..aa69ceaad0be 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -121,7 +121,7 @@ struct ath_tx_status { | |||
121 | u32 evm0; | 121 | u32 evm0; |
122 | u32 evm1; | 122 | u32 evm1; |
123 | u32 evm2; | 123 | u32 evm2; |
124 | u32 duration[4]; | 124 | u32 duration; |
125 | }; | 125 | }; |
126 | 126 | ||
127 | struct ath_rx_status { | 127 | struct ath_rx_status { |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7193a00d3bca..151ae49fa57e 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -683,6 +683,8 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, | |||
683 | if (bf_is_ampdu_not_probing(bf)) | 683 | if (bf_is_ampdu_not_probing(bf)) |
684 | txq->axq_ampdu_depth--; | 684 | txq->axq_ampdu_depth--; |
685 | 685 | ||
686 | ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, | ||
687 | ts->ts_rateindex); | ||
686 | if (!bf_isampdu(bf)) { | 688 | if (!bf_isampdu(bf)) { |
687 | if (!flush) { | 689 | if (!flush) { |
688 | info = IEEE80211_SKB_CB(bf->bf_mpdu); | 690 | info = IEEE80211_SKB_CB(bf->bf_mpdu); |