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