diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/txrx.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.c | 67 |
1 files changed, 22 insertions, 45 deletions
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 68b6faefd1d8..5ae373a1e294 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
| @@ -44,40 +44,39 @@ out: | |||
| 44 | spin_unlock_bh(&ar->data_lock); | 44 | spin_unlock_bh(&ar->data_lock); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | 47 | void ath10k_txrx_tx_unref(struct ath10k_htt *htt, |
| 48 | const struct htt_tx_done *tx_done) | ||
| 48 | { | 49 | { |
| 49 | struct device *dev = htt->ar->dev; | 50 | struct device *dev = htt->ar->dev; |
| 50 | struct ieee80211_tx_info *info; | 51 | struct ieee80211_tx_info *info; |
| 51 | struct sk_buff *txfrag = ATH10K_SKB_CB(txdesc)->htt.txfrag; | 52 | struct ath10k_skb_cb *skb_cb; |
| 52 | struct sk_buff *msdu = ATH10K_SKB_CB(txdesc)->htt.msdu; | 53 | struct sk_buff *msdu; |
| 53 | int ret; | 54 | int ret; |
| 54 | 55 | ||
| 55 | if (ATH10K_SKB_CB(txdesc)->htt.refcount == 0) | 56 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", |
| 56 | return; | 57 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); |
| 57 | |||
| 58 | ATH10K_SKB_CB(txdesc)->htt.refcount--; | ||
| 59 | 58 | ||
| 60 | if (ATH10K_SKB_CB(txdesc)->htt.refcount > 0) | 59 | if (tx_done->msdu_id >= htt->max_num_pending_tx) { |
| 60 | ath10k_warn("warning: msdu_id %d too big, ignoring\n", | ||
| 61 | tx_done->msdu_id); | ||
| 61 | return; | 62 | return; |
| 62 | |||
| 63 | if (txfrag) { | ||
| 64 | ret = ath10k_skb_unmap(dev, txfrag); | ||
| 65 | if (ret) | ||
| 66 | ath10k_warn("txfrag unmap failed (%d)\n", ret); | ||
| 67 | |||
| 68 | dev_kfree_skb_any(txfrag); | ||
| 69 | } | 63 | } |
| 70 | 64 | ||
| 65 | msdu = htt->pending_tx[tx_done->msdu_id]; | ||
| 66 | skb_cb = ATH10K_SKB_CB(msdu); | ||
| 67 | |||
| 71 | ret = ath10k_skb_unmap(dev, msdu); | 68 | ret = ath10k_skb_unmap(dev, msdu); |
| 72 | if (ret) | 69 | if (ret) |
| 73 | ath10k_warn("data skb unmap failed (%d)\n", ret); | 70 | ath10k_warn("data skb unmap failed (%d)\n", ret); |
| 74 | 71 | ||
| 72 | if (skb_cb->htt.frag_len) | ||
| 73 | skb_pull(msdu, skb_cb->htt.frag_len + skb_cb->htt.pad_len); | ||
| 74 | |||
| 75 | ath10k_report_offchan_tx(htt->ar, msdu); | 75 | ath10k_report_offchan_tx(htt->ar, msdu); |
| 76 | 76 | ||
| 77 | info = IEEE80211_SKB_CB(msdu); | 77 | info = IEEE80211_SKB_CB(msdu); |
| 78 | memset(&info->status, 0, sizeof(info->status)); | ||
| 79 | 78 | ||
| 80 | if (ATH10K_SKB_CB(txdesc)->htt.discard) { | 79 | if (tx_done->discard) { |
| 81 | ieee80211_free_txskb(htt->ar->hw, msdu); | 80 | ieee80211_free_txskb(htt->ar->hw, msdu); |
| 82 | goto exit; | 81 | goto exit; |
| 83 | } | 82 | } |
| @@ -85,7 +84,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | |||
| 85 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) | 84 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
| 86 | info->flags |= IEEE80211_TX_STAT_ACK; | 85 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 87 | 86 | ||
| 88 | if (ATH10K_SKB_CB(txdesc)->htt.no_ack) | 87 | if (tx_done->no_ack) |
| 89 | info->flags &= ~IEEE80211_TX_STAT_ACK; | 88 | info->flags &= ~IEEE80211_TX_STAT_ACK; |
| 90 | 89 | ||
| 91 | ieee80211_tx_status(htt->ar->hw, msdu); | 90 | ieee80211_tx_status(htt->ar->hw, msdu); |
| @@ -93,36 +92,12 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc) | |||
| 93 | 92 | ||
| 94 | exit: | 93 | exit: |
| 95 | spin_lock_bh(&htt->tx_lock); | 94 | spin_lock_bh(&htt->tx_lock); |
| 96 | htt->pending_tx[ATH10K_SKB_CB(txdesc)->htt.msdu_id] = NULL; | 95 | htt->pending_tx[tx_done->msdu_id] = NULL; |
| 97 | ath10k_htt_tx_free_msdu_id(htt, ATH10K_SKB_CB(txdesc)->htt.msdu_id); | 96 | ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); |
| 98 | __ath10k_htt_tx_dec_pending(htt); | 97 | __ath10k_htt_tx_dec_pending(htt); |
| 99 | if (bitmap_empty(htt->used_msdu_ids, htt->max_num_pending_tx)) | 98 | if (htt->num_pending_tx == 0) |
| 100 | wake_up(&htt->empty_tx_wq); | 99 | wake_up(&htt->empty_tx_wq); |
| 101 | spin_unlock_bh(&htt->tx_lock); | 100 | spin_unlock_bh(&htt->tx_lock); |
| 102 | |||
| 103 | dev_kfree_skb_any(txdesc); | ||
| 104 | } | ||
| 105 | |||
| 106 | void ath10k_txrx_tx_completed(struct ath10k_htt *htt, | ||
| 107 | const struct htt_tx_done *tx_done) | ||
| 108 | { | ||
| 109 | struct sk_buff *txdesc; | ||
| 110 | |||
| 111 | ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", | ||
| 112 | tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); | ||
| 113 | |||
| 114 | if (tx_done->msdu_id >= htt->max_num_pending_tx) { | ||
| 115 | ath10k_warn("warning: msdu_id %d too big, ignoring\n", | ||
| 116 | tx_done->msdu_id); | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | txdesc = htt->pending_tx[tx_done->msdu_id]; | ||
| 121 | |||
| 122 | ATH10K_SKB_CB(txdesc)->htt.discard = tx_done->discard; | ||
| 123 | ATH10K_SKB_CB(txdesc)->htt.no_ack = tx_done->no_ack; | ||
| 124 | |||
| 125 | ath10k_txrx_tx_unref(htt, txdesc); | ||
| 126 | } | 101 | } |
| 127 | 102 | ||
| 128 | static const u8 rx_legacy_rate_idx[] = { | 103 | static const u8 rx_legacy_rate_idx[] = { |
| @@ -293,6 +268,8 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) | |||
| 293 | status->vht_nss, | 268 | status->vht_nss, |
| 294 | status->freq, | 269 | status->freq, |
| 295 | status->band); | 270 | status->band); |
| 271 | ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", | ||
| 272 | info->skb->data, info->skb->len); | ||
| 296 | 273 | ||
| 297 | ieee80211_rx(ar->hw, info->skb); | 274 | ieee80211_rx(ar->hw, info->skb); |
| 298 | } | 275 | } |
