xref: /linux/drivers/net/wireless/nxp/nxpwifi/txrx.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * NXP Wireless LAN device driver: generic TX/RX data handling
4  *
5  * Copyright 2011-2024 NXP
6  */
7 
8 #include "cfg.h"
9 #include "util.h"
10 #include "fw.h"
11 #include "main.h"
12 #include "wmm.h"
13 
14 /*
15  * Parse the RxPD, select the target interface, and dispatch the packet for
16  * handling.
17  */
nxpwifi_handle_rx_packet(struct nxpwifi_adapter * adapter,struct sk_buff * skb)18 int nxpwifi_handle_rx_packet(struct nxpwifi_adapter *adapter,
19 			     struct sk_buff *skb)
20 {
21 	struct nxpwifi_private *priv =
22 		nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY);
23 	struct rxpd *local_rx_pd;
24 	struct nxpwifi_rxinfo *rx_info = NXPWIFI_SKB_RXCB(skb);
25 	int ret;
26 
27 	local_rx_pd = (struct rxpd *)(skb->data);
28 	/* Get the BSS number from rxpd, get corresponding priv */
29 	priv = nxpwifi_get_priv_by_id(adapter, local_rx_pd->bss_num &
30 				      BSS_NUM_MASK, local_rx_pd->bss_type);
31 	if (!priv)
32 		priv = nxpwifi_get_priv(adapter, NXPWIFI_BSS_ROLE_ANY);
33 
34 	if (!priv) {
35 		nxpwifi_dbg(adapter, ERROR,
36 			    "data: priv not found. Drop RX packet\n");
37 		dev_kfree_skb_any(skb);
38 		return -EINVAL;
39 	}
40 
41 	nxpwifi_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data,
42 			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
43 
44 	memset(rx_info, 0, sizeof(*rx_info));
45 	rx_info->bss_num = priv->bss_num;
46 	rx_info->bss_type = priv->bss_type;
47 
48 	if (priv->bss_role == NXPWIFI_BSS_ROLE_UAP)
49 		ret = nxpwifi_process_uap_rx_packet(priv, skb);
50 	else
51 		ret = nxpwifi_process_sta_rx_packet(priv, skb);
52 
53 	return ret;
54 }
55 EXPORT_SYMBOL_GPL(nxpwifi_handle_rx_packet);
56 
57 /*
58  * Add TxPD, validate, send the packet to firmware, then run completion
59  * callback.
60  */
nxpwifi_process_tx(struct nxpwifi_private * priv,struct sk_buff * skb,struct nxpwifi_tx_param * tx_param)61 int nxpwifi_process_tx(struct nxpwifi_private *priv, struct sk_buff *skb,
62 		       struct nxpwifi_tx_param *tx_param)
63 {
64 	int hroom, ret;
65 	struct nxpwifi_adapter *adapter = priv->adapter;
66 	struct txpd *local_tx_pd = NULL;
67 	struct nxpwifi_sta_node *dest_node;
68 	struct ethhdr *hdr = (void *)skb->data;
69 
70 	if (unlikely(!skb->len ||
71 		     skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN)) {
72 		ret = -EINVAL;
73 		goto out;
74 	}
75 
76 	hroom = adapter->intf_hdr_len;
77 
78 	if (priv->bss_role == NXPWIFI_BSS_ROLE_UAP) {
79 		rcu_read_lock();
80 		dest_node = nxpwifi_get_sta_entry(priv, hdr->h_dest);
81 		if (dest_node) {
82 			dest_node->stats.tx_bytes += skb->len;
83 			dest_node->stats.tx_packets++;
84 		}
85 		rcu_read_unlock();
86 		nxpwifi_process_uap_txpd(priv, skb);
87 	} else {
88 		nxpwifi_process_sta_txpd(priv, skb);
89 	}
90 
91 	if ((adapter->data_sent || adapter->tx_lock_flag)) {
92 		skb_queue_tail(&adapter->tx_data_q, skb);
93 		atomic_inc(&adapter->tx_queued);
94 		return 0;
95 	}
96 
97 	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
98 		local_tx_pd = (struct txpd *)(skb->data + hroom);
99 	ret = adapter->if_ops.host_to_card(adapter,
100 					   NXPWIFI_TYPE_DATA,
101 					   skb, tx_param);
102 	nxpwifi_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data,
103 			 min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN));
104 
105 out:
106 	switch (ret) {
107 	case -ENOSR:
108 		nxpwifi_dbg(adapter, DATA, "data: -ENOSR is returned\n");
109 		break;
110 	case -EBUSY:
111 		if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA) &&
112 		    adapter->pps_uapsd_mode && adapter->tx_lock_flag) {
113 			priv->adapter->tx_lock_flag = false;
114 			if (local_tx_pd)
115 				local_tx_pd->flags = 0;
116 		}
117 		nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
118 		break;
119 	case -EINPROGRESS:
120 		break;
121 	case -EINVAL:
122 		nxpwifi_dbg(adapter, ERROR,
123 			    "malformed skb (length: %u, headroom: %u)\n",
124 			    skb->len, skb_headroom(skb));
125 		fallthrough;
126 	case 0:
127 		nxpwifi_write_data_complete(adapter, skb, 0, ret);
128 		break;
129 	default:
130 		nxpwifi_dbg(adapter, ERROR,
131 			    "nxpwifi_write_data_async failed: 0x%X\n",
132 			    ret);
133 		adapter->dbg.num_tx_host_to_card_failure++;
134 		nxpwifi_write_data_complete(adapter, skb, 0, ret);
135 		break;
136 	}
137 
138 	return ret;
139 }
140 
nxpwifi_host_to_card(struct nxpwifi_adapter * adapter,struct sk_buff * skb,struct nxpwifi_tx_param * tx_param)141 static int nxpwifi_host_to_card(struct nxpwifi_adapter *adapter,
142 				struct sk_buff *skb,
143 				struct nxpwifi_tx_param *tx_param)
144 {
145 	struct txpd *local_tx_pd = NULL;
146 	u8 *head_ptr = skb->data;
147 	int ret = 0;
148 	struct nxpwifi_private *priv;
149 	struct nxpwifi_txinfo *tx_info;
150 
151 	tx_info = NXPWIFI_SKB_TXCB(skb);
152 	priv = nxpwifi_get_priv_by_id(adapter, tx_info->bss_num,
153 				      tx_info->bss_type);
154 	if (!priv) {
155 		nxpwifi_dbg(adapter, ERROR,
156 			    "data: priv not found. Drop TX packet\n");
157 		adapter->dbg.num_tx_host_to_card_failure++;
158 		nxpwifi_write_data_complete(adapter, skb, 0, 0);
159 		return ret;
160 	}
161 	if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
162 		local_tx_pd = (struct txpd *)(head_ptr + adapter->intf_hdr_len);
163 
164 	ret = adapter->if_ops.host_to_card(adapter,
165 					   NXPWIFI_TYPE_DATA,
166 					   skb, tx_param);
167 
168 	switch (ret) {
169 	case -ENOSR:
170 		nxpwifi_dbg(adapter, ERROR, "data: -ENOSR is returned\n");
171 		break;
172 	case -EBUSY:
173 		if ((GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA) &&
174 		    adapter->pps_uapsd_mode &&
175 		    adapter->tx_lock_flag) {
176 			priv->adapter->tx_lock_flag = false;
177 			if (local_tx_pd)
178 				local_tx_pd->flags = 0;
179 		}
180 		skb_queue_head(&adapter->tx_data_q, skb);
181 		if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
182 			atomic_add(tx_info->aggr_num, &adapter->tx_queued);
183 		else
184 			atomic_inc(&adapter->tx_queued);
185 		nxpwifi_dbg(adapter, ERROR, "data: -EBUSY is returned\n");
186 		break;
187 	case -EINPROGRESS:
188 		break;
189 	case 0:
190 		nxpwifi_write_data_complete(adapter, skb, 0, ret);
191 		break;
192 	default:
193 		nxpwifi_dbg(adapter, ERROR,
194 			    "nxpwifi_write_data_async failed: 0x%X\n", ret);
195 		adapter->dbg.num_tx_host_to_card_failure++;
196 		nxpwifi_write_data_complete(adapter, skb, 0, ret);
197 		break;
198 	}
199 	return ret;
200 }
201 
202 static int
nxpwifi_dequeue_tx_queue(struct nxpwifi_adapter * adapter)203 nxpwifi_dequeue_tx_queue(struct nxpwifi_adapter *adapter)
204 {
205 	struct sk_buff *skb, *skb_next;
206 	struct nxpwifi_txinfo *tx_info;
207 	struct nxpwifi_tx_param tx_param;
208 
209 	skb = skb_dequeue(&adapter->tx_data_q);
210 	if (!skb)
211 		return -ENOMEM;
212 
213 	tx_info = NXPWIFI_SKB_TXCB(skb);
214 	if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
215 		atomic_sub(tx_info->aggr_num, &adapter->tx_queued);
216 	else
217 		atomic_dec(&adapter->tx_queued);
218 
219 	if (!skb_queue_empty(&adapter->tx_data_q))
220 		skb_next = skb_peek(&adapter->tx_data_q);
221 	else
222 		skb_next = NULL;
223 	tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0);
224 	if (!tx_param.next_pkt_len) {
225 		if (!nxpwifi_wmm_lists_empty(adapter))
226 			tx_param.next_pkt_len = 1;
227 	}
228 	return nxpwifi_host_to_card(adapter, skb, &tx_param);
229 }
230 
231 void
nxpwifi_process_tx_queue(struct nxpwifi_adapter * adapter)232 nxpwifi_process_tx_queue(struct nxpwifi_adapter *adapter)
233 {
234 	do {
235 		if (adapter->data_sent || adapter->tx_lock_flag)
236 			break;
237 		if (nxpwifi_dequeue_tx_queue(adapter))
238 			break;
239 	} while (!skb_queue_empty(&adapter->tx_data_q));
240 }
241 
242 /*
243  * Packet send completion callback handler.
244  *
245  * It either frees the buffer directly or forwards it to another
246  * completion callback which checks conditions, updates statistics,
247  * wakes up stalled traffic queue if required, and then frees the buffer.
248  */
nxpwifi_write_data_complete(struct nxpwifi_adapter * adapter,struct sk_buff * skb,int aggr,int status)249 int nxpwifi_write_data_complete(struct nxpwifi_adapter *adapter,
250 				struct sk_buff *skb, int aggr, int status)
251 {
252 	struct nxpwifi_private *priv;
253 	struct nxpwifi_txinfo *tx_info;
254 	struct netdev_queue *txq;
255 	int index;
256 
257 	if (!skb)
258 		return 0;
259 
260 	tx_info = NXPWIFI_SKB_TXCB(skb);
261 	priv = nxpwifi_get_priv_by_id(adapter, tx_info->bss_num,
262 				      tx_info->bss_type);
263 	if (!priv)
264 		goto done;
265 
266 	nxpwifi_set_trans_start(priv->netdev);
267 
268 	if (tx_info->flags & NXPWIFI_BUF_FLAG_BRIDGED_PKT)
269 		atomic_dec_return(&adapter->pending_bridged_pkts);
270 
271 	if (tx_info->flags & NXPWIFI_BUF_FLAG_AGGR_PKT)
272 		goto done;
273 
274 	if (!status) {
275 		priv->stats.tx_packets++;
276 		priv->stats.tx_bytes += tx_info->pkt_len;
277 		if (priv->tx_timeout_cnt)
278 			priv->tx_timeout_cnt = 0;
279 	} else {
280 		priv->stats.tx_errors++;
281 	}
282 
283 	if (aggr)
284 		/* For skb_aggr, do not wake up tx queue */
285 		goto done;
286 
287 	atomic_dec(&adapter->tx_pending);
288 
289 	index = nxpwifi_1d_to_wmm_queue[skb->priority];
290 	if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) {
291 		txq = netdev_get_tx_queue(priv->netdev, index);
292 		if (netif_tx_queue_stopped(txq)) {
293 			netif_tx_wake_queue(txq);
294 			nxpwifi_dbg(adapter, DATA, "wake queue: %d\n", index);
295 		}
296 	}
297 done:
298 	dev_kfree_skb_any(skb);
299 
300 	return 0;
301 }
302 EXPORT_SYMBOL_GPL(nxpwifi_write_data_complete);
303 
nxpwifi_parse_tx_status_event(struct nxpwifi_private * priv,void * event_body)304 void nxpwifi_parse_tx_status_event(struct nxpwifi_private *priv,
305 				   void *event_body)
306 {
307 	struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
308 	struct sk_buff *ack_skb;
309 	struct nxpwifi_txinfo *tx_info;
310 
311 	if (!tx_status->tx_token_id)
312 		return;
313 
314 	spin_lock_bh(&priv->ack_status_lock);
315 	ack_skb = xa_erase(&priv->ack_status_frames, tx_status->tx_token_id);
316 	spin_unlock_bh(&priv->ack_status_lock);
317 
318 	if (ack_skb) {
319 		tx_info = NXPWIFI_SKB_TXCB(ack_skb);
320 
321 		if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS) {
322 			/* consumes ack_skb */
323 			skb_complete_wifi_ack(ack_skb, !tx_status->status);
324 		} else {
325 			/* Remove broadcast address which was added by driver */
326 			memmove(ack_skb->data +
327 				sizeof(struct ieee80211_hdr_3addr) +
328 				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
329 				ack_skb->data +
330 				sizeof(struct ieee80211_hdr_3addr) +
331 				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
332 				ETH_ALEN, ack_skb->len -
333 				(sizeof(struct ieee80211_hdr_3addr) +
334 				NXPWIFI_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
335 				ETH_ALEN));
336 			ack_skb->len = ack_skb->len - ETH_ALEN;
337 			/*
338 			 * Remove driver's proprietary header including 2 bytes
339 			 * of packet length and pass actual management frame buffer
340 			 * to cfg80211.
341 			 */
342 			cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
343 						ack_skb->data +
344 						NXPWIFI_MGMT_FRAME_HEADER_SIZE +
345 						sizeof(u16), ack_skb->len -
346 						(NXPWIFI_MGMT_FRAME_HEADER_SIZE
347 						 + sizeof(u16)),
348 						!tx_status->status, GFP_ATOMIC);
349 			dev_kfree_skb_any(ack_skb);
350 		}
351 	}
352 }
353