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