diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/txrx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index fbfb608e48ab..576e7c42ed65 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -49,25 +49,25 @@ out: spin_unlock_bh(&ar->data_lock); } -void ath10k_txrx_tx_unref(struct ath10k_htt *htt, - const struct htt_tx_done *tx_done) +int ath10k_txrx_tx_unref(struct ath10k_htt *htt, + const struct htt_tx_done *tx_done) { struct ath10k *ar = htt->ar; struct device *dev = ar->dev; struct ieee80211_tx_info *info; + struct ieee80211_txq *txq; struct ath10k_skb_cb *skb_cb; + struct ath10k_txq *artxq; struct sk_buff *msdu; - bool limit_mgmt_desc = false; ath10k_dbg(ar, ATH10K_DBG_HTT, - "htt tx completion msdu_id %u discard %d no_ack %d success %d\n", - tx_done->msdu_id, !!tx_done->discard, - !!tx_done->no_ack, !!tx_done->success); + "htt tx completion msdu_id %u status %d\n", + tx_done->msdu_id, tx_done->status); if (tx_done->msdu_id >= htt->max_num_pending_tx) { ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n", tx_done->msdu_id); - return; + return -EINVAL; } spin_lock_bh(&htt->tx_lock); @@ -76,17 +76,18 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n", tx_done->msdu_id); spin_unlock_bh(&htt->tx_lock); - return; + return -ENOENT; } skb_cb = ATH10K_SKB_CB(msdu); + txq = skb_cb->txq; + artxq = (void *)txq->drv_priv; - if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) && - ar->hw_params.max_probe_resp_desc_thres) - limit_mgmt_desc = true; + if (txq) + artxq->num_fw_queued--; ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); + ath10k_htt_tx_dec_pending(htt); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); @@ -99,22 +100,24 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, memset(&info->status, 0, sizeof(info->status)); trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); - if (tx_done->discard) { + if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) { ieee80211_free_txskb(htt->ar->hw, msdu); - return; + return 0; } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - if (tx_done->no_ack) + if (tx_done->status == HTT_TX_COMPL_STATE_NOACK) info->flags &= ~IEEE80211_TX_STAT_ACK; - if (tx_done->success && (info->flags & IEEE80211_TX_CTL_NO_ACK)) + if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) && + (info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; ieee80211_tx_status(htt->ar->hw, msdu); /* we do not own the msdu anymore */ + return 0; } struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, @@ -127,7 +130,7 @@ struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, list_for_each_entry(peer, &ar->peers, list) { if (peer->vdev_id != vdev_id) continue; - if (memcmp(peer->addr, addr, ETH_ALEN)) + if (!ether_addr_equal(peer->addr, addr)) continue; return peer; @@ -163,7 +166,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, (mapped == expect_mapped || test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); - }), 3*HZ); + }), 3 * HZ); if (time_left == 0) return -ETIMEDOUT; @@ -187,6 +190,13 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer map event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr); if (!peer) { @@ -203,6 +213,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n", ev->vdev_id, ev->addr, ev->peer_id); + ar->peer_map[ev->peer_id] = peer; set_bit(ev->peer_id, peer->peer_ids); exit: spin_unlock_bh(&ar->data_lock); @@ -214,6 +225,13 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, struct ath10k *ar = htt->ar; struct ath10k_peer *peer; + if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) { + ath10k_warn(ar, + "received htt peer unmap event with idx out of bounds: %hu\n", + ev->peer_id); + return; + } + spin_lock_bh(&ar->data_lock); peer = ath10k_peer_find_by_id(ar, ev->peer_id); if (!peer) { @@ -225,6 +243,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n", peer->vdev_id, peer->addr, ev->peer_id); + ar->peer_map[ev->peer_id] = NULL; clear_bit(ev->peer_id, peer->peer_ids); if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) { |