cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

txrx.c (7028B)


      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
     14static 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);
     39out:
     40	spin_unlock_bh(&ar->data_lock);
     41}
     42
     43int 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	u8 flags;
     54
     55	ath10k_dbg(ar, ATH10K_DBG_HTT,
     56		   "htt tx completion msdu_id %u status %d\n",
     57		   tx_done->msdu_id, tx_done->status);
     58
     59	if (tx_done->msdu_id >= htt->max_num_pending_tx) {
     60		ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
     61			    tx_done->msdu_id);
     62		return -EINVAL;
     63	}
     64
     65	spin_lock_bh(&htt->tx_lock);
     66	msdu = idr_find(&htt->pending_tx, tx_done->msdu_id);
     67	if (!msdu) {
     68		ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
     69			    tx_done->msdu_id);
     70		spin_unlock_bh(&htt->tx_lock);
     71		return -ENOENT;
     72	}
     73
     74	skb_cb = ATH10K_SKB_CB(msdu);
     75	txq = skb_cb->txq;
     76
     77	if (txq) {
     78		artxq = (void *)txq->drv_priv;
     79		artxq->num_fw_queued--;
     80	}
     81
     82	flags = skb_cb->flags;
     83	ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
     84	ath10k_htt_tx_dec_pending(htt);
     85	spin_unlock_bh(&htt->tx_lock);
     86
     87	rcu_read_lock();
     88	if (txq && txq->sta && skb_cb->airtime_est)
     89		ieee80211_sta_register_airtime(txq->sta, txq->tid,
     90					       skb_cb->airtime_est, 0);
     91	rcu_read_unlock();
     92
     93	if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
     94		dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
     95
     96	ath10k_report_offchan_tx(htt->ar, msdu);
     97
     98	info = IEEE80211_SKB_CB(msdu);
     99	memset(&info->status, 0, sizeof(info->status));
    100	info->status.rates[0].idx = -1;
    101
    102	trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
    103
    104	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
    105	    !(flags & ATH10K_SKB_F_NOACK_TID))
    106		info->flags |= IEEE80211_TX_STAT_ACK;
    107
    108	if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
    109		info->flags &= ~IEEE80211_TX_STAT_ACK;
    110
    111	if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
    112	    ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
    113	    (flags & ATH10K_SKB_F_NOACK_TID)))
    114		info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
    115
    116	if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
    117		if ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
    118		    (flags & ATH10K_SKB_F_NOACK_TID))
    119			info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED;
    120		else
    121			info->flags &= ~IEEE80211_TX_STAT_ACK;
    122	}
    123
    124	if (tx_done->status == HTT_TX_COMPL_STATE_ACK &&
    125	    tx_done->ack_rssi != ATH10K_INVALID_RSSI) {
    126		info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
    127						tx_done->ack_rssi;
    128		info->status.flags |= IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;
    129	}
    130
    131	ieee80211_tx_status(htt->ar->hw, msdu);
    132	/* we do not own the msdu anymore */
    133
    134	return 0;
    135}
    136
    137struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
    138				     const u8 *addr)
    139{
    140	struct ath10k_peer *peer;
    141
    142	lockdep_assert_held(&ar->data_lock);
    143
    144	list_for_each_entry(peer, &ar->peers, list) {
    145		if (peer->vdev_id != vdev_id)
    146			continue;
    147		if (!ether_addr_equal(peer->addr, addr))
    148			continue;
    149
    150		return peer;
    151	}
    152
    153	return NULL;
    154}
    155
    156struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
    157{
    158	struct ath10k_peer *peer;
    159
    160	if (peer_id >= BITS_PER_TYPE(peer->peer_ids))
    161		return NULL;
    162
    163	lockdep_assert_held(&ar->data_lock);
    164
    165	list_for_each_entry(peer, &ar->peers, list)
    166		if (test_bit(peer_id, peer->peer_ids))
    167			return peer;
    168
    169	return NULL;
    170}
    171
    172static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
    173				       const u8 *addr, bool expect_mapped)
    174{
    175	long time_left;
    176
    177	time_left = wait_event_timeout(ar->peer_mapping_wq, ({
    178			bool mapped;
    179
    180			spin_lock_bh(&ar->data_lock);
    181			mapped = !!ath10k_peer_find(ar, vdev_id, addr);
    182			spin_unlock_bh(&ar->data_lock);
    183
    184			(mapped == expect_mapped ||
    185			 test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
    186		}), 3 * HZ);
    187
    188	if (time_left == 0)
    189		return -ETIMEDOUT;
    190
    191	return 0;
    192}
    193
    194int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id, const u8 *addr)
    195{
    196	return ath10k_wait_for_peer_common(ar, vdev_id, addr, true);
    197}
    198
    199int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id, const u8 *addr)
    200{
    201	return ath10k_wait_for_peer_common(ar, vdev_id, addr, false);
    202}
    203
    204void ath10k_peer_map_event(struct ath10k_htt *htt,
    205			   struct htt_peer_map_event *ev)
    206{
    207	struct ath10k *ar = htt->ar;
    208	struct ath10k_peer *peer;
    209
    210	if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
    211		ath10k_warn(ar,
    212			    "received htt peer map event with idx out of bounds: %u\n",
    213			    ev->peer_id);
    214		return;
    215	}
    216
    217	spin_lock_bh(&ar->data_lock);
    218	peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr);
    219	if (!peer) {
    220		peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
    221		if (!peer)
    222			goto exit;
    223
    224		peer->vdev_id = ev->vdev_id;
    225		ether_addr_copy(peer->addr, ev->addr);
    226		list_add(&peer->list, &ar->peers);
    227		wake_up(&ar->peer_mapping_wq);
    228	}
    229
    230	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
    231		   ev->vdev_id, ev->addr, ev->peer_id);
    232
    233	WARN_ON(ar->peer_map[ev->peer_id] && (ar->peer_map[ev->peer_id] != peer));
    234	ar->peer_map[ev->peer_id] = peer;
    235	set_bit(ev->peer_id, peer->peer_ids);
    236exit:
    237	spin_unlock_bh(&ar->data_lock);
    238}
    239
    240void ath10k_peer_unmap_event(struct ath10k_htt *htt,
    241			     struct htt_peer_unmap_event *ev)
    242{
    243	struct ath10k *ar = htt->ar;
    244	struct ath10k_peer *peer;
    245
    246	if (ev->peer_id >= ATH10K_MAX_NUM_PEER_IDS) {
    247		ath10k_warn(ar,
    248			    "received htt peer unmap event with idx out of bounds: %u\n",
    249			    ev->peer_id);
    250		return;
    251	}
    252
    253	spin_lock_bh(&ar->data_lock);
    254	peer = ath10k_peer_find_by_id(ar, ev->peer_id);
    255	if (!peer) {
    256		ath10k_warn(ar, "peer-unmap-event: unknown peer id %d\n",
    257			    ev->peer_id);
    258		goto exit;
    259	}
    260
    261	ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
    262		   peer->vdev_id, peer->addr, ev->peer_id);
    263
    264	ar->peer_map[ev->peer_id] = NULL;
    265	clear_bit(ev->peer_id, peer->peer_ids);
    266
    267	if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) {
    268		list_del(&peer->list);
    269		kfree(peer);
    270		wake_up(&ar->peer_mapping_wq);
    271	}
    272
    273exit:
    274	spin_unlock_bh(&ar->data_lock);
    275}