xref: /linux/drivers/net/wireless/nxp/nxpwifi/uap_txrx.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * NXP Wireless LAN device driver: AP TX and RX data handling
4  *
5  * Copyright 2011-2024 NXP
6  */
7 
8 #include "cfg.h"
9 #include "main.h"
10 #include "wmm.h"
11 #include "11n_aggr.h"
12 #include "11n_rxreorder.h"
13 
14 /*
15  * Drop bridged pkts from RA list until pending <= low threshold; return true if
16  * any.
17  */
18 static bool
nxpwifi_uap_del_tx_pkts_in_ralist(struct nxpwifi_private * priv,struct list_head * ra_list_head,int tid)19 nxpwifi_uap_del_tx_pkts_in_ralist(struct nxpwifi_private *priv,
20 				  struct list_head *ra_list_head,
21 				  int tid)
22 {
23 	struct nxpwifi_ra_list_tbl *ra_list;
24 	struct sk_buff *skb, *tmp;
25 	bool pkt_deleted = false;
26 	struct nxpwifi_txinfo *tx_info;
27 	struct nxpwifi_adapter *adapter = priv->adapter;
28 
29 	list_for_each_entry(ra_list, ra_list_head, list) {
30 		if (skb_queue_empty(&ra_list->skb_head))
31 			continue;
32 
33 		skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) {
34 			tx_info = NXPWIFI_SKB_TXCB(skb);
35 			if (tx_info->flags & NXPWIFI_BUF_FLAG_BRIDGED_PKT) {
36 				__skb_unlink(skb, &ra_list->skb_head);
37 				nxpwifi_write_data_complete(adapter, skb, 0,
38 							    -1);
39 				if (ra_list->tx_paused)
40 					priv->wmm.pkts_paused[tid]--;
41 				else
42 					atomic_dec(&priv->wmm.tx_pkts_queued);
43 				pkt_deleted = true;
44 			}
45 			if ((atomic_read(&adapter->pending_bridged_pkts) <=
46 					     NXPWIFI_BRIDGED_PKTS_THR_LOW))
47 				break;
48 		}
49 	}
50 
51 	return pkt_deleted;
52 }
53 
54 /* Delete bridged pkts from one RA list; rotate index to keep fairness. */
nxpwifi_uap_cleanup_tx_queues(struct nxpwifi_private * priv)55 static void nxpwifi_uap_cleanup_tx_queues(struct nxpwifi_private *priv)
56 {
57 	struct list_head *ra_list;
58 	int i;
59 
60 	spin_lock_bh(&priv->wmm.ra_list_spinlock);
61 
62 	for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) {
63 		if (priv->del_list_idx == MAX_NUM_TID)
64 			priv->del_list_idx = 0;
65 		ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list;
66 		if (nxpwifi_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) {
67 			priv->del_list_idx++;
68 			break;
69 		}
70 	}
71 
72 	spin_unlock_bh(&priv->wmm.ra_list_spinlock);
73 }
74 
75 static void
nxpwifi_uap_queue_bridged_pkt(struct nxpwifi_private * priv,struct sk_buff * skb)76 nxpwifi_uap_queue_bridged_pkt(struct nxpwifi_private *priv,
77 			      struct sk_buff *skb)
78 {
79 	struct nxpwifi_adapter *adapter = priv->adapter;
80 	struct uap_rxpd *uap_rx_pd;
81 	struct rx_packet_hdr *rx_pkt_hdr;
82 	struct sk_buff *new_skb;
83 	struct nxpwifi_txinfo *tx_info;
84 	int hdr_chop;
85 	struct ethhdr *p_ethhdr;
86 	struct nxpwifi_sta_node *src_node;
87 	int index;
88 
89 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
90 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
91 
92 	if ((atomic_read(&adapter->pending_bridged_pkts) >=
93 					     NXPWIFI_BRIDGED_PKTS_THR_HIGH)) {
94 		nxpwifi_dbg(adapter, ERROR,
95 			    "Tx: Bridge packet limit reached. Drop packet!\n");
96 		kfree_skb(skb);
97 		nxpwifi_uap_cleanup_tx_queues(priv);
98 		return;
99 	}
100 
101 	if (sizeof(*rx_pkt_hdr) +
102 	    le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) {
103 		priv->stats.rx_dropped++;
104 		dev_kfree_skb_any(skb);
105 		return;
106 	}
107 
108 	if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
109 		     sizeof(bridge_tunnel_header))) ||
110 	    (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
111 		     sizeof(rfc1042_header)) &&
112 	     rx_pkt_hdr->rfc1042_hdr.snap_type != htons(ETH_P_AARP) &&
113 	     rx_pkt_hdr->rfc1042_hdr.snap_type != htons(ETH_P_IPX))) {
114 		/*
115 		 * Replace the 803 header and rfc1042 header (llc/snap) with
116 		 * an Ethernet II header, keep the src/dst and snap_type
117 		 * (ethertype).
118 		 *
119 		 * The firmware only passes up SNAP frames converting all RX
120 		 * data from 802.11 to 802.2/LLC/SNAP frames.
121 		 *
122 		 * To create the Ethernet II, just move the src, dst address
123 		 * right before the snap_type.
124 		 */
125 		p_ethhdr = (struct ethhdr *)
126 			((u8 *)(&rx_pkt_hdr->eth803_hdr)
127 			 + sizeof(rx_pkt_hdr->eth803_hdr)
128 			 + sizeof(rx_pkt_hdr->rfc1042_hdr)
129 			 - sizeof(rx_pkt_hdr->eth803_hdr.h_dest)
130 			 - sizeof(rx_pkt_hdr->eth803_hdr.h_source)
131 			 - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type));
132 		memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source,
133 		       sizeof(p_ethhdr->h_source));
134 		memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest,
135 		       sizeof(p_ethhdr->h_dest));
136 		/*
137 		 * Chop off the rxpd + the excess memory from
138 		 * 802.2/llc/snap header that was removed.
139 		 */
140 		hdr_chop = (u8 *)p_ethhdr - (u8 *)uap_rx_pd;
141 	} else {
142 		/* Chop off the rxpd */
143 		hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
144 	}
145 
146 	/*
147 	 * Chop off the leading header bytes so that it points
148 	 * to the start of either the reconstructed EthII frame
149 	 * or the 802.2/llc/snap frame.
150 	 */
151 	skb_pull(skb, hdr_chop);
152 
153 	if (skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN) {
154 		nxpwifi_dbg(adapter, ERROR,
155 			    "data: Tx: insufficient skb headroom %d\n",
156 			    skb_headroom(skb));
157 		/* Insufficient skb headroom - allocate a new skb */
158 		new_skb =
159 			skb_realloc_headroom(skb, NXPWIFI_MIN_DATA_HEADER_LEN);
160 		if (unlikely(!new_skb)) {
161 			nxpwifi_dbg(adapter, ERROR,
162 				    "Tx: cannot allocate new_skb\n");
163 			kfree_skb(skb);
164 			priv->stats.tx_dropped++;
165 			return;
166 		}
167 
168 		kfree_skb(skb);
169 		skb = new_skb;
170 		nxpwifi_dbg(adapter, INFO,
171 			    "info: new skb headroom %d\n",
172 			    skb_headroom(skb));
173 	}
174 
175 	tx_info = NXPWIFI_SKB_TXCB(skb);
176 	memset(tx_info, 0, sizeof(*tx_info));
177 	tx_info->bss_num = priv->bss_num;
178 	tx_info->bss_type = priv->bss_type;
179 	tx_info->flags |= NXPWIFI_BUF_FLAG_BRIDGED_PKT;
180 
181 	rcu_read_lock();
182 	src_node = nxpwifi_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source);
183 	if (src_node) {
184 		src_node->stats.last_rx = jiffies;
185 		src_node->stats.rx_bytes += skb->len;
186 		src_node->stats.rx_packets++;
187 		src_node->stats.last_tx_rate = uap_rx_pd->rx_rate;
188 		src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info;
189 	}
190 	rcu_read_unlock();
191 
192 	if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
193 		/*
194 		 * Update bridge packet statistics as the
195 		 * packet is not going to kernel/upper layer.
196 		 */
197 		priv->stats.rx_bytes += skb->len;
198 		priv->stats.rx_packets++;
199 
200 		/*
201 		 * Sending bridge packet to TX queue, so save the packet
202 		 * length in TXCB to update statistics in TX complete.
203 		 */
204 		tx_info->pkt_len = skb->len;
205 	}
206 
207 	__net_timestamp(skb);
208 
209 	index = nxpwifi_1d_to_wmm_queue[skb->priority];
210 	atomic_inc(&priv->wmm_tx_pending[index]);
211 	nxpwifi_wmm_add_buf_txqueue(priv, skb);
212 	atomic_inc(&adapter->tx_pending);
213 	atomic_inc(&adapter->pending_bridged_pkts);
214 
215 	nxpwifi_queue_work(adapter, &adapter->main_work);
216 }
217 
218 /* AP fwd: mcast/bcast -> up + bridge; unicast -> bridge if RA assoc, else up. */
nxpwifi_handle_uap_rx_forward(struct nxpwifi_private * priv,struct sk_buff * skb)219 int nxpwifi_handle_uap_rx_forward(struct nxpwifi_private *priv,
220 				  struct sk_buff *skb)
221 {
222 	struct nxpwifi_adapter *adapter = priv->adapter;
223 	struct uap_rxpd *uap_rx_pd;
224 	struct rx_packet_hdr *rx_pkt_hdr;
225 	u8 ra[ETH_ALEN];
226 	struct sk_buff *skb_uap;
227 	struct nxpwifi_sta_node *node;
228 
229 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
230 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
231 
232 	/* don't do packet forwarding in disconnected state */
233 	if (!priv->media_connected) {
234 		nxpwifi_dbg(adapter, ERROR,
235 			    "drop packet in disconnected state.\n");
236 		dev_kfree_skb_any(skb);
237 		return 0;
238 	}
239 
240 	memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
241 
242 	if (is_multicast_ether_addr(ra)) {
243 		skb_uap = skb_copy(skb, GFP_ATOMIC);
244 		if (likely(skb_uap)) {
245 			nxpwifi_uap_queue_bridged_pkt(priv, skb_uap);
246 		} else {
247 			nxpwifi_dbg(adapter, ERROR,
248 				    "failed to copy skb for uAP\n");
249 			priv->stats.rx_dropped++;
250 			dev_kfree_skb_any(skb);
251 			return -ENOMEM;
252 		}
253 	} else {
254 		node = nxpwifi_get_sta_entry_rcu(priv, ra);
255 		if (node) {
256 			/* Requeue Intra-BSS packet */
257 			nxpwifi_uap_queue_bridged_pkt(priv, skb);
258 			return 0;
259 		}
260 	}
261 
262 	/* Forward unicat/Inter-BSS packets to kernel. */
263 	return nxpwifi_process_rx_packet(priv, skb);
264 }
265 
nxpwifi_uap_recv_packet(struct nxpwifi_private * priv,struct sk_buff * skb)266 int nxpwifi_uap_recv_packet(struct nxpwifi_private *priv,
267 			    struct sk_buff *skb)
268 {
269 	struct nxpwifi_adapter *adapter = priv->adapter;
270 	struct nxpwifi_sta_node *src_node, *dst_node;
271 	struct ethhdr *p_ethhdr;
272 	struct sk_buff *skb_uap;
273 	struct nxpwifi_txinfo *tx_info;
274 
275 	if (!skb)
276 		return -ENOMEM;
277 
278 	p_ethhdr = (void *)skb->data;
279 	rcu_read_lock();
280 	src_node = nxpwifi_get_sta_entry(priv, p_ethhdr->h_source);
281 	if (src_node) {
282 		src_node->stats.last_rx = jiffies;
283 		src_node->stats.rx_bytes += skb->len;
284 		src_node->stats.rx_packets++;
285 	}
286 	dst_node = nxpwifi_get_sta_entry(priv, p_ethhdr->h_dest);
287 	rcu_read_unlock();
288 
289 	if (is_multicast_ether_addr(p_ethhdr->h_dest) || dst_node) {
290 		if (skb_headroom(skb) < NXPWIFI_MIN_DATA_HEADER_LEN)
291 			skb_uap =
292 			skb_realloc_headroom(skb, NXPWIFI_MIN_DATA_HEADER_LEN);
293 		else
294 			skb_uap = skb_copy(skb, GFP_ATOMIC);
295 
296 		if (likely(skb_uap)) {
297 			tx_info = NXPWIFI_SKB_TXCB(skb_uap);
298 			memset(tx_info, 0, sizeof(*tx_info));
299 			tx_info->bss_num = priv->bss_num;
300 			tx_info->bss_type = priv->bss_type;
301 			tx_info->flags |= NXPWIFI_BUF_FLAG_BRIDGED_PKT;
302 			__net_timestamp(skb_uap);
303 			nxpwifi_wmm_add_buf_txqueue(priv, skb_uap);
304 			atomic_inc(&adapter->tx_pending);
305 			atomic_inc(&adapter->pending_bridged_pkts);
306 			if ((atomic_read(&adapter->pending_bridged_pkts) >=
307 					NXPWIFI_BRIDGED_PKTS_THR_HIGH)) {
308 				nxpwifi_dbg(adapter, ERROR,
309 					    "Tx: Bridge packet limit reached. Drop packet!\n");
310 				nxpwifi_uap_cleanup_tx_queues(priv);
311 			}
312 
313 		} else {
314 			nxpwifi_dbg(adapter, ERROR, "failed to allocate skb_uap");
315 		}
316 
317 		nxpwifi_queue_work(adapter, &adapter->main_work);
318 		/* Don't forward Intra-BSS unicast packet to upper layer*/
319 
320 		if (dst_node)
321 			return 0;
322 	}
323 
324 	skb->dev = priv->netdev;
325 	skb->protocol = eth_type_trans(skb, priv->netdev);
326 	skb->ip_summed = CHECKSUM_NONE;
327 
328 	/* Forward multicast/broadcast packet to upper layer*/
329 	netif_rx(skb);
330 	return 0;
331 }
332 
333 /* Process AP RX: check RxPD/len, handle mgmt or 11n reorder/AMSDU, then forward. */
nxpwifi_process_uap_rx_packet(struct nxpwifi_private * priv,struct sk_buff * skb)334 int nxpwifi_process_uap_rx_packet(struct nxpwifi_private *priv,
335 				  struct sk_buff *skb)
336 {
337 	struct nxpwifi_adapter *adapter = priv->adapter;
338 	int ret;
339 	struct uap_rxpd *uap_rx_pd;
340 	struct rx_packet_hdr *rx_pkt_hdr;
341 	u16 rx_pkt_type;
342 	u8 ta[ETH_ALEN], pkt_type;
343 	struct nxpwifi_sta_node *node;
344 
345 	uap_rx_pd = (struct uap_rxpd *)(skb->data);
346 	rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
347 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
348 
349 	if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
350 	    sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) {
351 		nxpwifi_dbg(adapter, ERROR,
352 			    "wrong rx packet for struct ethhdr: len=%d, offset=%d\n",
353 			    skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
354 		priv->stats.rx_dropped++;
355 		dev_kfree_skb_any(skb);
356 		return 0;
357 	}
358 
359 	ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
360 
361 	if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
362 	     le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16)skb->len) {
363 		nxpwifi_dbg(adapter, ERROR,
364 			    "wrong rx packet: len=%d, offset=%d, length=%d\n",
365 			    skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
366 			    le16_to_cpu(uap_rx_pd->rx_pkt_length));
367 		priv->stats.rx_dropped++;
368 		rcu_read_lock();
369 		node = nxpwifi_get_sta_entry(priv, ta);
370 		if (node)
371 			node->stats.tx_failed++;
372 		rcu_read_unlock();
373 
374 		dev_kfree_skb_any(skb);
375 		return 0;
376 	}
377 
378 	if (rx_pkt_type == PKT_TYPE_MGMT) {
379 		ret = nxpwifi_process_mgmt_packet(priv, skb);
380 		if (ret && (ret != -EINPROGRESS))
381 			nxpwifi_dbg(adapter, DATA, "Rx of mgmt packet failed");
382 		if (ret != -EINPROGRESS)
383 			dev_kfree_skb_any(skb);
384 		return ret;
385 	}
386 
387 	if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
388 		rcu_read_lock();
389 		node = nxpwifi_get_sta_entry(priv, ta);
390 		if (node)
391 			node->rx_seq[uap_rx_pd->priority] =
392 						le16_to_cpu(uap_rx_pd->seq_num);
393 		rcu_read_unlock();
394 	}
395 
396 	if (!priv->ap_11n_enabled ||
397 	    (!nxpwifi_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
398 	    (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
399 		ret = nxpwifi_handle_uap_rx_forward(priv, skb);
400 		return ret;
401 	}
402 
403 	/* Reorder and send to kernel */
404 	pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
405 	ret = nxpwifi_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
406 					 uap_rx_pd->priority, ta, pkt_type, skb);
407 
408 	if (ret || rx_pkt_type == PKT_TYPE_BAR)
409 		dev_kfree_skb_any(skb);
410 
411 	if (ret)
412 		priv->stats.rx_dropped++;
413 
414 	return ret;
415 }
416 
417 /*
418  * Build TxPD for AP TX: push aligned TxPD; set bss, len/off, prio, delay, txctl,
419  * flags.
420  */
nxpwifi_process_uap_txpd(struct nxpwifi_private * priv,struct sk_buff * skb)421 void nxpwifi_process_uap_txpd(struct nxpwifi_private *priv,
422 			      struct sk_buff *skb)
423 {
424 	struct nxpwifi_adapter *adapter = priv->adapter;
425 	struct uap_txpd *txpd;
426 	struct nxpwifi_txinfo *tx_info = NXPWIFI_SKB_TXCB(skb);
427 	int pad;
428 	u16 pkt_type, pkt_offset;
429 	int hroom = adapter->intf_hdr_len;
430 
431 	pkt_type = nxpwifi_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0;
432 
433 	pad = ((uintptr_t)skb->data - (sizeof(*txpd) + hroom)) &
434 	       (NXPWIFI_DMA_ALIGN_SZ - 1);
435 
436 	skb_push(skb, sizeof(*txpd) + pad);
437 
438 	txpd = (struct uap_txpd *)skb->data;
439 	memset(txpd, 0, sizeof(*txpd));
440 	txpd->bss_num = priv->bss_num;
441 	txpd->bss_type = priv->bss_type;
442 	txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - (sizeof(*txpd) +
443 						pad)));
444 	txpd->priority = (u8)skb->priority;
445 
446 	txpd->pkt_delay_2ms = nxpwifi_wmm_compute_drv_pkt_delay(priv, skb);
447 
448 	if (tx_info->flags & NXPWIFI_BUF_FLAG_EAPOL_TX_STATUS ||
449 	    tx_info->flags & NXPWIFI_BUF_FLAG_ACTION_TX_STATUS) {
450 		txpd->tx_token_id = tx_info->ack_frame_id;
451 		txpd->flags |= NXPWIFI_TXPD_FLAGS_REQ_TX_STATUS;
452 	}
453 
454 	if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
455 		/*
456 		 * Set the priority specific tx_control field, setting of 0 will
457 		 * cause the default value to be used later in this function.
458 		 */
459 		txpd->tx_control =
460 		    cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]);
461 
462 	/* Offset of actual data */
463 	pkt_offset = sizeof(*txpd) + pad;
464 	if (pkt_type == PKT_TYPE_MGMT) {
465 		/* Set the packet type and add header for management frame */
466 		txpd->tx_pkt_type = cpu_to_le16(pkt_type);
467 		pkt_offset += NXPWIFI_MGMT_FRAME_HEADER_SIZE;
468 	}
469 
470 	txpd->tx_pkt_offset = cpu_to_le16(pkt_offset);
471 
472 	/* make space for adapter->intf_hdr_len */
473 	skb_push(skb, hroom);
474 
475 	if (!txpd->tx_control)
476 		/* TxCtrl set by user or default */
477 		txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl);
478 }
479