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 (10747B)


      1/*
      2 * NXP Wireless LAN device driver: generic TX/RX data handling
      3 *
      4 * Copyright 2011-2020 NXP
      5 *
      6 * This software file (the "File") is distributed by NXP
      7 * under the terms of the GNU General Public License Version 2, June 1991
      8 * (the "License").  You may use, redistribute and/or modify this File in
      9 * accordance with the terms and conditions of the License, a copy of which
     10 * is available by writing to the Free Software Foundation, Inc.,
     11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
     12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
     13 *
     14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
     15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
     16 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
     17 * this warranty disclaimer.
     18 */
     19
     20#include "decl.h"
     21#include "ioctl.h"
     22#include "util.h"
     23#include "fw.h"
     24#include "main.h"
     25#include "wmm.h"
     26
     27/*
     28 * This function processes the received buffer.
     29 *
     30 * Main responsibility of this function is to parse the RxPD to
     31 * identify the correct interface this packet is headed for and
     32 * forwarding it to the associated handling function, where the
     33 * packet will be further processed and sent to kernel/upper layer
     34 * if required.
     35 */
     36int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
     37			     struct sk_buff *skb)
     38{
     39	struct mwifiex_private *priv =
     40		mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
     41	struct rxpd *local_rx_pd;
     42	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
     43	int ret;
     44
     45	local_rx_pd = (struct rxpd *) (skb->data);
     46	/* Get the BSS number from rxpd, get corresponding priv */
     47	priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num &
     48				      BSS_NUM_MASK, local_rx_pd->bss_type);
     49	if (!priv)
     50		priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
     51
     52	if (!priv) {
     53		mwifiex_dbg(adapter, ERROR,
     54			    "data: priv not found. Drop RX packet\n");
     55		dev_kfree_skb_any(skb);
     56		return -1;
     57	}
     58
     59	mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
     60			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
     61
     62	memset(rx_info, 0, sizeof(*rx_info));
     63	rx_info->bss_num = priv->bss_num;
     64	rx_info->bss_type = priv->bss_type;
     65
     66	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
     67		ret = mwifiex_process_uap_rx_packet(priv, skb);
     68	else
     69		ret = mwifiex_process_sta_rx_packet(priv, skb);
     70
     71	return ret;
     72}
     73EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
     74
     75/*
     76 * This function sends a packet to device.
     77 *
     78 * It processes the packet to add the TxPD, checks condition and
     79 * sends the processed packet to firmware for transmission.
     80 *
     81 * On successful completion, the function calls the completion callback
     82 * and logs the time.
     83 */
     84int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
     85		       struct mwifiex_tx_param *tx_param)
     86{
     87	int hroom, ret = -1;
     88	struct mwifiex_adapter *adapter = priv->adapter;
     89	u8 *head_ptr;
     90	struct txpd *local_tx_pd = NULL;
     91	struct mwifiex_sta_node *dest_node;
     92	struct ethhdr *hdr = (void *)skb->data;
     93
     94	hroom = adapter->intf_hdr_len;
     95
     96	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
     97		dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
     98		if (dest_node) {
     99			dest_node->stats.tx_bytes += skb->len;
    100			dest_node->stats.tx_packets++;
    101		}
    102
    103		head_ptr = mwifiex_process_uap_txpd(priv, skb);
    104	} else {
    105		head_ptr = mwifiex_process_sta_txpd(priv, skb);
    106	}
    107
    108	if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
    109		skb_queue_tail(&adapter->tx_data_q, skb);
    110		atomic_inc(&adapter->tx_queued);
    111		return 0;
    112	}
    113
    114	if (head_ptr) {
    115		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
    116			local_tx_pd = (struct txpd *)(head_ptr + hroom);
    117		if (adapter->iface_type == MWIFIEX_USB) {
    118			ret = adapter->if_ops.host_to_card(adapter,
    119							   priv->usb_port,
    120							   skb, tx_param);
    121		} else {
    122			ret = adapter->if_ops.host_to_card(adapter,
    123							   MWIFIEX_TYPE_DATA,
    124							   skb, tx_param);
    125		}
    126	}
    127	mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
    128			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
    129
    130	switch (ret) {
    131	case -ENOSR:
    132		mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n");
    133		break;
    134	case -EBUSY:
    135		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
    136		    (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) {
    137				priv->adapter->tx_lock_flag = false;
    138				if (local_tx_pd)
    139					local_tx_pd->flags = 0;
    140		}
    141		mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
    142		break;
    143	case -1:
    144		mwifiex_dbg(adapter, ERROR,
    145			    "mwifiex_write_data_async failed: 0x%X\n",
    146			    ret);
    147		adapter->dbg.num_tx_host_to_card_failure++;
    148		mwifiex_write_data_complete(adapter, skb, 0, ret);
    149		break;
    150	case -EINPROGRESS:
    151		break;
    152	case 0:
    153		mwifiex_write_data_complete(adapter, skb, 0, ret);
    154		break;
    155	default:
    156		break;
    157	}
    158
    159	return ret;
    160}
    161
    162static int mwifiex_host_to_card(struct mwifiex_adapter *adapter,
    163				struct sk_buff *skb,
    164				struct mwifiex_tx_param *tx_param)
    165{
    166	struct txpd *local_tx_pd = NULL;
    167	u8 *head_ptr = skb->data;
    168	int ret = 0;
    169	struct mwifiex_private *priv;
    170	struct mwifiex_txinfo *tx_info;
    171
    172	tx_info = MWIFIEX_SKB_TXCB(skb);
    173	priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
    174				      tx_info->bss_type);
    175	if (!priv) {
    176		mwifiex_dbg(adapter, ERROR,
    177			    "data: priv not found. Drop TX packet\n");
    178		adapter->dbg.num_tx_host_to_card_failure++;
    179		mwifiex_write_data_complete(adapter, skb, 0, 0);
    180		return ret;
    181	}
    182	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
    183		local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
    184
    185	if (adapter->iface_type == MWIFIEX_USB) {
    186		ret = adapter->if_ops.host_to_card(adapter,
    187						   priv->usb_port,
    188						   skb, tx_param);
    189	} else {
    190		ret = adapter->if_ops.host_to_card(adapter,
    191						   MWIFIEX_TYPE_DATA,
    192						   skb, tx_param);
    193	}
    194	switch (ret) {
    195	case -ENOSR:
    196		mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
    197		break;
    198	case -EBUSY:
    199		if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
    200		    (adapter->pps_uapsd_mode) &&
    201		    (adapter->tx_lock_flag)) {
    202			priv->adapter->tx_lock_flag = false;
    203			if (local_tx_pd)
    204				local_tx_pd->flags = 0;
    205		}
    206		skb_queue_head(&adapter->tx_data_q, skb);
    207		if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
    208			atomic_add(tx_info->aggr_num, &adapter->tx_queued);
    209		else
    210			atomic_inc(&adapter->tx_queued);
    211		mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
    212		break;
    213	case -1:
    214		mwifiex_dbg(adapter, ERROR,
    215			    "mwifiex_write_data_async failed: 0x%X\n", ret);
    216		adapter->dbg.num_tx_host_to_card_failure++;
    217		mwifiex_write_data_complete(adapter, skb, 0, ret);
    218		break;
    219	case -EINPROGRESS:
    220		break;
    221	case 0:
    222		mwifiex_write_data_complete(adapter, skb, 0, ret);
    223		break;
    224	default:
    225		break;
    226	}
    227	return ret;
    228}
    229
    230static int
    231mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter)
    232{
    233	struct sk_buff *skb, *skb_next;
    234	struct mwifiex_txinfo *tx_info;
    235	struct mwifiex_tx_param tx_param;
    236
    237	skb = skb_dequeue(&adapter->tx_data_q);
    238	if (!skb)
    239		return -1;
    240
    241	tx_info = MWIFIEX_SKB_TXCB(skb);
    242	if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
    243		atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
    244	else
    245		atomic_dec(&adapter->tx_queued);
    246
    247	if (!skb_queue_empty(&adapter->tx_data_q))
    248		skb_next = skb_peek(&adapter->tx_data_q);
    249	else
    250		skb_next = NULL;
    251	tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
    252	if (!tx_param.next_pkt_len) {
    253		if (!mwifiex_wmm_lists_empty(adapter))
    254			tx_param.next_pkt_len = 1;
    255	}
    256	return mwifiex_host_to_card(adapter, skb, &tx_param);
    257}
    258
    259void
    260mwifiex_process_tx_queue(struct mwifiex_adapter *adapter)
    261{
    262	do {
    263		if (adapter->data_sent || adapter->tx_lock_flag)
    264			break;
    265		if (mwifiex_dequeue_tx_queue(adapter))
    266			break;
    267	} while (!skb_queue_empty(&adapter->tx_data_q));
    268}
    269
    270/*
    271 * Packet send completion callback handler.
    272 *
    273 * It either frees the buffer directly or forwards it to another
    274 * completion callback which checks conditions, updates statistics,
    275 * wakes up stalled traffic queue if required, and then frees the buffer.
    276 */
    277int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
    278				struct sk_buff *skb, int aggr, int status)
    279{
    280	struct mwifiex_private *priv;
    281	struct mwifiex_txinfo *tx_info;
    282	struct netdev_queue *txq;
    283	int index;
    284
    285	if (!skb)
    286		return 0;
    287
    288	tx_info = MWIFIEX_SKB_TXCB(skb);
    289	priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num,
    290				      tx_info->bss_type);
    291	if (!priv)
    292		goto done;
    293
    294	mwifiex_set_trans_start(priv->netdev);
    295
    296	if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
    297		atomic_dec_return(&adapter->pending_bridged_pkts);
    298
    299	if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
    300		goto done;
    301
    302	if (!status) {
    303		priv->stats.tx_packets++;
    304		priv->stats.tx_bytes += tx_info->pkt_len;
    305		if (priv->tx_timeout_cnt)
    306			priv->tx_timeout_cnt = 0;
    307	} else {
    308		priv->stats.tx_errors++;
    309	}
    310
    311	if (aggr)
    312		/* For skb_aggr, do not wake up tx queue */
    313		goto done;
    314
    315	atomic_dec(&adapter->tx_pending);
    316
    317	index = mwifiex_1d_to_wmm_queue[skb->priority];
    318	if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
    319		txq = netdev_get_tx_queue(priv->netdev, index);
    320		if (netif_tx_queue_stopped(txq)) {
    321			netif_tx_wake_queue(txq);
    322			mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index);
    323		}
    324	}
    325done:
    326	dev_kfree_skb_any(skb);
    327
    328	return 0;
    329}
    330EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
    331
    332void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
    333				   void *event_body)
    334{
    335	struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
    336	struct sk_buff *ack_skb;
    337	struct mwifiex_txinfo *tx_info;
    338
    339	if (!tx_status->tx_token_id)
    340		return;
    341
    342	spin_lock_bh(&priv->ack_status_lock);
    343	ack_skb = idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
    344	spin_unlock_bh(&priv->ack_status_lock);
    345
    346	if (ack_skb) {
    347		tx_info = MWIFIEX_SKB_TXCB(ack_skb);
    348
    349		if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
    350			/* consumes ack_skb */
    351			skb_complete_wifi_ack(ack_skb, !tx_status->status);
    352		} else {
    353			/* Remove broadcast address which was added by driver */
    354			memmove(ack_skb->data +
    355				sizeof(struct ieee80211_hdr_3addr) +
    356				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
    357				ack_skb->data +
    358				sizeof(struct ieee80211_hdr_3addr) +
    359				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
    360				ETH_ALEN, ack_skb->len -
    361				(sizeof(struct ieee80211_hdr_3addr) +
    362				MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
    363				ETH_ALEN));
    364			ack_skb->len = ack_skb->len - ETH_ALEN;
    365			/* Remove driver's proprietary header including 2 bytes
    366			 * of packet length and pass actual management frame buffer
    367			 * to cfg80211.
    368			 */
    369			cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
    370						ack_skb->data +
    371						MWIFIEX_MGMT_FRAME_HEADER_SIZE +
    372						sizeof(u16), ack_skb->len -
    373						(MWIFIEX_MGMT_FRAME_HEADER_SIZE
    374						 + sizeof(u16)),
    375						!tx_status->status, GFP_ATOMIC);
    376			dev_kfree_skb_any(ack_skb);
    377		}
    378	}
    379}