mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Lin <yu-hao.lin@nxp.com>
To: linux-wireless@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, kvalo@kernel.org,
	johannes@sipsolutions.net, briannorris@chromium.org,
	francesco@dolcini.it, tsung-hsien.hsieh@nxp.com,
	David Lin <yu-hao.lin@nxp.com>
Subject: [PATCH v2 33/43] wifi: nxpwifi: add txrx.c
Date: Fri,  9 Aug 2024 17:45:23 +0800	[thread overview]
Message-ID: <20240809094533.1660-34-yu-hao.lin@nxp.com> (raw)
In-Reply-To: <20240809094533.1660-1-yu-hao.lin@nxp.com>

---
 drivers/net/wireless/nxp/nxpwifi/txrx.c | 358 ++++++++++++++++++++++++
 1 file changed, 358 insertions(+)
 create mode 100644 drivers/net/wireless/nxp/nxpwifi/txrx.c

diff --git a/drivers/net/wireless/nxp/nxpwifi/txrx.c b/drivers/net/wireless/nxp/nxpwifi/txrx.c
new file mode 100644
index 000000000000..860c88bf8ea8
--- /dev/null
+++ b/drivers/net/wireless/nxp/nxpwifi/txrx.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * NXP Wireless LAN device driver: generic TX/RX data handling
+ *
+ * Copyright 2011-2024 NXP
+ */
+
+#include "decl.h"
+#include "cfg.h"
+#include "util.h"
+#include "fw.h"
+#include "main.h"
+#include "wmm.h"
+
+/* This function processes the received buffer.
+ *
+ * Main responsibility of this function is to parse the RxPD to
+ * identify the correct interface this packet is headed for and
+ * forwarding it to the associated handling function, where the
+ * packet will be further processed and sent to kernel/upper layer
+ * if required.
+ */
+int nxpwifi_handle_rx_packet(struct nxpwifi_adapter *adapter,
+			     struct sk_buff *skb)
+{
+	struct nxpwifi_private *priv =
+		nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY);
+	struct rxpd *local_rx_pd;
+	struct nxpwifi_rxinfo *rx_info = NXPWIFI_SKB_RXCB(skb);
+	int ret;
+
+	local_rx_pd = (struct rxpd *)(skb->data);
+	/* Get the BSS number from rxpd, get corresponding priv */
+	priv = nxpwifi_get_priv_by_id(adapter, local_rx_pd->bss_num &
+				      BSS_NUM_MASK, local_rx_pd->bss_type);
+	if (!priv)
+		priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY);
+
+	if (!priv) {
+		nxpwifi_dbg(adapter, ERROR,
+			    "data: priv not found. Drop RX packet\n");
+		dev_kfree_skb_any(skb);
+		return -EINVAL;
+	}
+
+	nxpwifi_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
+			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
+
+	memset(rx_info, 0, sizeof(*rx_info));
+	rx_info->bss_num = priv->bss_num;
+	rx_info->bss_type = priv->bss_type;
+
+	if (priv->bss_role == NXPWIFI_BSS_ROLE_UAP)
+		ret = nxpwifi_process_uap_rx_packet(priv, skb);
+	else
+		ret = nxpwifi_process_sta_rx_packet(priv, skb);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nxpwifi_handle_rx_packet);
+
+/* This function sends a packet to device.
+ *
+ * It processes the packet to add the TxPD, checks condition and
+ * sends the processed packet to firmware for transmission.
+ *
+ * On successful completion, the function calls the completion callback
+ * and logs the time.
+ */
+int nxpwifi_process_tx(struct nxpwifi_private *priv, struct sk_buff *skb,
+		       struct nxpwifi_tx_param *tx_param)
+{
+	int hroom, ret;
+	struct nxpwifi_adapter *adapter = priv->adapter;
+	struct txpd *local_tx_pd = NULL;
+	struct nxpwifi_sta_node *dest_node;
+	struct ethhdr *hdr = (void *)skb->data;
+
+	if (unlikely(!skb->len ||
+		     skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	hroom = adapter->intf_hdr_len;
+
+	if (priv->bss_role == NXPWIFI_BSS_ROLE_UAP) {
+		dest_node = nxpwifi_get_sta_entry(priv, hdr->h_dest);
+		if (dest_node) {
+			dest_node->stats.tx_bytes += skb->len;
+			dest_node->stats.tx_packets++;
+		}
+
+		nxpwifi_process_uap_txpd(priv, skb);
+	} else {
+		nxpwifi_process_sta_txpd(priv, skb);
+	}
+
+	if ((adapter->data_sent || adapter->tx_lock_flag)) {
+		skb_queue_tail(&adapter->tx_data_q, skb);
+		atomic_inc(&adapter->tx_queued);
+		return 0;
+	}
+
+	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
+		local_tx_pd = (struct txpd *)(skb->data + hroom);
+	ret = adapter->if_ops.host_to_card(adapter,
+					   NXPWIFI_TYPE_DATA,
+					   skb, tx_param);
+	nxpwifi_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
+			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
+
+out:
+	switch (ret) {
+	case -ENOSR:
+		nxpwifi_dbg(adapter, DATA, "data: -ENOSR is returned\n");
+		break;
+	case -EBUSY:
+		if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA) &&
+		    adapter->pps_uapsd_mode && adapter->tx_lock_flag) {
+			priv->adapter->tx_lock_flag = false;
+			if (local_tx_pd)
+				local_tx_pd->flags = 0;
+		}
+		nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+		break;
+	case -EINPROGRESS:
+		break;
+	case -EINVAL:
+		nxpwifi_dbg(adapter, ERROR,
+			    "malformed skb (length: %u, headroom: %u)\n",
+			    skb->len, skb_headroom(skb));
+		fallthrough;
+	case 0:
+		nxpwifi_write_data_complete(adapter, skb, 0, ret);
+		break;
+	default:
+		nxpwifi_dbg(adapter, ERROR,
+			    "nxpwifi_write_data_async failed: 0x%X\n",
+			    ret);
+		adapter->dbg.num_tx_host_to_card_failure++;
+		nxpwifi_write_data_complete(adapter, skb, 0, ret);
+		break;
+	}
+
+	return ret;
+}
+
+static int nxpwifi_host_to_card(struct nxpwifi_adapter *adapter,
+				struct sk_buff *skb,
+				struct nxpwifi_tx_param *tx_param)
+{
+	struct txpd *local_tx_pd = NULL;
+	u8 *head_ptr = skb->data;
+	int ret = 0;
+	struct nxpwifi_private *priv;
+	struct nxpwifi_txinfo *tx_info;
+
+	tx_info = NXPWIFI_SKB_TXCB(skb);
+	priv = nxpwifi_get_priv_by_id(adapter, tx_info->bss_num,
+				      tx_info->bss_type);
+	if (!priv) {
+		nxpwifi_dbg(adapter, ERROR,
+			    "data: priv not found. Drop TX packet\n");
+		adapter->dbg.num_tx_host_to_card_failure++;
+		nxpwifi_write_data_complete(adapter, skb, 0, 0);
+		return ret;
+	}
+	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
+		local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
+
+	ret = adapter->if_ops.host_to_card(adapter,
+					   NXPWIFI_TYPE_DATA,
+					   skb, tx_param);
+
+	switch (ret) {
+	case -ENOSR:
+		nxpwifi_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
+		break;
+	case -EBUSY:
+		if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA) &&
+		    adapter->pps_uapsd_mode &&
+		    adapter->tx_lock_flag) {
+			priv->adapter->tx_lock_flag = false;
+			if (local_tx_pd)
+				local_tx_pd->flags = 0;
+		}
+		skb_queue_head(&adapter->tx_data_q, skb);
+		if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
+			atomic_add(tx_info->aggr_num, &adapter->tx_queued);
+		else
+			atomic_inc(&adapter->tx_queued);
+		nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
+		break;
+	case -EINPROGRESS:
+		break;
+	case 0:
+		nxpwifi_write_data_complete(adapter, skb, 0, ret);
+		break;
+	default:
+		nxpwifi_dbg(adapter, ERROR,
+			    "nxpwifi_write_data_async failed: 0x%X\n", ret);
+		adapter->dbg.num_tx_host_to_card_failure++;
+		nxpwifi_write_data_complete(adapter, skb, 0, ret);
+		break;
+	}
+	return ret;
+}
+
+static int
+nxpwifi_dequeue_tx_queue(struct nxpwifi_adapter *adapter)
+{
+	struct sk_buff *skb, *skb_next;
+	struct nxpwifi_txinfo *tx_info;
+	struct nxpwifi_tx_param tx_param;
+
+	skb = skb_dequeue(&adapter->tx_data_q);
+	if (!skb)
+		return -ENOMEM;
+
+	tx_info = NXPWIFI_SKB_TXCB(skb);
+	if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
+		atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
+	else
+		atomic_dec(&adapter->tx_queued);
+
+	if (!skb_queue_empty(&adapter->tx_data_q))
+		skb_next = skb_peek(&adapter->tx_data_q);
+	else
+		skb_next = NULL;
+	tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
+	if (!tx_param.next_pkt_len) {
+		if (!nxpwifi_wmm_lists_empty(adapter))
+			tx_param.next_pkt_len = 1;
+	}
+	return nxpwifi_host_to_card(adapter, skb, &tx_param);
+}
+
+void
+nxpwifi_process_tx_queue(struct nxpwifi_adapter *adapter)
+{
+	do {
+		if (adapter->data_sent || adapter->tx_lock_flag)
+			break;
+		if (nxpwifi_dequeue_tx_queue(adapter))
+			break;
+	} while (!skb_queue_empty(&adapter->tx_data_q));
+}
+
+/* Packet send completion callback handler.
+ *
+ * It either frees the buffer directly or forwards it to another
+ * completion callback which checks conditions, updates statistics,
+ * wakes up stalled traffic queue if required, and then frees the buffer.
+ */
+int nxpwifi_write_data_complete(struct nxpwifi_adapter *adapter,
+				struct sk_buff *skb, int aggr, int status)
+{
+	struct nxpwifi_private *priv;
+	struct nxpwifi_txinfo *tx_info;
+	struct netdev_queue *txq;
+	int index;
+
+	if (!skb)
+		return 0;
+
+	tx_info = NXPWIFI_SKB_TXCB(skb);
+	priv = nxpwifi_get_priv_by_id(adapter, tx_info->bss_num,
+				      tx_info->bss_type);
+	if (!priv)
+		goto done;
+
+	nxpwifi_set_trans_start(priv->netdev);
+
+	if (tx_info->flags & NXPWIFI_BUF_FLAG_BRIDGED_PKT)
+		atomic_dec_return(&adapter->pending_bridged_pkts);
+
+	if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
+		goto done;
+
+	if (!status) {
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += tx_info->pkt_len;
+		if (priv->tx_timeout_cnt)
+			priv->tx_timeout_cnt = 0;
+	} else {
+		priv->stats.tx_errors++;
+	}
+
+	if (aggr)
+		/* For skb_aggr, do not wake up tx queue */
+		goto done;
+
+	atomic_dec(&adapter->tx_pending);
+
+	index = nxpwifi_1d_to_wmm_queue[skb->priority];
+	if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
+		txq = netdev_get_tx_queue(priv->netdev, index);
+		if (netif_tx_queue_stopped(txq)) {
+			netif_tx_wake_queue(txq);
+			nxpwifi_dbg(adapter, DATA, "wake queue: %d\n", index);
+		}
+	}
+done:
+	dev_kfree_skb_any(skb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nxpwifi_write_data_complete);
+
+void nxpwifi_parse_tx_status_event(struct nxpwifi_private *priv,
+				   void *event_body)
+{
+	struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
+	struct sk_buff *ack_skb;
+	struct nxpwifi_txinfo *tx_info;
+
+	if (!tx_status->tx_token_id)
+		return;
+
+	spin_lock_bh(&priv->ack_status_lock);
+	ack_skb = idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
+	spin_unlock_bh(&priv->ack_status_lock);
+
+	if (ack_skb) {
+		tx_info = NXPWIFI_SKB_TXCB(ack_skb);
+
+		if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS) {
+			/* consumes ack_skb */
+			skb_complete_wifi_ack(ack_skb, !tx_status->status);
+		} else {
+			/* Remove broadcast address which was added by driver */
+			memmove(ack_skb->data +
+				sizeof(struct ieee80211_hdr_3addr) +
+				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
+				ack_skb->data +
+				sizeof(struct ieee80211_hdr_3addr) +
+				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+				ETH_ALEN, ack_skb->len -
+				(sizeof(struct ieee80211_hdr_3addr) +
+				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+				ETH_ALEN));
+			ack_skb->len = ack_skb->len - ETH_ALEN;
+			/* Remove driver's proprietary header including 2 bytes
+			 * of packet length and pass actual management frame buffer
+			 * to cfg80211.
+			 */
+			cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
+						ack_skb->data +
+						NXPWIFI_MGMT_FRAME_HEADER_SIZE +
+						sizeof(u16), ack_skb->len -
+						(NXPWIFI_MGMT_FRAME_HEADER_SIZE
+						 + sizeof(u16)),
+						!tx_status->status, GFP_ATOMIC);
+			dev_kfree_skb_any(ack_skb);
+		}
+	}
+}
-- 
2.34.1


  parent reply	other threads:[~2024-08-09  9:47 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-09  9:44 [PATCH v2 00/43] wifi: nxpwifi: create nxpwifi to support iw61x David Lin
2024-08-09  9:44 ` [PATCH v2 01/43] wifi: nxpwifi: add 11ac.c David Lin
2024-08-09  9:44 ` [PATCH v2 02/43] wifi: nxpwifi: add 11ac.h David Lin
2024-08-09  9:44 ` [PATCH v2 03/43] wifi: nxpwifi: add 11h.c David Lin
2024-08-09  9:44 ` [PATCH v2 04/43] wifi: nxpwifi: add 11n_aggr.c David Lin
2024-08-09  9:44 ` [PATCH v2 05/43] wifi: nxpwifi: add 11n_aggr.h David Lin
2024-08-09  9:44 ` [PATCH v2 06/43] wifi: nxpwifi: add 11n.c David Lin
2024-08-09  9:44 ` [PATCH v2 07/43] wifi: nxpwifi: add 11n.h David Lin
2024-08-09  9:44 ` [PATCH v2 08/43] wifi: nxpwifi: add 11n_rxreorder.c David Lin
2024-08-09  9:44 ` [PATCH v2 09/43] wifi: nxpwifi: add 11n_rxreorder.h David Lin
2024-08-09  9:45 ` [PATCH v2 10/43] wifi: nxpwifi: add cfg80211.c David Lin
2024-08-09  9:45 ` [PATCH v2 11/43] wifi: nxpwifi: add cfg80211.h David Lin
2024-08-09  9:45 ` [PATCH v2 12/43] wifi: nxpwifi: add cfg.h David Lin
2024-08-09  9:45 ` [PATCH v2 13/43] wifi: nxpwifi: add cfp.c David Lin
2024-08-09  9:45 ` [PATCH v2 14/43] wifi: nxpwifi: add cmdevt.c David Lin
2024-08-09  9:45 ` [PATCH v2 15/43] wifi: nxpwifi: add cmdevt.h David Lin
2024-08-09  9:45 ` [PATCH v2 16/43] wifi: nxpwifi: add debugfs.c David Lin
2024-08-09  9:45 ` [PATCH v2 17/43] wifi: nxpwifi: add decl.h David Lin
2024-08-09  9:45 ` [PATCH v2 18/43] wifi: nxpwifi: add ethtool.c David Lin
2024-08-09  9:45 ` [PATCH v2 19/43] wifi: nxpwifi: add fw.h David Lin
2024-08-09  9:45 ` [PATCH v2 20/43] wifi: nxpwifi: add ie.c David Lin
2024-08-09  9:45 ` [PATCH v2 21/43] wifi: nxpwifi: add init.c David Lin
2024-08-09  9:45 ` [PATCH v2 22/43] wifi: nxpwifi: add join.c David Lin
2024-08-09  9:45 ` [PATCH v2 23/43] wifi: nxpwifi: add main.c David Lin
2024-08-09  9:45 ` [PATCH v2 24/43] wifi: nxpwifi: add main.h David Lin
2024-08-09  9:45 ` [PATCH v2 25/43] wifi: nxpwifi: add scan.c David Lin
2024-08-09  9:45 ` [PATCH v2 26/43] wifi: nxpwifi: add sdio.c David Lin
2024-08-09  9:45 ` [PATCH v2 27/43] wifi: nxpwifi: add sdio.h David Lin
2024-08-09  9:45 ` [PATCH v2 28/43] wifi: nxpwifi: add sta_cfg.c David Lin
2024-08-09  9:45 ` [PATCH v2 29/43] wifi: nxpwifi: add sta_cmd.c David Lin
2024-08-09  9:45 ` [PATCH v2 30/43] wifi: nxpwifi: add sta_event.c David Lin
2024-08-09  9:45 ` [PATCH v2 31/43] wifi: nxpwifi: add sta_rx.c David Lin
2024-08-09  9:45 ` [PATCH v2 32/43] wifi: nxpwifi: add sta_tx.c David Lin
2024-08-09  9:45 ` David Lin [this message]
2024-08-09  9:45 ` [PATCH v2 34/43] wifi: nxpwifi: add uap_cmd.c David Lin
2024-08-09  9:45 ` [PATCH v2 35/43] wifi: nxpwifi: add uap_event.c David Lin
2024-08-09  9:45 ` [PATCH v2 36/43] wifi: nxpwifi: add uap_txrx.c David Lin
2024-08-09  9:45 ` [PATCH v2 37/43] wifi: nxpwifi: add util.c David Lin
2024-08-09  9:45 ` [PATCH v2 38/43] wifi: nxpwifi: add util.h David Lin
2024-08-09  9:45 ` [PATCH v2 39/43] wifi: nxpwifi: add wmm.c David Lin
2024-08-09  9:45 ` [PATCH v2 40/43] wifi: nxpwifi: add wmm.h David Lin
2024-08-14 18:48   ` Greg KH
2024-08-15  1:52     ` [EXT] " David Lin
2024-08-15  5:08       ` Greg KH
2024-08-15  6:20         ` David Lin
2024-08-15  6:23           ` David Lin
2024-08-15  6:57           ` Greg KH
2024-08-15  9:51           ` Kalle Valo
2024-08-16  1:39             ` David Lin
2024-08-15  9:43         ` Kalle Valo
2024-08-15  9:58           ` Greg KH
2024-08-15 11:44             ` Kalle Valo
2024-08-09  9:45 ` [PATCH v2 41/43] wifi: nxpwifi: add nxp sdio vendor id and iw61x device id David Lin
2024-08-09  9:45 ` [PATCH v2 42/43] wifi: nxpwifi: add Makefile and Kconfig files for nxpwifi compilation David Lin
2024-08-09  9:45 ` [PATCH v2 43/43] wifi: nxpwifi: add nxpwifi related information to MAINTAINERS David Lin
2024-08-14  3:47 ` [PATCH v2 00/43] wifi: nxpwifi: create nxpwifi to support iw61x David Lin
2024-08-15  9:35   ` Kalle Valo
2024-08-16  5:32     ` [EXT] " David Lin
2024-08-22 12:56 ` Sascha Hauer
2024-08-24 13:48   ` Francesco Dolcini
2024-08-26  2:30     ` [EXT] " David Lin
2024-08-26  7:43     ` Sascha Hauer
2024-08-25 20:37   ` Calvin Owens
2024-08-26  2:33     ` [EXT] " David Lin
2024-08-26  2:49       ` Calvin Owens
2024-08-26  2:56         ` David Lin
2024-08-26  5:30           ` Calvin Owens
2024-08-26  5:49             ` David Lin
2024-10-17  7:48   ` Kalle Valo
2024-12-11  3:52     ` [EXT] " David Lin
2025-01-10  5:31       ` Jeff Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240809094533.1660-34-yu-hao.lin@nxp.com \
    --to=yu-hao.lin@nxp.com \
    --cc=briannorris@chromium.org \
    --cc=francesco@dolcini.it \
    --cc=johannes@sipsolutions.net \
    --cc=kvalo@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=tsung-hsien.hsieh@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®