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