diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3cea3f76e373..e9e99f730ca8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
357 | struct ath_frame_info *fi; | 357 | struct ath_frame_info *fi; |
358 | int nframes; | 358 | int nframes; |
359 | u8 tidno; | 359 | u8 tidno; |
360 | bool clear_filter; | ||
360 | 361 | ||
361 | skb = bf->bf_mpdu; | 362 | skb = bf->bf_mpdu; |
362 | hdr = (struct ieee80211_hdr *)skb->data; | 363 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
441 | /* transmit completion */ | 442 | /* transmit completion */ |
442 | acked_cnt++; | 443 | acked_cnt++; |
443 | } else { | 444 | } else { |
444 | if (!(tid->state & AGGR_CLEANUP) && retry) { | 445 | if ((tid->state & AGGR_CLEANUP) || !retry) { |
445 | if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
446 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
447 | txpending = 1; | ||
448 | } else { | ||
449 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
450 | txfail = 1; | ||
451 | sendbar = 1; | ||
452 | txfail_cnt++; | ||
453 | } | ||
454 | } else { | ||
455 | /* | 446 | /* |
456 | * cleanup in progress, just fail | 447 | * cleanup in progress, just fail |
457 | * the un-acked sub-frames | 448 | * the un-acked sub-frames |
458 | */ | 449 | */ |
459 | txfail = 1; | 450 | txfail = 1; |
451 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
452 | if (!(ts->ts_status & ATH9K_TXERR_FILT) || | ||
453 | !an->sleeping) | ||
454 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
455 | |||
456 | clear_filter = true; | ||
457 | txpending = 1; | ||
458 | } else { | ||
459 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
460 | txfail = 1; | ||
461 | sendbar = 1; | ||
462 | txfail_cnt++; | ||
460 | } | 463 | } |
461 | } | 464 | } |
462 | 465 | ||
@@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
496 | !txfail, sendbar); | 499 | !txfail, sendbar); |
497 | } else { | 500 | } else { |
498 | /* retry the un-acked ones */ | 501 | /* retry the un-acked ones */ |
502 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); | ||
499 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 503 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { |
500 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 504 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
501 | struct ath_buf *tbf; | 505 | struct ath_buf *tbf; |
@@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
546 | 550 | ||
547 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 551 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
548 | if (!list_empty(&bf_pending)) { | 552 | if (!list_empty(&bf_pending)) { |
553 | if (an->sleeping) | ||
554 | ieee80211_sta_set_tim(sta); | ||
555 | |||
549 | spin_lock_bh(&txq->axq_lock); | 556 | spin_lock_bh(&txq->axq_lock); |
557 | if (clear_filter) | ||
558 | tid->ac->clear_ps_filter = true; | ||
550 | list_splice(&bf_pending, &tid->buf_q); | 559 | list_splice(&bf_pending, &tid->buf_q); |
551 | ath_tx_queue_tid(txq, tid); | 560 | ath_tx_queue_tid(txq, tid); |
552 | spin_unlock_bh(&txq->axq_lock); | 561 | spin_unlock_bh(&txq->axq_lock); |
@@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
816 | bf = list_first_entry(&bf_q, struct ath_buf, list); | 825 | bf = list_first_entry(&bf_q, struct ath_buf, list); |
817 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); | 826 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); |
818 | 827 | ||
828 | if (tid->ac->clear_ps_filter) { | ||
829 | tid->ac->clear_ps_filter = false; | ||
830 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); | ||
831 | } | ||
832 | |||
819 | /* if only one frame, send as non-aggregate */ | 833 | /* if only one frame, send as non-aggregate */ |
820 | if (bf == bf->bf_lastbf) { | 834 | if (bf == bf->bf_lastbf) { |
821 | fi = get_frame_info(bf->bf_mpdu); | 835 | fi = get_frame_info(bf->bf_mpdu); |
@@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
896 | ath_tx_flush_tid(sc, txtid); | 910 | ath_tx_flush_tid(sc, txtid); |
897 | } | 911 | } |
898 | 912 | ||
913 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | ||
914 | { | ||
915 | struct ath_atx_tid *tid; | ||
916 | struct ath_atx_ac *ac; | ||
917 | struct ath_txq *txq; | ||
918 | bool buffered = false; | ||
919 | int tidno; | ||
920 | |||
921 | for (tidno = 0, tid = &an->tid[tidno]; | ||
922 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
923 | |||
924 | if (!tid->sched) | ||
925 | continue; | ||
926 | |||
927 | ac = tid->ac; | ||
928 | txq = ac->txq; | ||
929 | |||
930 | spin_lock_bh(&txq->axq_lock); | ||
931 | |||
932 | if (!list_empty(&tid->buf_q)) | ||
933 | buffered = true; | ||
934 | |||
935 | tid->sched = false; | ||
936 | list_del(&tid->list); | ||
937 | |||
938 | if (ac->sched) { | ||
939 | ac->sched = false; | ||
940 | list_del(&ac->list); | ||
941 | } | ||
942 | |||
943 | spin_unlock_bh(&txq->axq_lock); | ||
944 | } | ||
945 | |||
946 | return buffered; | ||
947 | } | ||
948 | |||
949 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | ||
950 | { | ||
951 | struct ath_atx_tid *tid; | ||
952 | struct ath_atx_ac *ac; | ||
953 | struct ath_txq *txq; | ||
954 | int tidno; | ||
955 | |||
956 | for (tidno = 0, tid = &an->tid[tidno]; | ||
957 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
958 | |||
959 | ac = tid->ac; | ||
960 | txq = ac->txq; | ||
961 | |||
962 | spin_lock_bh(&txq->axq_lock); | ||
963 | ac->clear_ps_filter = true; | ||
964 | |||
965 | if (!list_empty(&tid->buf_q) && !tid->paused) { | ||
966 | ath_tx_queue_tid(txq, tid); | ||
967 | ath_txq_schedule(sc, txq); | ||
968 | } | ||
969 | |||
970 | spin_unlock_bh(&txq->axq_lock); | ||
971 | } | ||
972 | } | ||
973 | |||
899 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 974 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
900 | { | 975 | { |
901 | struct ath_atx_tid *txtid; | 976 | struct ath_atx_tid *txtid; |
@@ -1451,7 +1526,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1451 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | 1526 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
1452 | struct ieee80211_hdr *hdr; | 1527 | struct ieee80211_hdr *hdr; |
1453 | struct ath_frame_info *fi = get_frame_info(skb); | 1528 | struct ath_frame_info *fi = get_frame_info(skb); |
1454 | struct ath_node *an; | 1529 | struct ath_node *an = NULL; |
1455 | struct ath_atx_tid *tid; | 1530 | struct ath_atx_tid *tid; |
1456 | enum ath9k_key_type keytype; | 1531 | enum ath9k_key_type keytype; |
1457 | u16 seqno = 0; | 1532 | u16 seqno = 0; |
@@ -1459,11 +1534,13 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1459 | 1534 | ||
1460 | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); | 1535 | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
1461 | 1536 | ||
1537 | if (sta) | ||
1538 | an = (struct ath_node *) sta->drv_priv; | ||
1539 | |||
1462 | hdr = (struct ieee80211_hdr *)skb->data; | 1540 | hdr = (struct ieee80211_hdr *)skb->data; |
1463 | if (sta && ieee80211_is_data_qos(hdr->frame_control) && | 1541 | if (an && ieee80211_is_data_qos(hdr->frame_control) && |
1464 | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { | 1542 | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { |
1465 | 1543 | ||
1466 | an = (struct ath_node *) sta->drv_priv; | ||
1467 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; | 1544 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
1468 | 1545 | ||
1469 | /* | 1546 | /* |
@@ -1479,6 +1556,8 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1479 | memset(fi, 0, sizeof(*fi)); | 1556 | memset(fi, 0, sizeof(*fi)); |
1480 | if (hw_key) | 1557 | if (hw_key) |
1481 | fi->keyix = hw_key->hw_key_idx; | 1558 | fi->keyix = hw_key->hw_key_idx; |
1559 | else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) | ||
1560 | fi->keyix = an->ps_key; | ||
1482 | else | 1561 | else |
1483 | fi->keyix = ATH9K_TXKEYIX_INVALID; | 1562 | fi->keyix = ATH9K_TXKEYIX_INVALID; |
1484 | fi->keytype = keytype; | 1563 | fi->keytype = keytype; |
@@ -1491,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff *skb) | |||
1491 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1570 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1492 | int flags = 0; | 1571 | int flags = 0; |
1493 | 1572 | ||
1494 | flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ | ||
1495 | flags |= ATH9K_TXDESC_INTREQ; | 1573 | flags |= ATH9K_TXDESC_INTREQ; |
1496 | 1574 | ||
1497 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) | 1575 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
@@ -1754,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1754 | if (txctl->paprd) | 1832 | if (txctl->paprd) |
1755 | bf->bf_state.bfs_paprd_timestamp = jiffies; | 1833 | bf->bf_state.bfs_paprd_timestamp = jiffies; |
1756 | 1834 | ||
1835 | if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) | ||
1836 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); | ||
1837 | |||
1757 | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); | 1838 | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); |
1758 | } | 1839 | } |
1759 | 1840 | ||