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