/** * @brief This function processes the received buffer * * @param pmadapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = MNULL; RxPD *prx_pd; #ifdef DEBUG_LEVEL1 t_u32 sec = 0, usec = 0; #endif ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Get the BSS number from RxPD, get corresponding priv */ priv = wlan_get_priv_by_id(pmadapter, prx_pd->bss_num & BSS_NUM_MASK, prx_pd->bss_type); if (!priv) priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); pmbuf->bss_index = priv->bss_index; PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data <= FW\n", sec, usec); ret = priv->ops.process_rx_packet(pmadapter, pmbuf); LEAVE(); return ret; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param pmadapter A pointer to mlan_adapter * @param pmbuf A pointer to mlan_buffer which includes the received packet * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_upload_uap_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; UapRxPD *prx_pd; ENTER(); prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset); /* Chop off RxPD */ pmbuf->data_len -= prx_pd->rx_pkt_offset; pmbuf->data_offset += prx_pd->rx_pkt_offset; pmbuf->pparent = MNULL; DBG_HEXDUMP(MDAT_D, "uAP RxPD", (t_u8 *)prx_pd, MIN(sizeof(UapRxPD), MAX_DATA_DUMP_LEN)); DBG_HEXDUMP(MDAT_D, "uAP Rx Payload", ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset), MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN)); pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n", pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num, prx_pd->priority); ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); if (ret == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "uAP Rx Error: moal_recv_packet returned error\n"); pmbuf->status_code = MLAN_ERROR_PKT_INVALID; } if (ret != MLAN_STATUS_PENDING) wlan_free_mlan_buffer(pmadapter, pmbuf); LEAVE(); return ret; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer or send back to firmware * * @param priv A pointer to mlan_private * @param pmbuf A pointer to mlan_buffer which includes the received packet * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_process_uap_rx_packet(IN mlan_private *priv, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = priv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; UapRxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_buffer newbuf = MNULL; ENTER(); prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset); prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); DBG_HEXDUMP(MDAT_D, "uAP RxPD", prx_pd, MIN(sizeof(UapRxPD), MAX_DATA_DUMP_LEN)); DBG_HEXDUMP(MDAT_D, "uAP Rx Payload", ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset), MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN)); PRINTM(MINFO, "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); PRINTM(MDATA, "Rx dest " MACSTR "\n", MAC2STR(prx_pkt->eth803_hdr.dest_addr)); /* don't do packet forwarding in disconnected state */ /* don't do packet forwarding when packet > 1514 */ if ((priv->media_connected == MFALSE) || ((pmbuf->data_len - prx_pd->rx_pkt_offset) > MV_ETH_FRAME_LEN)) goto upload; if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) { if (!(priv->pkt_fwd & PKT_FWD_INTRA_BCAST)) { /* Multicast pkt */ newbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_TX_DATA_BUF_SIZE_2K, 0, MOAL_MALLOC_BUFFER); if (newbuf) { newbuf->bss_index = pmbuf->bss_index; newbuf->buf_type = pmbuf->buf_type; newbuf->priority = pmbuf->priority; newbuf->in_ts_sec = pmbuf->in_ts_sec; newbuf->in_ts_usec = pmbuf->in_ts_usec; newbuf->data_offset = (sizeof(UapTxPD) + INTF_HEADER_LEN + DMA_ALIGNMENT); util_scalar_increment(pmadapter->pmoal_handle, &pmadapter-> pending_bridge_pkts, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF; /* copy the data, skip rxpd */ memcpy(pmadapter, (t_u8 *)newbuf->pbuf + newbuf->data_offset, pmbuf->pbuf + pmbuf->data_offset + prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); newbuf->data_len = pmbuf->data_len - prx_pd->rx_pkt_offset; wlan_wmm_add_buf_txqueue(pmadapter, newbuf); if (util_scalar_read(pmadapter->pmoal_handle, &pmadapter-> pending_bridge_pkts, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock) > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL); } } } else { if ((!(priv->pkt_fwd & PKT_FWD_INTRA_UCAST)) && (wlan_get_station_entry (priv, prx_pkt->eth803_hdr.dest_addr))) { /* Forwarding Intra-BSS packet */ pmbuf->data_len -= prx_pd->rx_pkt_offset; pmbuf->data_offset += prx_pd->rx_pkt_offset; pmbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF; util_scalar_increment(pmadapter->pmoal_handle, &pmadapter->pending_bridge_pkts, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock); wlan_wmm_add_buf_txqueue(pmadapter, pmbuf); if (util_scalar_read(pmadapter->pmoal_handle, &pmadapter->pending_bridge_pkts, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock) > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL); goto done; } else if (MLAN_STATUS_FAILURE == wlan_check_unicast_packet(priv, prx_pkt->eth803_hdr. dest_addr)) { PRINTM(MDATA, "Drop Pkts: Rx dest " MACSTR "\n", MAC2STR(prx_pkt->eth803_hdr.dest_addr)); pmbuf->status_code = MLAN_ERROR_PKT_INVALID; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } } upload: /* Chop off RxPD */ pmbuf->data_len -= prx_pd->rx_pkt_offset; pmbuf->data_offset += prx_pd->rx_pkt_offset; pmbuf->pparent = MNULL; pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n", pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num, prx_pd->priority); ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); if (ret == MLAN_STATUS_FAILURE) { PRINTM(MERROR, "uAP Rx Error: moal_recv_packet returned error\n"); pmbuf->status_code = MLAN_ERROR_PKT_INVALID; } if (ret != MLAN_STATUS_PENDING) wlan_free_mlan_buffer(pmadapter, pmbuf); done: LEAVE(); return ret; }
/** * @brief This function checks the conditions and sends packet to device * * @param priv A pointer to mlan_private structure * @param pmbuf A pointer to the mlan_buffer for process * @param tx_param A pointer to mlan_tx_param structure * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise failure */ mlan_status wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, mlan_tx_param * tx_param) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_adapter pmadapter = priv->adapter; t_u8 *head_ptr = MNULL; #ifdef DEBUG_LEVEL1 t_u32 sec = 0, usec = 0; #endif #ifdef STA_SUPPORT TxPD *plocal_tx_pd = MNULL; #endif ENTER(); head_ptr = (t_u8 *) priv->ops.process_txpd(priv, pmbuf); if (!head_ptr) { pmbuf->status_code = MLAN_ERROR_PKT_INVALID; ret = MLAN_STATUS_FAILURE; goto done; } #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) plocal_tx_pd = (TxPD *) (head_ptr + INTF_HEADER_LEN); #endif ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, tx_param); done: switch (ret) { case MLAN_STATUS_RESOURCE: #ifdef STA_SUPPORT if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && pmadapter->pps_uapsd_mode && (pmadapter->tx_lock_flag == MTRUE)) { pmadapter->tx_lock_flag = MFALSE; plocal_tx_pd->flags = 0; } #endif PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n"); break; case MLAN_STATUS_FAILURE: pmadapter->data_sent = MFALSE; PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret); pmadapter->dbg.num_tx_host_to_card_failure++; pmbuf->status_code = MLAN_ERROR_DATA_TX_FAIL; wlan_write_data_complete(pmadapter, pmbuf, ret); break; case MLAN_STATUS_PENDING: DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + INTF_HEADER_LEN, MIN(pmbuf->data_len + sizeof(TxPD), MAX_DATA_DUMP_LEN)); break; case MLAN_STATUS_SUCCESS: DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + INTF_HEADER_LEN, MIN(pmbuf->data_len + sizeof(TxPD), MAX_DATA_DUMP_LEN)); wlan_write_data_complete(pmadapter, pmbuf, ret); break; default: break; } if ((ret == MLAN_STATUS_SUCCESS) || (ret == MLAN_STATUS_PENDING)) { PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec); } LEAVE(); return ret; }
/** * @brief Aggregate multiple packets into one single AMSDU packet * * @param priv A pointer to mlan_private structure * @param pra_list Pointer to the RA List table containing the pointers * to packets. * @param headroom Any interface specific headroom that may be need. TxPD * will be formed leaving this headroom. * @param ptrindex Pointer index * * @return Final packet size or MLAN_STATUS_FAILURE */ int wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, int headroom, int ptrindex) { int pkt_size = 0; pmlan_adapter pmadapter = priv->adapter; mlan_buffer *pmbuf_aggr, *pmbuf_src; t_u8 *data; int pad = 0; mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef DEBUG_LEVEL1 t_u32 sec = 0, usec = 0; #endif mlan_tx_param tx_param; #ifdef STA_SUPPORT TxPD *ptx_pd = MNULL; #endif t_u32 max_amsdu_size = MIN(pra_list->max_amsdu, pmadapter->tx_buf_size); ENTER(); PRINTM(MDAT_D, "Handling Aggr packet\n"); pmbuf_src = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); if (pmbuf_src) { pmbuf_aggr = wlan_alloc_mlan_buffer(pmadapter, pmadapter->tx_buf_size, 0, MOAL_MALLOC_BUFFER); if (!pmbuf_aggr) { PRINTM(MERROR, "Error allocating mlan_buffer\n"); pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); LEAVE(); return MLAN_STATUS_FAILURE; } data = pmbuf_aggr->pbuf + headroom; pmbuf_aggr->bss_index = pmbuf_src->bss_index; pmbuf_aggr->buf_type = pmbuf_src->buf_type; pmbuf_aggr->priority = pmbuf_src->priority; pmbuf_aggr->pbuf = data; pmbuf_aggr->data_offset = 0; pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec; pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec; if (pmbuf_src->flags & MLAN_BUF_FLAG_TDLS) pmbuf_aggr->flags |= MLAN_BUF_FLAG_TDLS; /* Form AMSDU */ wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr); pkt_size = sizeof(TxPD); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) ptx_pd = (TxPD *) pmbuf_aggr->pbuf; #endif } else { pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); goto exit; } while (pmbuf_src && ((pkt_size + (pmbuf_src->data_len + LLC_SNAP_LEN) + headroom) <= max_amsdu_size)) { pmbuf_src = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); pra_list->total_pkts--; /* decrement for every PDU taken from the list */ priv->wmm.pkts_queued[ptrindex]--; util_scalar_decrement(pmadapter->pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL); pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); if (pmbuf_src->flags & MLAN_BUF_FLAG_TCP_ACK) pmadapter->callbacks.moal_tcp_ack_tx_ind(pmadapter-> pmoal_handle, pmbuf_src); pkt_size += wlan_11n_form_amsdu_pkt(pmadapter, (data + pkt_size), pmbuf_src->pbuf + pmbuf_src->data_offset, pmbuf_src->data_len, &pad); DBG_HEXDUMP(MDAT_D, "pmbuf_src", pmbuf_src, sizeof(mlan_buffer)); wlan_write_data_complete(pmadapter, pmbuf_src, MLAN_STATUS_SUCCESS); pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); LEAVE(); return MLAN_STATUS_FAILURE; } pmbuf_src = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, &pra_list->buf_head, MNULL, MNULL); } pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); /* Last AMSDU packet does not need padding */ pkt_size -= pad; pmbuf_aggr->data_len = pkt_size; wlan_11n_update_pktlen_amsdu_txpd(priv, pmbuf_aggr); pmbuf_aggr->data_len += headroom; pmbuf_aggr->pbuf = data - headroom; tx_param.next_pkt_len = ((pmbuf_src) ? pmbuf_src->data_len + sizeof(TxPD) : 0); ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf_aggr, &tx_param); switch (ret) { case MLAN_STATUS_RESOURCE: pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (!wlan_is_ralist_valid(priv, pra_list, ptrindex)) { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, priv->wmm. ra_list_spinlock); pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID; wlan_write_data_complete(pmadapter, pmbuf_aggr, MLAN_STATUS_FAILURE); LEAVE(); return MLAN_STATUS_FAILURE; } #ifdef STA_SUPPORT /* reset tx_lock_flag */ if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && pmadapter->pps_uapsd_mode && (pmadapter->tx_lock_flag == MTRUE)) { pmadapter->tx_lock_flag = MFALSE; ptx_pd->flags = 0; } #endif util_enqueue_list_head(pmadapter->pmoal_handle, &pra_list->buf_head, (pmlan_linked_list) pmbuf_aggr, MNULL, MNULL); pra_list->total_pkts++; /* add back only one: aggregated packet is requeued as one */ priv->wmm.pkts_queued[ptrindex]++; util_scalar_increment(pmadapter->pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL); pmbuf_aggr->flags |= MLAN_BUF_FLAG_REQUEUED_PKT; pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); PRINTM(MINFO, "MLAN_STATUS_RESOURCE is returned\n"); pmbuf_aggr->status_code = MLAN_ERROR_PKT_INVALID; break; case MLAN_STATUS_FAILURE: pmadapter->data_sent = MFALSE; PRINTM(MERROR, "Error: host_to_card failed: 0x%X\n", ret); pmbuf_aggr->status_code = MLAN_ERROR_DATA_TX_FAIL; pmadapter->dbg.num_tx_host_to_card_failure++; wlan_write_data_complete(pmadapter, pmbuf_aggr, ret); goto exit; case MLAN_STATUS_PENDING: break; case MLAN_STATUS_SUCCESS: wlan_write_data_complete(pmadapter, pmbuf_aggr, ret); break; default: break; } if (ret != MLAN_STATUS_RESOURCE) { pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); if (wlan_is_ralist_valid(priv, pra_list, ptrindex)) { priv->wmm.packets_out[ptrindex]++; priv->wmm.tid_tbl_ptr[ptrindex].ra_list_curr = pra_list; } pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur = pmadapter->bssprio_tbl[priv->bss_priority].bssprio_cur-> pnext; pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm. ra_list_spinlock); } PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec); exit: LEAVE(); return pkt_size + headroom; }
/** * @brief This function tells firmware to send a NULL data packet. * * @param priv A pointer to mlan_private structure * @param flags Transmit Pkt Flags * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise failure */ mlan_status wlan_send_null_packet(pmlan_private priv, t_u8 flags) { pmlan_adapter pmadapter = priv->adapter; TxPD *ptx_pd; /* sizeof(TxPD) + Interface specific header */ #define NULL_PACKET_HDR 256 t_u32 data_len = NULL_PACKET_HDR; pmlan_buffer pmbuf = MNULL; t_u8 *ptr; mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef DEBUG_LEVEL1 t_u32 sec, usec; #endif ENTER(); if (pmadapter->surprise_removed == MTRUE) { ret = MLAN_STATUS_FAILURE; goto done; } if (priv->media_connected == MFALSE) { ret = MLAN_STATUS_FAILURE; goto done; } if (pmadapter->data_sent == MTRUE) { ret = MLAN_STATUS_FAILURE; goto done; } pmbuf = wlan_alloc_mlan_buffer(pmadapter, data_len, 0, MOAL_MALLOC_BUFFER); if (!pmbuf) { ret = MLAN_STATUS_FAILURE; goto done; } memset(pmadapter, pmbuf->pbuf, 0, data_len); pmbuf->bss_index = priv->bss_index; pmbuf->buf_type = MLAN_BUF_TYPE_DATA; ptr = pmbuf->pbuf + pmbuf->data_offset; pmbuf->data_len = sizeof(TxPD) + INTF_HEADER_LEN; ptx_pd = (TxPD *) (ptr + INTF_HEADER_LEN); ptx_pd->tx_control = priv->pkt_tx_ctrl; ptx_pd->flags = flags; ptx_pd->priority = WMM_HIGHEST_PRIORITY; ptx_pd->tx_pkt_offset = sizeof(TxPD); /* Set the BSS number to TxPD */ ptx_pd->bss_num = GET_BSS_NUM(priv); ptx_pd->bss_type = priv->bss_type; endian_convert_TxPD(ptx_pd); ret = wlan_sdio_host_to_card(pmadapter, MLAN_TYPE_DATA, pmbuf, MNULL); switch (ret) { case MLAN_STATUS_RESOURCE: pmadapter->data_sent = MTRUE; /* Fall through FAILURE handling */ case MLAN_STATUS_FAILURE: wlan_free_mlan_buffer(pmadapter, pmbuf); PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n"); pmadapter->dbg.num_tx_host_to_card_failure++; goto done; case MLAN_STATUS_SUCCESS: wlan_free_mlan_buffer(pmadapter, pmbuf); PRINTM(MINFO, "STA Tx: Successfully send the NULL packet\n"); pmadapter->tx_lock_flag = MTRUE; break; case MLAN_STATUS_PENDING: break; default: break; } PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Null data => FW\n", sec, usec); DBG_HEXDUMP(MDAT_D, "Null data", ptr, sizeof(TxPD) + INTF_HEADER_LEN); done: LEAVE(); return ret; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param pmadapter A pointer to mlan_adapter * @param pmbuf A pointer to mlan_buffer which includes the received packet * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; RxPacketHdr_t *prx_pkt; RxPD *prx_pd; int hdr_chop; EthII_Hdr_t *peth_hdr; t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; t_u8 snap_oui_802_h[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; t_u8 appletalk_aarp_type[2] = { 0x80, 0xf3 }; t_u8 ipx_snap_type[2] = { 0x81, 0x37 }; ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); /** Small debug type */ #define DBG_TYPE_SMALL 2 /** Size of debugging structure */ #define SIZE_OF_DBG_STRUCT 4 if (prx_pd->rx_pkt_type == PKT_TYPE_DEBUG) { t_u8 dbgType; dbgType = *(t_u8 *) & prx_pkt->eth803_hdr; if (dbgType == DBG_TYPE_SMALL) { PRINTM(MFW_D, "\n"); DBG_HEXDUMP(MFW_D, "FWDBG", (char *)((t_u8 *) & prx_pkt->eth803_hdr + SIZE_OF_DBG_STRUCT), prx_pd->rx_pkt_length); PRINTM(MFW_D, "FWDBG::\n"); } goto done; } PRINTM(MINFO, "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); HEXDUMP("RX Data: Dest", prx_pkt->eth803_hdr.dest_addr, sizeof(prx_pkt->eth803_hdr.dest_addr)); HEXDUMP("RX Data: Src", prx_pkt->eth803_hdr.src_addr, sizeof(prx_pkt->eth803_hdr.src_addr)); if ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, snap_oui_802_h, sizeof(snap_oui_802_h)) == 0) || ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) && memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, appletalk_aarp_type, sizeof(appletalk_aarp_type)) && memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, ipx_snap_type, sizeof(ipx_snap_type)))) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type (ethertype). * The firmware only passes up SNAP frames converting * all RX Data from 802.11 to 802.2/LLC/SNAP frames. * To create the Ethernet II, just move the src, dst address right * before the snap_type. */ peth_hdr = (EthII_Hdr_t *) ((t_u8 *) & prx_pkt->eth803_hdr + sizeof(prx_pkt->eth803_hdr) + sizeof(prx_pkt->rfc1042_hdr) - sizeof(prx_pkt->eth803_hdr.dest_addr) - sizeof(prx_pkt->eth803_hdr.src_addr) - sizeof(prx_pkt->rfc1042_hdr.snap_type)); memcpy(pmadapter, peth_hdr->src_addr, prx_pkt->eth803_hdr.src_addr, sizeof(peth_hdr->src_addr)); memcpy(pmadapter, peth_hdr->dest_addr, prx_pkt->eth803_hdr.dest_addr, sizeof(peth_hdr->dest_addr)); /* Chop off the RxPD + the excess memory from the 802.2/llc/snap header that was removed. */ hdr_chop = (t_u32) ((t_ptr) peth_hdr - (t_ptr) prx_pd); } else { HEXDUMP("RX Data: LLC/SNAP", (t_u8 *) & prx_pkt->rfc1042_hdr, sizeof(prx_pkt->rfc1042_hdr)); /* Chop off the RxPD */ hdr_chop = (t_u32) ((t_ptr) & prx_pkt->eth803_hdr - (t_ptr) prx_pd); } /* Chop off the leading header bytes so the it points to the start of either the reconstructed EthII frame or the 802.2/llc/snap frame */ pmbuf->data_len -= hdr_chop; pmbuf->data_offset += hdr_chop; pmbuf->pparent = MNULL; DBG_HEXDUMP(MDAT_D, "RxPD", (t_u8 *) prx_pd, MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN)); DBG_HEXDUMP(MDAT_D, "Rx Payload", ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset), MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN)); priv->rxpd_rate = prx_pd->rx_rate; priv->rxpd_htinfo = prx_pd->ht_info; pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n", pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num, prx_pd->priority); ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); if (ret == MLAN_STATUS_FAILURE) { pmbuf->status_code = MLAN_ERROR_PKT_INVALID; PRINTM(MERROR, "STA Rx Error: moal_recv_packet returned error\n"); } done: if (ret != MLAN_STATUS_PENDING) { wlan_free_mlan_buffer(pmadapter, pmbuf); } LEAVE(); return ret; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param pmadapter A pointer to mlan_adapter * @param pmbuf A pointer to mlan_buffer which includes the received packet * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; RxPacketHdr_t *prx_pkt; RxPD *prx_pd; int hdr_chop; EthII_Hdr_t *peth_hdr; t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; t_u8 snap_oui_802_h[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; t_u8 appletalk_aarp_type[2] = { 0x80, 0xf3 }; t_u8 ipx_snap_type[2] = { 0x81, 0x37 }; t_u8 tdls_action_type[2] = { 0x89, 0x0d }; #ifdef DRV_EMBEDDED_SUPPLICANT t_u8 eapol_type[2] = { 0x88, 0x8e }; #endif t_u8 adj_rx_rate = 0; ENTER(); prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset); prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); /** Small debug type */ #define DBG_TYPE_SMALL 2 /** Size of debugging structure */ #define SIZE_OF_DBG_STRUCT 4 if (prx_pd->rx_pkt_type == PKT_TYPE_DEBUG) { t_u8 dbg_type; dbg_type = *(t_u8 *)&prx_pkt->eth803_hdr; if (dbg_type == DBG_TYPE_SMALL) { PRINTM(MFW_D, "\n"); DBG_HEXDUMP(MFW_D, "FWDBG", (char *)((t_u8 *)&prx_pkt->eth803_hdr + SIZE_OF_DBG_STRUCT), prx_pd->rx_pkt_length); PRINTM(MFW_D, "FWDBG::\n"); } goto done; } PRINTM(MINFO, "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); HEXDUMP("RX Data: Dest", prx_pkt->eth803_hdr.dest_addr, sizeof(prx_pkt->eth803_hdr.dest_addr)); HEXDUMP("RX Data: Src", prx_pkt->eth803_hdr.src_addr, sizeof(prx_pkt->eth803_hdr.src_addr)); if ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, snap_oui_802_h, sizeof(snap_oui_802_h)) == 0) || ((memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) && memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, appletalk_aarp_type, sizeof(appletalk_aarp_type)) && memcmp(pmadapter, &prx_pkt->rfc1042_hdr.snap_type, ipx_snap_type, sizeof(ipx_snap_type)))) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type (ethertype). * The firmware only passes up SNAP frames converting * all RX Data from 802.11 to 802.2/LLC/SNAP frames. * To create the Ethernet II, just move the src, dst address * right before the snap_type. */ peth_hdr = (EthII_Hdr_t *) ((t_u8 *)&prx_pkt->eth803_hdr + sizeof(prx_pkt->eth803_hdr) + sizeof(prx_pkt->rfc1042_hdr) - sizeof(prx_pkt->eth803_hdr.dest_addr) - sizeof(prx_pkt->eth803_hdr.src_addr) - sizeof(prx_pkt->rfc1042_hdr.snap_type)); memcpy(pmadapter, peth_hdr->src_addr, prx_pkt->eth803_hdr.src_addr, sizeof(peth_hdr->src_addr)); memcpy(pmadapter, peth_hdr->dest_addr, prx_pkt->eth803_hdr.dest_addr, sizeof(peth_hdr->dest_addr)); /* Chop off the RxPD + the excess memory from the 802.2/llc/snap header that was removed. */ hdr_chop = (t_u32)((t_ptr)peth_hdr - (t_ptr)prx_pd); } else { HEXDUMP("RX Data: LLC/SNAP", (t_u8 *)&prx_pkt->rfc1042_hdr, sizeof(prx_pkt->rfc1042_hdr)); if ((priv->hotspot_cfg & HOTSPOT_ENABLED) && discard_gratuitous_ARP_msg(prx_pkt, pmadapter)) { ret = MLAN_STATUS_SUCCESS; PRINTM(MDATA, "Bypass sending Gratuitous ARP frame to Kernel.\n"); goto done; } if (!memcmp(pmadapter, &prx_pkt->eth803_hdr.h803_len, tdls_action_type, sizeof(tdls_action_type))) { wlan_process_tdls_action_frame(priv, ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset), prx_pd->rx_pkt_length); } /* Chop off the RxPD */ hdr_chop = (t_u32)((t_ptr)&prx_pkt->eth803_hdr - (t_ptr)prx_pd); } /* Chop off the leading header bytes so the it points to the start of either the reconstructed EthII frame or the 802.2/llc/snap frame */ pmbuf->data_len -= hdr_chop; pmbuf->data_offset += hdr_chop; pmbuf->pparent = MNULL; DBG_HEXDUMP(MDAT_D, "RxPD", (t_u8 *)prx_pd, MIN(sizeof(RxPD), MAX_DATA_DUMP_LEN)); DBG_HEXDUMP(MDAT_D, "Rx Payload", ((t_u8 *)prx_pd + prx_pd->rx_pkt_offset), MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN)); priv->rxpd_rate = prx_pd->rx_rate; priv->rxpd_htinfo = prx_pd->ht_info; if (priv->bss_type == MLAN_BSS_TYPE_STA) { adj_rx_rate = wlan_adjust_data_rate(priv, priv->rxpd_rate, priv->rxpd_htinfo); pmadapter->callbacks.moal_hist_data_add(pmadapter->pmoal_handle, pmbuf->bss_index, adj_rx_rate, prx_pd->snr, prx_pd->nf, prx_pd->antenna); } pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n", pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num, prx_pd->priority); #ifdef DRV_EMBEDDED_SUPPLICANT if (priv->adapter->psdio_device->driver_supplicant_auth && supplicantIsEnabled(priv->psapriv) && (!memcmp (pmadapter, &prx_pkt->eth803_hdr.h803_len, eapol_type, sizeof(eapol_type)))) { // BML_SET_OFFSET(bufDesc, offset); if (ProcessEAPoLPkt(priv->psapriv, pmbuf)) { wlan_free_mlan_buffer(pmadapter, pmbuf); ret = MLAN_STATUS_SUCCESS; PRINTM(MMSG, "host supplicant eapol pkt process done.\n"); LEAVE(); return ret; } } #endif ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); if (ret == MLAN_STATUS_FAILURE) { pmbuf->status_code = MLAN_ERROR_PKT_INVALID; PRINTM(MERROR, "STA Rx Error: moal_recv_packet returned error\n"); } done: if (ret != MLAN_STATUS_PENDING) wlan_free_mlan_buffer(pmadapter, pmbuf); LEAVE(); return ret; }