root/drivers/net/wireless/ath/ath10k/txrx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ath10k_report_offchan_tx
  2. ath10k_txrx_tx_unref
  3. ath10k_peer_find
  4. ath10k_peer_find_by_id
  5. ath10k_wait_for_peer_common
  6. ath10k_wait_for_peer_created
  7. ath10k_wait_for_peer_deleted
  8. ath10k_peer_map_event
  9. ath10k_peer_unmap_event

   1 // SPDX-License-Identifier: ISC
   2 /*
   3  * Copyright (c) 2005-2011 Atheros Communications Inc.
   4  * Copyright (c) 2011-2016 Qualcomm Atheros, Inc.
   5  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
   6  */
   7 
   8 #include "core.h"
   9 #include "txrx.h"
  10 #include "htt.h"
  11 #include "mac.h"
  12 #include "debug.h"
  13 
  14 static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
  15 {
  16         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  17 
  18         if (likely(!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)))
  19                 return;
  20 
  21         if (ath10k_mac_tx_frm_has_freq(ar))
  22                 return;
  23 
  24         /* If the original wait_for_completion() timed out before
  25          * {data,mgmt}_tx_completed() was called then we could complete
  26          * offchan_tx_completed for a different skb. Prevent this by using
  27          * offchan_tx_skb.
  28          */
  29         spin_lock_bh(&ar->data_lock);
  30         if (ar->offchan_tx_skb != skb) {
  31                 ath10k_warn(ar, "completed old offchannel frame\n");
  32                 goto out;
  33         }
  34 
  35         complete(&ar->offchan_tx_completed);
  36         ar->offchan_tx_skb = NULL; /* just for sanity */
  37 
  38         ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %pK\n", skb);
  39 out:
  40         spin_unlock_bh(&ar->data_lock);
  41 }
  42 
  43 int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
  44                          const struct htt_tx_done *tx_done)
  45 {
  46         struct ath10k *ar = htt->ar;
  47         struct device *dev = ar->dev;
  48         struct ieee80211_tx_info *info;
  49         struct ieee80211_txq *txq;
  50         struct ath10k_skb_cb *skb_cb;
  51         struct ath10k_txq *artxq;
  52         struct sk_buff *msdu;
  53 
  54         ath10k_dbg(ar, ATH10K_DBG_HTT,
  55                    "htt tx completion msdu_id %u status %d\n",
  56                    tx_done->msdu_id, tx_done->status);
  57 
  58         if (tx_done->msdu_id >= htt->max_num_pending_tx) {
  59                 ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
  60                             tx_done->msdu_id);
  61                 return -EINVAL;
  62         }
  63 
  64         spin_lock_bh(&htt->tx_lock);
  65         msdu = idr_find(&htt->pending_tx, tx_done->msdu_id);
  66         if (!msdu) {
  67                 ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
  68                             tx_done->msdu_id);
  69                 spin_unlock_bh(&htt->tx_lock);
  70                 return -ENOENT;
  71         }
  72 
  73         skb_cb = ATH10K_SKB_CB(msdu);
  74         txq = skb_cb->txq;
  75 
  76         if (txq) {
  77                 artxq = (void *)txq->drv_priv;
  78                 artxq->num_fw_queued--;
  79         }
  80 
  81         ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
  82         ath10k_htt_tx_dec_pending(htt);
  83         if (htt->num_pending_tx == 0)
  84                 wake_up(&htt->empty_tx_wq);
  85         spin_unlock_bh(&htt->tx_lock);
  86 
  87         if (txq && txq->sta && skb_cb->airtime_est)
  88                 ieee80211_sta_register_airtime(txq->sta, txq->tid,
  89                                                skb_cb->airtime_est, 0);
  90 
  91         if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
  92                 dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
  93 
  94         ath10k_report_offchan_tx(htt->ar, msdu);
  95 
  96         info = IEEE80211_SKB_CB(msdu);
  97         memset(&info->status, 0, sizeof(info->status));
  98         info->status.rates[0].idx = -1;
  99 
 100         trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
 101 
 102         if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
 103                 info->flags |= IEEE80211_TX_STAT_ACK;
 104 
 105         if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
 106                 info->flags &= ~IEEE80211_TX_STAT_ACK;
 107 
 108         if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
 109             (info->flags & IEEE80211_TX_CTL_NO_ACK))
 110                 info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
 111 
 112         if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
 113                 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
 114                         info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED;
 115                 else
 116                         info->flags &= ~IEEE80211_TX_STAT_ACK;
 117         }
 118 
 119         if (tx_done->status == HTT_TX_COMPL_STATE_ACK &&
 120             tx_done->ack_rssi != ATH10K_INVALID_RSSI) {
 121                 info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
 122                                                 tx_done->ack_rssi;
 123                 info->status.is_valid_ack_signal = true;
 124         }
 125 
 126         ieee80211_tx_status(htt->ar->hw, msdu);
 127         /* we do not own the msdu anymore */
 128 
 129         return 0;
 130 }
 131 
 132 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
 133                                      const u8 *addr)
 134 {
 135         struct ath10k_peer *peer;
 136 
 137         lockdep_assert_held(&ar->data_lock);
 138 
 139         list_for_each_entry(peer, &ar->peers, list) {
 140                 if (peer->vdev_id != vdev_id)
 141                         continue;
 142                 if (!ether_addr_equal(peer->addr, addr))
 143                         continue;
 144 
 145                 return peer;
 146         }
 147 
 148         return NULL;
 149 }
 150 
 151 struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 152 {
 153         struct ath10k_peer *peer;
 154 
 155         if (peer_id >= BITS_PER_TYPE(peer->peer_ids))
 156                 return NULL;
 157 
 158         lockdep_assert_held(&ar->data_lock);
 159 
 160         list_for_each_entry(peer, &ar->peers, list)
 161                 if (test_bit(peer_id, peer->peer_ids))
 162                         return peer;
 163 
 164         return NULL;
 165 }
 166 
 167 static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
 168                                        const u8 *addr, bool expect_mapped)
 169 {
 170         long time_left;
 171 
 172         time_left = wait_event_timeout(ar->peer_mapping_wq, ({
 173                         bool mapped;
 174 
 175                         spin_lock_bh(&ar->data_lock);
 176                         mapped = !!ath10k_peer_find(ar, vdev_id, addr);
 177                         spin_unlock_bh(&ar->data_lock);
 178 
 179                         (mapped == expect_mapped ||
 180                          test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
 181                 }), 3 * HZ);
 182 
 183         if (time_left == 0)
 184                 return -ETIMEDOUT;
 185 
 186         return 0;
 187 }
 188 
 189 int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, const u8 *addr)
 190 {
 191         return ath10k_wait_for_peer_common(ar, vdev_id, addr, true);
 192 }
 193 
 194 int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, const u8 *addr)
 195 {
 196         return ath10k_wait_for_peer_common(ar, vdev_id, addr, false);
 197 }
 198 
 199 void ath10k_peer_map_event(struct ath10k_htt *htt,
 200                            struct htt_peer_map_event *ev)
 201 {
 202         struct ath10k *ar = htt->ar;
 203         struct ath10k_peer *peer;
 204 
 205         if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
 206                 ath10k_warn(ar,
 207                             "received htt peer map event with idx out of bounds: %hu\n",
 208                             ev->peer_id);
 209                 return;
 210         }
 211 
 212         spin_lock_bh(&ar->data_lock);
 213         peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr);
 214         if (!peer) {
 215                 peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
 216                 if (!peer)
 217                         goto exit;
 218 
 219                 peer->vdev_id = ev->vdev_id;
 220                 ether_addr_copy(peer->addr, ev->addr);
 221                 list_add(&peer->list, &ar->peers);
 222                 wake_up(&ar->peer_mapping_wq);
 223         }
 224 
 225         ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
 226                    ev->vdev_id, ev->addr, ev->peer_id);
 227 
 228         WARN_ON(ar->peer_map[ev->peer_id] && (ar->peer_map[ev->peer_id] != peer));
 229         ar->peer_map[ev->peer_id] = peer;
 230         set_bit(ev->peer_id, peer->peer_ids);
 231 exit:
 232         spin_unlock_bh(&ar->data_lock);
 233 }
 234 
 235 void ath10k_peer_unmap_event(struct ath10k_htt *htt,
 236                              struct htt_peer_unmap_event *ev)
 237 {
 238         struct ath10k *ar = htt->ar;
 239         struct ath10k_peer *peer;
 240 
 241         if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
 242                 ath10k_warn(ar,
 243                             "received htt peer unmap event with idx out of bounds: %hu\n",
 244                             ev->peer_id);
 245                 return;
 246         }
 247 
 248         spin_lock_bh(&ar->data_lock);
 249         peer = ath10k_peer_find_by_id(ar, ev->peer_id);
 250         if (!peer) {
 251                 ath10k_warn(ar, "peer-unmap-event: unknown peer id %d\n",
 252                             ev->peer_id);
 253                 goto exit;
 254         }
 255 
 256         ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
 257                    peer->vdev_id, peer->addr, ev->peer_id);
 258 
 259         ar->peer_map[ev->peer_id] = NULL;
 260         clear_bit(ev->peer_id, peer->peer_ids);
 261 
 262         if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) {
 263                 list_del(&peer->list);
 264                 kfree(peer);
 265                 wake_up(&ar->peer_mapping_wq);
 266         }
 267 
 268 exit:
 269         spin_unlock_bh(&ar->data_lock);
 270 }

/* [<][>][^][v][top][bottom][index][help] */