1 /** @file mlan_uap_txrx.c
2 *
3 * @brief This file contains AP mode transmit and receive functions
4 *
5 *
6 * Copyright 2009-2021 NXP
7 *
8 * This software file (the File) is distributed by NXP
9 * under the terms of the GNU General Public License Version 2, June 1991
10 * (the License). You may use, redistribute and/or modify the File in
11 * accordance with the terms and conditions of the License, a copy of which
12 * is available by writing to the Free Software Foundation, Inc.,
13 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15 *
16 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19 * this warranty disclaimer.
20 *
21 */
22
23 /********************************************************
24 Change log:
25 02/05/2009: initial version
26 ********************************************************/
27
28 #include "mlan.h"
29 #include "mlan_util.h"
30 #include "mlan_fw.h"
31 #ifdef STA_SUPPORT
32 #include "mlan_join.h"
33 #endif
34 #include "mlan_main.h"
35 #include "mlan_uap.h"
36 #include "mlan_wmm.h"
37 #include "mlan_11n_aggr.h"
38 #include "mlan_11n_rxreorder.h"
39 #ifdef DRV_EMBEDDED_AUTHENTICATOR
40 #include "authenticator_api.h"
41 #endif
42
43 /********************************************************
44 Local Functions
45 ********************************************************/
46
47 /**
48 * @brief This function processes received packet and forwards it
49 * to kernel/upper layer
50 *
51 * @param pmadapter A pointer to mlan_adapter
52 * @param pmbuf A pointer to mlan_buffer which includes the received packet
53 *
54 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
55 */
wlan_upload_uap_rx_packet(pmlan_adapter pmadapter,pmlan_buffer pmbuf)56 static mlan_status wlan_upload_uap_rx_packet(pmlan_adapter pmadapter,
57 pmlan_buffer pmbuf)
58 {
59 mlan_status ret = MLAN_STATUS_SUCCESS;
60 #ifdef DEBUG_LEVEL1
61 pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
62 #endif
63 PRxPD prx_pd;
64 ENTER();
65 prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
66
67 /* Chop off RxPD */
68 pmbuf->data_len -= prx_pd->rx_pkt_offset;
69 pmbuf->data_offset += prx_pd->rx_pkt_offset;
70 pmbuf->pparent = MNULL;
71
72 DBG_HEXDUMP(MDAT_D, "uAP RxPD", (t_u8 *)prx_pd,
73 MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
74 DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
75 ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
76 MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
77
78 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
79 &pmbuf->out_ts_sec,
80 &pmbuf->out_ts_usec);
81 PRINTM_NETINTF(MDATA, priv);
82 PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
83 pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
84 prx_pd->priority);
85 ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
86 pmbuf);
87 if (ret == MLAN_STATUS_FAILURE) {
88 PRINTM(MERROR,
89 "uAP Rx Error: moal_recv_packet returned error\n");
90 pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
91 }
92
93 if (ret != MLAN_STATUS_PENDING)
94 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
95 #ifdef USB
96 else if (IS_USB(pmadapter->card_type))
97 pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
98 MNULL,
99 pmadapter->rx_data_ep,
100 ret);
101 #endif
102 LEAVE();
103
104 return ret;
105 }
106
107 /**
108 * @brief This function will check if unicast packet need be dropped
109 *
110 * @param priv A pointer to mlan_private
111 * @param mac mac address to find in station list table
112 *
113 * @return MLAN_STATUS_FAILURE -- drop packet, otherwise forward to
114 * network stack
115 */
wlan_check_unicast_packet(mlan_private * priv,t_u8 * mac)116 static mlan_status wlan_check_unicast_packet(mlan_private *priv, t_u8 *mac)
117 {
118 int j;
119 sta_node *sta_ptr = MNULL;
120 pmlan_adapter pmadapter = priv->adapter;
121 pmlan_private pmpriv = MNULL;
122 t_u8 pkt_type = 0;
123 mlan_status ret = MLAN_STATUS_SUCCESS;
124 ENTER();
125 for (j = 0; j < MLAN_MAX_BSS_NUM; ++j) {
126 pmpriv = pmadapter->priv[j];
127 if (pmpriv) {
128 if (GET_BSS_ROLE(pmpriv) == MLAN_BSS_ROLE_STA)
129 continue;
130 sta_ptr = wlan_get_station_entry(pmpriv, mac);
131 if (sta_ptr) {
132 if (pmpriv == priv)
133 pkt_type = PKT_INTRA_UCAST;
134 else
135 pkt_type = PKT_INTER_UCAST;
136 break;
137 }
138 }
139 }
140 if ((pkt_type == PKT_INTRA_UCAST) &&
141 (priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) {
142 PRINTM(MDATA, "Drop INTRA_UCAST packet\n");
143 ret = MLAN_STATUS_FAILURE;
144 } else if ((pkt_type == PKT_INTER_UCAST) &&
145 (priv->pkt_fwd & PKT_FWD_INTER_UCAST)) {
146 PRINTM(MDATA, "Drop INTER_UCAST packet\n");
147 ret = MLAN_STATUS_FAILURE;
148 }
149 LEAVE();
150 return ret;
151 }
152 /********************************************************
153 Global Functions
154 ********************************************************/
155 /**
156 * @brief This function fill the txpd for tx packet
157 *
158 * @param priv A pointer to mlan_private structure
159 * @param pmbuf A pointer to the mlan_buffer for process
160 *
161 * @return headptr or MNULL
162 */
wlan_ops_uap_process_txpd(t_void * priv,pmlan_buffer pmbuf)163 t_void *wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf)
164 {
165 pmlan_private pmpriv = (pmlan_private)priv;
166 TxPD *plocal_tx_pd;
167 t_u8 *head_ptr = MNULL;
168 t_u32 pkt_type;
169 t_u32 tx_control;
170 t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
171
172 ENTER();
173
174 if (!pmbuf->data_len) {
175 PRINTM(MERROR, "uAP Tx Error: Invalid packet length: %d\n",
176 pmbuf->data_len);
177 pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
178 goto done;
179 }
180 if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
181 memcpy_ext(pmpriv->adapter, &pkt_type,
182 pmbuf->pbuf + pmbuf->data_offset, sizeof(pkt_type),
183 sizeof(pkt_type));
184 memcpy_ext(pmpriv->adapter, &tx_control,
185 pmbuf->pbuf + pmbuf->data_offset + sizeof(pkt_type),
186 sizeof(tx_control), sizeof(tx_control));
187 pmbuf->data_offset += sizeof(pkt_type) + sizeof(tx_control);
188 pmbuf->data_len -= sizeof(pkt_type) + sizeof(tx_control);
189 }
190 if (pmbuf->data_offset <
191 (sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT)) {
192 PRINTM(MERROR,
193 "not enough space for TxPD: headroom=%d pkt_len=%d, required=%d\n",
194 pmbuf->data_offset, pmbuf->data_len,
195 sizeof(TxPD) + pmpriv->intf_hr_len + DMA_ALIGNMENT);
196 DBG_HEXDUMP(MDAT_D, "drop pkt",
197 pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len);
198 pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
199 goto done;
200 }
201
202 /* head_ptr should be aligned */
203 head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) -
204 pmpriv->intf_hr_len;
205 head_ptr = (t_u8 *)((t_ptr)head_ptr & ~((t_ptr)(DMA_ALIGNMENT - 1)));
206
207 plocal_tx_pd = (TxPD *)(head_ptr + pmpriv->intf_hr_len);
208 memset(pmpriv->adapter, plocal_tx_pd, 0, sizeof(TxPD));
209
210 /* Set the BSS number to TxPD */
211 plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv);
212 plocal_tx_pd->bss_type = pmpriv->bss_type;
213
214 plocal_tx_pd->tx_pkt_length = (t_u16)pmbuf->data_len;
215
216 plocal_tx_pd->priority = (t_u8)pmbuf->priority;
217 plocal_tx_pd->pkt_delay_2ms =
218 wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf);
219
220 if (plocal_tx_pd->priority <
221 NELEMENTS(pmpriv->wmm.user_pri_pkt_tx_ctrl))
222 /*
223 * Set the priority specific tx_control field, setting of 0 will
224 * cause the default value to be used later in this function
225 */
226 plocal_tx_pd->tx_control =
227 pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->priority];
228
229 if (pmbuf->flags & MLAN_BUF_FLAG_TX_STATUS) {
230 plocal_tx_pd->tx_control_1 |= pmbuf->tx_seq_num << 8;
231 plocal_tx_pd->flags |= MRVDRV_TxPD_FLAGS_TX_PACKET_STATUS;
232 }
233
234 /* Offset of actual data */
235 plocal_tx_pd->tx_pkt_offset = (t_u16)(
236 (t_ptr)pmbuf->pbuf + pmbuf->data_offset - (t_ptr)plocal_tx_pd);
237
238 if (!plocal_tx_pd->tx_control) {
239 /* TxCtrl set by user or default */
240 plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl;
241 }
242
243 if (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) {
244 plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type;
245 plocal_tx_pd->tx_control = tx_control;
246 }
247
248 if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) {
249 if (pmbuf->u.tx_info.data_rate) {
250 memcpy_ext(pmpriv->adapter, dst_mac,
251 pmbuf->pbuf + pmbuf->data_offset,
252 sizeof(dst_mac), sizeof(dst_mac));
253 plocal_tx_pd->tx_control |=
254 (wlan_ieee_rateid_to_mrvl_rateid(
255 pmpriv, pmbuf->u.tx_info.data_rate,
256 dst_mac)
257 << 16);
258 plocal_tx_pd->tx_control |= TXPD_TXRATE_ENABLE;
259 }
260 plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.channel << 21;
261 if (pmbuf->u.tx_info.bw) {
262 plocal_tx_pd->tx_control_1 |= pmbuf->u.tx_info.bw << 16;
263 plocal_tx_pd->tx_control_1 |= TXPD_BW_ENABLE;
264 }
265 if (pmbuf->u.tx_info.tx_power.tp.hostctl)
266 plocal_tx_pd->tx_control |=
267 (t_u32)pmbuf->u.tx_info.tx_power.val;
268 if (pmbuf->u.tx_info.retry_limit) {
269 plocal_tx_pd->tx_control |= pmbuf->u.tx_info.retry_limit
270 << 8;
271 plocal_tx_pd->tx_control |= TXPD_RETRY_ENABLE;
272 }
273 }
274 if (pmbuf->flags & MLAN_BUF_FLAG_MC_AGGR_PKT) {
275 tx_ctrl *ctrl = (tx_ctrl *)&plocal_tx_pd->tx_control;
276 mc_tx_ctrl *mc_ctrl =
277 (mc_tx_ctrl *)&plocal_tx_pd->pkt_delay_2ms;
278 plocal_tx_pd->tx_pkt_type = PKT_TYPE_802DOT11_MC_AGGR;
279 if (pmbuf->u.mc_tx_info.mc_pkt_flags & MC_FLAG_START_CYCLE)
280 ctrl->mc_cycle_start = MTRUE;
281 else
282 ctrl->mc_cycle_start = MFALSE;
283 if (pmbuf->u.mc_tx_info.mc_pkt_flags & MC_FLAG_END_CYCLE)
284 ctrl->mc_cycle_end = MTRUE;
285 else
286 ctrl->mc_cycle_end = MFALSE;
287 if (pmbuf->u.mc_tx_info.mc_pkt_flags & MC_FLAG_START_AMPDU)
288 ctrl->mc_ampdu_start = MTRUE;
289 else
290 ctrl->mc_ampdu_start = MFALSE;
291 if (pmbuf->u.mc_tx_info.mc_pkt_flags & MC_FLAG_END_AMPDU)
292 ctrl->mc_ampdu_end = MTRUE;
293 else
294 ctrl->mc_ampdu_end = MFALSE;
295 if (pmbuf->u.mc_tx_info.mc_pkt_flags & MC_FLAG_RETRY)
296 ctrl->mc_pkt_retry = MTRUE;
297 else
298 ctrl->mc_pkt_retry = MFALSE;
299 ctrl->bw = pmbuf->u.mc_tx_info.bandwidth & 0x7;
300 ctrl->tx_rate = pmbuf->u.mc_tx_info.mcs_index & 0x1f;
301 mc_ctrl->abs_tsf_expirytime =
302 wlan_cpu_to_le32(pmbuf->u.mc_tx_info.pkt_expiry);
303 mc_ctrl->mc_seq = wlan_cpu_to_le16(pmbuf->u.mc_tx_info.seq_num);
304 }
305
306 endian_convert_TxPD(plocal_tx_pd);
307
308 /* Adjust the data offset and length to include TxPD in pmbuf */
309 pmbuf->data_len += pmbuf->data_offset;
310 pmbuf->data_offset = (t_u32)((t_ptr)head_ptr - (t_ptr)pmbuf->pbuf);
311 pmbuf->data_len -= pmbuf->data_offset;
312
313 done:
314 LEAVE();
315 return head_ptr;
316 }
317
318 /**
319 * @brief This function processes received packet and forwards it
320 * to kernel/upper layer
321 *
322 * @param adapter A pointer to mlan_adapter
323 * @param pmbuf A pointer to mlan_buffer which includes the received packet
324 *
325 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
326 */
wlan_ops_uap_process_rx_packet(t_void * adapter,pmlan_buffer pmbuf)327 mlan_status wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf)
328 {
329 pmlan_adapter pmadapter = (pmlan_adapter)adapter;
330 mlan_status ret = MLAN_STATUS_SUCCESS;
331 RxPD *prx_pd;
332 wlan_mgmt_pkt *puap_pkt_hdr = MNULL;
333
334 RxPacketHdr_t *prx_pkt;
335 pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
336 t_u8 ta[MLAN_MAC_ADDR_LENGTH];
337 t_u16 rx_pkt_type = 0;
338 sta_node *sta_ptr = MNULL;
339 #ifdef DRV_EMBEDDED_AUTHENTICATOR
340 t_u8 eapol_type[2] = {0x88, 0x8e};
341 #endif
342 t_u16 adj_rx_rate = 0;
343 t_u8 antenna = 0;
344
345 t_u32 last_rx_sec = 0;
346 t_u32 last_rx_usec = 0;
347 t_u8 ext_rate_info = 0;
348
349 ENTER();
350
351 prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
352 /* Endian conversion */
353 endian_convert_RxPD(prx_pd);
354
355 if (prx_pd->flags & RXPD_FLAG_EXTRA_HEADER) {
356 endian_convert_RxPD_extra_header(
357 (rxpd_extra_info *)((t_u8 *)prx_pd + sizeof(*prx_pd)));
358 }
359
360 if (priv->adapter->pcard_info->v14_fw_api) {
361 t_u8 rxpd_rate_info_orig = prx_pd->rate_info;
362 prx_pd->rate_info = wlan_convert_v14_rx_rate_info(
363 priv, rxpd_rate_info_orig);
364 PRINTM(MINFO,
365 "UAP RX: v14_fw_api=%d rx_rate =%d rxpd_rate_info=0x%x->0x%x\n",
366 priv->adapter->pcard_info->v14_fw_api, prx_pd->rx_rate,
367 rxpd_rate_info_orig, prx_pd->rate_info);
368 }
369
370 if (priv->rx_pkt_info) {
371 ext_rate_info = (t_u8)(prx_pd->rx_info >> 16);
372 pmbuf->u.rx_info.data_rate =
373 wlan_index_to_data_rate(priv->adapter, prx_pd->rx_rate,
374 prx_pd->rate_info,
375 ext_rate_info);
376 pmbuf->u.rx_info.channel =
377 (prx_pd->rx_info & RXPD_CHAN_MASK) >> 5;
378 pmbuf->u.rx_info.antenna = prx_pd->antenna;
379 pmbuf->u.rx_info.rssi = prx_pd->snr - prx_pd->nf;
380 }
381
382 rx_pkt_type = prx_pd->rx_pkt_type;
383 prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
384
385 PRINTM(MINFO,
386 "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
387 pmbuf->data_len, prx_pd->rx_pkt_offset,
388 pmbuf->data_len - prx_pd->rx_pkt_offset);
389
390 if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) !=
391 (t_u16)pmbuf->data_len) {
392 PRINTM(MERROR,
393 "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
394 " rx_pkt_length=%d\n",
395 pmbuf->data_len, prx_pd->rx_pkt_offset,
396 prx_pd->rx_pkt_length);
397 pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID;
398 ret = MLAN_STATUS_FAILURE;
399 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
400 goto done;
401 }
402 pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
403
404 if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask &&
405 prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) {
406 /* Check if this is mgmt packet and needs to
407 * forwarded to app as an event
408 */
409 puap_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd +
410 prx_pd->rx_pkt_offset);
411 puap_pkt_hdr->frm_len = wlan_le16_to_cpu(puap_pkt_hdr->frm_len);
412 if ((puap_pkt_hdr->wlan_header.frm_ctl &
413 IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
414 wlan_process_802dot11_mgmt_pkt(
415 pmadapter->priv[pmbuf->bss_index],
416 (t_u8 *)&puap_pkt_hdr->wlan_header,
417 puap_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) -
418 sizeof(puap_pkt_hdr->frm_len),
419 (RxPD *)prx_pd);
420 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
421 goto done;
422 }
423 if (rx_pkt_type != PKT_TYPE_BAR) {
424 priv->rxpd_rate = prx_pd->rx_rate;
425 priv->rxpd_rate_info = prx_pd->rate_info;
426 priv->rxpd_rx_info = (t_u8)(prx_pd->rx_info >> 16);
427
428 if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
429 antenna = wlan_adjust_antenna(priv, (RxPD *)prx_pd);
430 adj_rx_rate = wlan_adjust_data_rate(
431 priv, priv->rxpd_rate, priv->rxpd_rate_info);
432 pmadapter->callbacks.moal_hist_data_add(
433 pmadapter->pmoal_handle, pmbuf->bss_index,
434 adj_rx_rate, prx_pd->snr, prx_pd->nf, antenna);
435 }
436 }
437
438 sta_ptr = wlan_get_station_entry(priv, prx_pkt->eth803_hdr.src_addr);
439 if (sta_ptr) {
440 sta_ptr->snr = prx_pd->snr;
441 sta_ptr->nf = prx_pd->nf;
442 pmadapter->callbacks.moal_get_system_time(
443 pmadapter->pmoal_handle, &last_rx_sec, &last_rx_usec);
444 sta_ptr->stats.last_rx_in_msec =
445 (t_u64)last_rx_sec * 1000 + (t_u64)last_rx_usec / 1000;
446 if (rx_pkt_type != PKT_TYPE_BAR) {
447 sta_ptr->stats.rx_packets++;
448 sta_ptr->stats.rx_bytes += prx_pd->rx_pkt_length;
449 }
450 }
451
452 #ifdef DRV_EMBEDDED_AUTHENTICATOR
453 /**process eapol packet for uap*/
454 if (IsAuthenticatorEnabled(priv->psapriv) &&
455 (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type,
456 sizeof(eapol_type)))) {
457 ret = AuthenticatorProcessEapolPacket(
458 priv->psapriv, ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
459 prx_pd->rx_pkt_length);
460 if (ret == MLAN_STATUS_SUCCESS) {
461 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
462 goto done;
463 }
464 }
465 #endif
466
467 pmbuf->priority |= prx_pd->priority;
468 memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr,
469 MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
470 if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) {
471 sta_ptr = wlan_get_station_entry(priv, ta);
472 if (sta_ptr) {
473 sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num;
474 sta_ptr->snr = prx_pd->snr;
475 sta_ptr->nf = prx_pd->nf;
476 }
477 }
478 /* check if UAP enable 11n */
479 if ((!priv->is_11n_enabled && !priv->is_11ax_enabled) ||
480 (!wlan_11n_get_rxreorder_tbl((mlan_private *)priv, prx_pd->priority,
481 ta) &&
482 (prx_pd->rx_pkt_type != PKT_TYPE_AMSDU))) {
483 if (priv->pkt_fwd)
484 wlan_process_uap_rx_packet(priv, pmbuf);
485 else
486 wlan_upload_uap_rx_packet(pmadapter, pmbuf);
487 goto done;
488 }
489 /* Reorder and send to OS */
490 ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority,
491 ta, (t_u8)prx_pd->rx_pkt_type,
492 (void *)pmbuf);
493 if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
494 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
495 }
496 done:
497 LEAVE();
498 return ret;
499 }
500
501 /**
502 * @brief This function processes received packet and forwards it
503 * to kernel/upper layer or send back to firmware
504 *
505 * @param priv A pointer to mlan_private
506 * @param pmbuf A pointer to mlan_buffer which includes the received packet
507 *
508 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
509 */
wlan_uap_recv_packet(mlan_private * priv,pmlan_buffer pmbuf)510 mlan_status wlan_uap_recv_packet(mlan_private *priv, pmlan_buffer pmbuf)
511 {
512 pmlan_adapter pmadapter = priv->adapter;
513 mlan_status ret = MLAN_STATUS_SUCCESS;
514 RxPacketHdr_t *prx_pkt;
515 pmlan_buffer newbuf = MNULL;
516
517 ENTER();
518
519 prx_pkt = (RxPacketHdr_t *)((t_u8 *)pmbuf->pbuf + pmbuf->data_offset);
520
521 DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset,
522 MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN));
523
524 PRINTM(MDATA, "AMSDU dest " MACSTR "\n",
525 MAC2STR(prx_pkt->eth803_hdr.dest_addr));
526
527 /* don't do packet forwarding in disconnected state */
528 if (priv->media_connected == MFALSE)
529 goto upload;
530
531 if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
532 if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
533 /* Multicast pkt */
534 newbuf =
535 wlan_alloc_mlan_buffer(pmadapter,
536 MLAN_TX_DATA_BUF_SIZE_2K,
537 0, MOAL_MALLOC_BUFFER);
538 if (newbuf) {
539 newbuf->bss_index = pmbuf->bss_index;
540 newbuf->buf_type = pmbuf->buf_type;
541 newbuf->priority = pmbuf->priority;
542 newbuf->in_ts_sec = pmbuf->in_ts_sec;
543 newbuf->in_ts_usec = pmbuf->in_ts_usec;
544 newbuf->data_offset =
545 (sizeof(TxPD) + priv->intf_hr_len +
546 DMA_ALIGNMENT);
547 util_scalar_increment(
548 pmadapter->pmoal_handle,
549 &pmadapter->pending_bridge_pkts,
550 pmadapter->callbacks.moal_spin_lock,
551 pmadapter->callbacks.moal_spin_unlock);
552
553 newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
554
555 /* copy the data */
556 memcpy_ext(pmadapter,
557 (t_u8 *)newbuf->pbuf +
558 newbuf->data_offset,
559 pmbuf->pbuf + pmbuf->data_offset,
560 pmbuf->data_len,
561 MLAN_TX_DATA_BUF_SIZE_2K);
562 newbuf->data_len = pmbuf->data_len;
563 wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
564 if (util_scalar_read(
565 pmadapter->pmoal_handle,
566 &pmadapter->pending_bridge_pkts,
567 pmadapter->callbacks.moal_spin_lock,
568 pmadapter->callbacks
569 .moal_spin_unlock) >
570 RX_HIGH_THRESHOLD)
571 wlan_drop_tx_pkts(priv);
572 wlan_recv_event(
573 priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
574 MNULL);
575 }
576 }
577 } else {
578 if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
579 (wlan_get_station_entry(priv,
580 prx_pkt->eth803_hdr.dest_addr))) {
581 /* Intra BSS packet */
582 newbuf =
583 wlan_alloc_mlan_buffer(pmadapter,
584 MLAN_TX_DATA_BUF_SIZE_2K,
585 0, MOAL_MALLOC_BUFFER);
586 if (newbuf) {
587 newbuf->bss_index = pmbuf->bss_index;
588 newbuf->buf_type = pmbuf->buf_type;
589 newbuf->priority = pmbuf->priority;
590 newbuf->in_ts_sec = pmbuf->in_ts_sec;
591 newbuf->in_ts_usec = pmbuf->in_ts_usec;
592 newbuf->data_offset =
593 (sizeof(TxPD) + priv->intf_hr_len +
594 DMA_ALIGNMENT);
595 util_scalar_increment(
596 pmadapter->pmoal_handle,
597 &pmadapter->pending_bridge_pkts,
598 pmadapter->callbacks.moal_spin_lock,
599 pmadapter->callbacks.moal_spin_unlock);
600 newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
601
602 /* copy the data */
603 memcpy_ext(pmadapter,
604 (t_u8 *)newbuf->pbuf +
605 newbuf->data_offset,
606 pmbuf->pbuf + pmbuf->data_offset,
607 pmbuf->data_len,
608 MLAN_TX_DATA_BUF_SIZE_2K);
609 newbuf->data_len = pmbuf->data_len;
610 wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
611 if (util_scalar_read(
612 pmadapter->pmoal_handle,
613 &pmadapter->pending_bridge_pkts,
614 pmadapter->callbacks.moal_spin_lock,
615 pmadapter->callbacks
616 .moal_spin_unlock) >
617 RX_HIGH_THRESHOLD)
618 wlan_drop_tx_pkts(priv);
619 wlan_recv_event(
620 priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
621 MNULL);
622 }
623 goto done;
624 } else if (MLAN_STATUS_FAILURE ==
625 wlan_check_unicast_packet(
626 priv, prx_pkt->eth803_hdr.dest_addr)) {
627 /* drop packet */
628 PRINTM(MDATA, "Drop AMSDU dest " MACSTR "\n",
629 MAC2STR(prx_pkt->eth803_hdr.dest_addr));
630 goto done;
631 }
632 }
633 upload:
634 /** send packet to moal */
635 ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
636 pmbuf);
637 done:
638 LEAVE();
639 return ret;
640 }
641
642 /**
643 * @brief This function processes received packet and forwards it
644 * to kernel/upper layer or send back to firmware
645 *
646 * @param priv A pointer to mlan_private
647 * @param pmbuf A pointer to mlan_buffer which includes the received packet
648 *
649 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
650 */
wlan_process_uap_rx_packet(mlan_private * priv,pmlan_buffer pmbuf)651 mlan_status wlan_process_uap_rx_packet(mlan_private *priv, pmlan_buffer pmbuf)
652 {
653 pmlan_adapter pmadapter = priv->adapter;
654 mlan_status ret = MLAN_STATUS_SUCCESS;
655 RxPD *prx_pd;
656 RxPacketHdr_t *prx_pkt;
657 pmlan_buffer newbuf = MNULL;
658
659 ENTER();
660
661 prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset);
662 prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset);
663
664 DBG_HEXDUMP(MDAT_D, "uAP RxPD", prx_pd,
665 MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN));
666 DBG_HEXDUMP(MDAT_D, "uAP Rx Payload",
667 ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset),
668 MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN));
669
670 PRINTM(MINFO,
671 "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n",
672 pmbuf->data_len, prx_pd->rx_pkt_offset,
673 pmbuf->data_len - prx_pd->rx_pkt_offset);
674 PRINTM(MDATA, "Rx dest " MACSTR "\n",
675 MAC2STR(prx_pkt->eth803_hdr.dest_addr));
676
677 if (pmadapter->enable_net_mon) {
678 pmbuf->flags |= MLAN_BUF_FLAG_NET_MONITOR;
679 goto upload;
680 }
681
682 /* don't do packet forwarding in disconnected state */
683 /* don't do packet forwarding when packet > 1514 */
684 if (priv->media_connected == MFALSE)
685 goto upload;
686
687 if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) {
688 if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) {
689 /* Multicast pkt */
690 newbuf =
691 wlan_alloc_mlan_buffer(pmadapter,
692 MLAN_TX_DATA_BUF_SIZE_2K,
693 0, MOAL_MALLOC_BUFFER);
694 if (newbuf) {
695 newbuf->bss_index = pmbuf->bss_index;
696 newbuf->buf_type = pmbuf->buf_type;
697 newbuf->priority = pmbuf->priority;
698 newbuf->in_ts_sec = pmbuf->in_ts_sec;
699 newbuf->in_ts_usec = pmbuf->in_ts_usec;
700 newbuf->data_offset =
701 (sizeof(TxPD) + priv->intf_hr_len +
702 DMA_ALIGNMENT);
703 util_scalar_increment(
704 pmadapter->pmoal_handle,
705 &pmadapter->pending_bridge_pkts,
706 pmadapter->callbacks.moal_spin_lock,
707 pmadapter->callbacks.moal_spin_unlock);
708 newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
709
710 /* copy the data, skip rxpd */
711 memcpy_ext(pmadapter,
712 (t_u8 *)newbuf->pbuf +
713 newbuf->data_offset,
714 pmbuf->pbuf + pmbuf->data_offset +
715 prx_pd->rx_pkt_offset,
716 pmbuf->data_len -
717 prx_pd->rx_pkt_offset,
718 MLAN_TX_DATA_BUF_SIZE_2K);
719 newbuf->data_len =
720 pmbuf->data_len - prx_pd->rx_pkt_offset;
721 wlan_wmm_add_buf_txqueue(pmadapter, newbuf);
722 if (util_scalar_read(
723 pmadapter->pmoal_handle,
724 &pmadapter->pending_bridge_pkts,
725 pmadapter->callbacks.moal_spin_lock,
726 pmadapter->callbacks
727 .moal_spin_unlock) >
728 RX_HIGH_THRESHOLD)
729 wlan_drop_tx_pkts(priv);
730 wlan_recv_event(
731 priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
732 MNULL);
733 }
734 }
735 } else {
736 if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) &&
737 (wlan_get_station_entry(priv,
738 prx_pkt->eth803_hdr.dest_addr))) {
739 /* Forwarding Intra-BSS packet */
740 #ifdef USB
741 if (IS_USB(pmadapter->card_type)) {
742 if (pmbuf->flags & MLAN_BUF_FLAG_RX_DEAGGR) {
743 newbuf = wlan_alloc_mlan_buffer(
744 pmadapter,
745 MLAN_TX_DATA_BUF_SIZE_2K, 0,
746 MOAL_MALLOC_BUFFER);
747 if (newbuf) {
748 newbuf->bss_index =
749 pmbuf->bss_index;
750 newbuf->buf_type =
751 pmbuf->buf_type;
752 newbuf->priority =
753 pmbuf->priority;
754 newbuf->in_ts_sec =
755 pmbuf->in_ts_sec;
756 newbuf->in_ts_usec =
757 pmbuf->in_ts_usec;
758 newbuf->data_offset =
759 (sizeof(TxPD) +
760 priv->intf_hr_len +
761 DMA_ALIGNMENT);
762 util_scalar_increment(
763 pmadapter->pmoal_handle,
764 &pmadapter->pending_bridge_pkts,
765 pmadapter->callbacks
766 .moal_spin_lock,
767 pmadapter->callbacks
768 .moal_spin_unlock);
769 newbuf->flags |=
770 MLAN_BUF_FLAG_BRIDGE_BUF;
771
772 /* copy the data, skip rxpd */
773 memcpy_ext(
774 pmadapter,
775 (t_u8 *)newbuf->pbuf +
776 newbuf->data_offset,
777 pmbuf->pbuf +
778 pmbuf->data_offset +
779 prx_pd->rx_pkt_offset,
780 pmbuf->data_len -
781 prx_pd->rx_pkt_offset,
782 pmbuf->data_len -
783 prx_pd->rx_pkt_offset);
784 newbuf->data_len =
785 pmbuf->data_len -
786 prx_pd->rx_pkt_offset;
787 wlan_wmm_add_buf_txqueue(
788 pmadapter, newbuf);
789 if (util_scalar_read(
790 pmadapter->pmoal_handle,
791 &pmadapter->pending_bridge_pkts,
792 pmadapter->callbacks
793 .moal_spin_lock,
794 pmadapter->callbacks
795 .moal_spin_unlock) >
796 RX_HIGH_THRESHOLD)
797 wlan_drop_tx_pkts(priv);
798 wlan_recv_event(
799 priv,
800 MLAN_EVENT_ID_DRV_DEFER_HANDLING,
801 MNULL);
802 }
803 pmadapter->callbacks.moal_recv_complete(
804 pmadapter->pmoal_handle, pmbuf,
805 pmadapter->rx_data_ep, ret);
806 goto done;
807 }
808 }
809 #endif
810 pmbuf->data_len -= prx_pd->rx_pkt_offset;
811 pmbuf->data_offset += prx_pd->rx_pkt_offset;
812 pmbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF;
813 util_scalar_increment(
814 pmadapter->pmoal_handle,
815 &pmadapter->pending_bridge_pkts,
816 pmadapter->callbacks.moal_spin_lock,
817 pmadapter->callbacks.moal_spin_unlock);
818 wlan_wmm_add_buf_txqueue(pmadapter, pmbuf);
819 if (util_scalar_read(
820 pmadapter->pmoal_handle,
821 &pmadapter->pending_bridge_pkts,
822 pmadapter->callbacks.moal_spin_lock,
823 pmadapter->callbacks.moal_spin_unlock) >
824 RX_HIGH_THRESHOLD)
825 wlan_drop_tx_pkts(priv);
826 wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING,
827 MNULL);
828 goto done;
829 } else if (MLAN_STATUS_FAILURE ==
830 wlan_check_unicast_packet(
831 priv, prx_pkt->eth803_hdr.dest_addr)) {
832 PRINTM(MDATA, "Drop Pkts: Rx dest " MACSTR "\n",
833 MAC2STR(prx_pkt->eth803_hdr.dest_addr));
834 pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
835 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
836 goto done;
837 }
838 }
839
840 upload:
841 /* Chop off RxPD */
842 pmbuf->data_len -= prx_pd->rx_pkt_offset;
843 pmbuf->data_offset += prx_pd->rx_pkt_offset;
844 pmbuf->pparent = MNULL;
845
846 pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
847 &pmbuf->out_ts_sec,
848 &pmbuf->out_ts_usec);
849 PRINTM_NETINTF(MDATA, priv);
850 PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n",
851 pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num,
852 prx_pd->priority);
853 if (pmbuf->flags & MLAN_BUF_FLAG_NET_MONITOR) {
854 // Use some rxpd space to save rxpd info for radiotap header
855 // We should insure radiotap_info is not bigger than RxPD
856 wlan_rxpdinfo_to_radiotapinfo(
857 priv, (RxPD *)prx_pd,
858 (radiotap_info *)(pmbuf->pbuf + pmbuf->data_offset -
859 sizeof(radiotap_info)));
860 }
861
862 ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle,
863 pmbuf);
864 if (ret == MLAN_STATUS_FAILURE) {
865 PRINTM(MERROR,
866 "uAP Rx Error: moal_recv_packet returned error\n");
867 pmbuf->status_code = MLAN_ERROR_PKT_INVALID;
868 }
869
870 if (ret != MLAN_STATUS_PENDING)
871 pmadapter->ops.data_complete(pmadapter, pmbuf, ret);
872 #ifdef USB
873 else if (IS_USB(pmadapter->card_type))
874 pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle,
875 MNULL,
876 pmadapter->rx_data_ep,
877 ret);
878 #endif
879 done:
880 LEAVE();
881 return ret;
882 }
883