LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath/ath10k - txrx.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 136 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 9 0.0 %
Branches: 0 114 0.0 %

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

Generated by: LCOV version 1.14