/** * @brief Packet send completion handling * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to mlan_buffer structure * @param status Callback status * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_write_data_complete(IN pmlan_adapter pmadapter, IN pmlan_buffer pmbuf, IN mlan_status status) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb; ENTER(); MASSERT(pmadapter && pmbuf); pcb = &pmadapter->callbacks; if (pmbuf->flags & MLAN_BUF_FLAG_TCP_ACK) { pmbuf->flags &= ~MLAN_BUF_FLAG_TCP_ACK; pcb->moal_tcp_ack_tx_ind(pmadapter->pmoal_handle, pmbuf); } if ((pmbuf->buf_type == MLAN_BUF_TYPE_DATA) || (pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA)) { PRINTM(MINFO, "wlan_write_data_complete: DATA %p\n", pmbuf); if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF) { /* pmbuf was allocated by MOAL */ pcb->moal_send_packet_complete(pmadapter->pmoal_handle, pmbuf, status); } else { /* pmbuf was allocated by MLAN */ wlan_free_mlan_buffer(pmadapter, pmbuf); } } LEAVE(); return ret; }
/** * @brief Shutdown firmware * * @param pmlan_adapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS * The firmware shutdown call succeeded. * MLAN_STATUS_PENDING * The firmware shutdown call is pending. * MLAN_STATUS_FAILURE * The firmware shutdown call failed. */ mlan_status mlan_shutdown_fw(IN t_void * pmlan_adapter) { mlan_status ret = MLAN_STATUS_PENDING; mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; pmlan_buffer pmbuf; pmlan_callbacks pcb; t_s32 i = 0; ENTER(); MASSERT(pmlan_adapter); /* MLAN already shutdown */ if (pmadapter->hw_status == WlanHardwareStatusNotReady) { LEAVE(); return MLAN_STATUS_SUCCESS; } pmadapter->hw_status = WlanHardwareStatusClosing; /* Wait for mlan_process to complete */ if (pmadapter->mlan_processing) { PRINTM(MWARN, "MLAN main processing is still running\n"); LEAVE(); return ret; } /* Shut down MLAN */ PRINTM(MINFO, "Shutdown MLAN...\n"); /* Cancel all pending commands and complete ioctls */ wlan_cancel_all_pending_cmd(pmadapter); /* Clean up priv structures */ for (i = 0; i < pmadapter->priv_num; i++) { if (pmadapter->priv[i]) { wlan_free_priv(pmadapter->priv[i]); } } pcb = &pmadapter->callbacks; while ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, &pmadapter->rx_data_queue, pcb->moal_spin_lock, pcb->moal_spin_unlock))) { wlan_free_mlan_buffer(pmadapter, pmbuf); } util_scalar_write(pmadapter->pmoal_handle, &pmadapter->rx_pkts_queued, 0, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); /* Notify completion */ ret = wlan_shutdown_fw_complete(pmadapter); LEAVE(); return ret; }
/** * @brief This function frees the structure of adapter * * @param pmadapter A pointer to mlan_adapter structure * * @return N/A */ t_void wlan_free_adapter(pmlan_adapter pmadapter) { mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; ENTER(); if (!pmadapter) { PRINTM(MERROR, "The adapter is NULL\n"); LEAVE(); return; } wlan_cancel_all_pending_cmd(pmadapter); /* Free command buffer */ PRINTM(MINFO, "Free Command buffer\n"); wlan_free_cmd_buffer(pmadapter); if (pmadapter->cmd_timer_is_set) { /* Cancel command timeout timer */ pcb->moal_stop_timer(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_timer); pmadapter->cmd_timer_is_set = MFALSE; } #ifdef STA_SUPPORT PRINTM(MINFO, "Free ScanTable\n"); if (pmadapter->pscan_table) { pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter->pscan_table); pmadapter->pscan_table = MNULL; } if (pmadapter->bcn_buf) { pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter->bcn_buf); pmadapter->bcn_buf = MNULL; } #endif wlan_11h_cleanup(pmadapter); if (pmadapter->mp_regs_buf) { pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter->mp_regs_buf); pmadapter->mp_regs_buf = MNULL; pmadapter->mp_regs = MNULL; } #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) wlan_free_sdio_mpa_buffers(pmadapter); #endif wlan_free_mlan_buffer(pmadapter, pmadapter->psleep_cfm); pmadapter->psleep_cfm = MNULL; LEAVE(); return; }
/** * @brief Packet receive completion callback handler * * @param pmlan_adapter A pointer to mlan_adapter structure * @param pmbuf A pointer to mlan_buffer structure * @param status Callback status * * @return MLAN_STATUS_SUCCESS */ mlan_status mlan_recv_packet_complete(IN t_void * pmlan_adapter, IN pmlan_buffer pmbuf, IN mlan_status status) { mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter; ENTER(); wlan_free_mlan_buffer(pmadapter, pmbuf); LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief Packet receive completion callback handler * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to mlan_buffer structure * @param status Callback status * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_recv_packet_complete(IN pmlan_adapter pmadapter, IN pmlan_buffer pmbuf, IN mlan_status status) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmp; pmlan_callbacks pcb; pmlan_buffer pmbuf_parent; ENTER(); MASSERT(pmadapter && pmbuf); pcb = &pmadapter->callbacks; MASSERT(pmbuf->bss_index < pmadapter->priv_num); pmp = pmadapter->priv[pmbuf->bss_index]; if (pmbuf->pparent) { pmbuf_parent = pmbuf->pparent; pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, pmp->rx_pkt_lock); --pmbuf_parent->use_count; if (!pmbuf_parent->use_count) { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, pmp->rx_pkt_lock); wlan_free_mlan_buffer(pmadapter, pmbuf_parent); } else { pmadapter->callbacks.moal_spin_unlock(pmadapter-> pmoal_handle, pmp->rx_pkt_lock); } wlan_free_mlan_buffer(pmadapter, pmbuf); } else { wlan_free_mlan_buffer(pmadapter, pmbuf); } LEAVE(); return ret; }
/** * @brief This function frees the structure of adapter * * @param pmadapter A pointer to mlan_adapter structure * * @return N/A */ t_void wlan_free_adapter(pmlan_adapter pmadapter) { mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; ENTER(); if (!pmadapter) { PRINTM(MERROR, "The adapter is MNULL.\n"); LEAVE(); return; } wlan_cancel_all_pending_cmd(pmadapter); /* Free command buffer */ PRINTM(MINFO, "Free Command buffer\n"); wlan_free_cmd_buffer(pmadapter); util_free_list_head(&pmadapter->cmd_free_q, pmadapter->callbacks.moal_free_lock); util_free_list_head(&pmadapter->cmd_pending_q, pmadapter->callbacks.moal_free_lock); util_free_list_head(&pmadapter->scan_pending_q, pmadapter->callbacks.moal_free_lock); if (pmadapter->cmd_timer_is_set) { /* Cancel command timeout timer */ pcb->moal_stop_timer(pmadapter->pmlan_cmd_timer); pmadapter->cmd_timer_is_set = MFALSE; } PRINTM(MINFO, "Free ScanTable\n"); if (pmadapter->pscan_table) { pcb->moal_mfree((t_u8 *) pmadapter->pscan_table); pmadapter->pscan_table = MNULL; } if (pmadapter->mp_regs_buf) { pcb->moal_mfree((t_u8 *) pmadapter->mp_regs_buf); pmadapter->mp_regs_buf = MNULL; pmadapter->mp_regs = MNULL; } #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) wlan_free_sdio_mpa_buffers(pmadapter); #endif wlan_free_mlan_buffer(&pmadapter->callbacks, pmadapter->psleep_cfm); LEAVE(); return; }
/** * @brief This function frees the command buffer. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_free_cmd_buffer(IN mlan_adapter * pmadapter) { mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; cmd_ctrl_node *pcmd_array; t_u32 i; ENTER(); /* Need to check if cmd pool is allocated or not */ if (pmadapter->cmd_pool == MNULL) { PRINTM(MINFO, "FREE_CMD_BUF: cmd_pool is Null\n"); goto done; } pcmd_array = pmadapter->cmd_pool; /* Release shared memory buffers */ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) { if (pcmd_array[i].pmbuf) { PRINTM(MCMND, "Free all the command buffer.\n"); wlan_free_mlan_buffer(pcb, pcmd_array[i].pmbuf); pcmd_array[i].pmbuf = MNULL; } if (pcmd_array[i].respbuf) { pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pcmd_array[i].respbuf, 0, MLAN_STATUS_SUCCESS); pcmd_array[i].respbuf = MNULL; } } /* Release cmd_ctrl_node */ if (pmadapter->cmd_pool) { PRINTM(MCMND, "Free command pool.\n"); pcb->moal_mfree((t_u8 *) pmadapter->cmd_pool); pmadapter->cmd_pool = MNULL; } done: LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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 Packet send completion handling * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to mlan_buffer structure * @param status Callback status * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_write_data_complete(IN pmlan_adapter pmadapter, IN pmlan_buffer pmbuf, IN mlan_status status) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb; ENTER(); MASSERT(pmadapter && pmbuf); pcb = &pmadapter->callbacks; if (pmbuf->buf_type == MLAN_BUF_TYPE_DATA) { PRINTM(MDATA, "wlan_write_data_complete: DATA\n"); if (pmbuf->flags & MLAN_BUF_FLAG_MOAL_TX_BUF) { /* pmbuf was allocated by MOAL */ pcb->moal_send_packet_complete(pmadapter->pmoal_handle, pmbuf, status); } else { if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF) { pmadapter->pending_bridge_pkts--; if (pmadapter->rx_pause_flag && (pmadapter->pending_bridge_pkts <= RX_LOW_THRESHOLD)) { pmadapter->rx_pause_flag = MFALSE; wlan_prepare_cmd(pmadapter->priv[pmbuf->bss_num], HOST_CMD_RX_DATA_PAUSE, HostCmd_ACT_GEN_SET, 0, MNULL, MNULL); } } /* pmbuf was allocated by MLAN */ wlan_free_mlan_buffer(pmadapter, pmbuf); } } LEAVE(); return ret; }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void * adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16) pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *) & pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr-> frm_len)); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } /* Reorder and send to OS */ if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8) prx_pd->rx_pkt_type, (void *)pmbuf)) || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: 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 processes received packet and forwards it * to kernel/upper layer * * @param adapter 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_ops_uap_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter)adapter; mlan_status ret = MLAN_STATUS_SUCCESS; UapRxPD *prx_pd; wlan_mgmt_pkt *puap_pkt_hdr = MNULL; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; sta_node *sta_ptr = MNULL; t_u8 adj_rx_rate = 0; ENTER(); prx_pd = (UapRxPD *)(pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ uap_endian_convert_RxPD(prx_pd); priv->rxpd_rate = prx_pd->rx_rate; priv->rxpd_rate_info = prx_pd->rate_info; if (!priv->adapter->psdio_device->v15_fw_api) priv->rxpd_rate_info = wlan_convert_v14_rate_ht_info(priv->rxpd_rate_info); if (priv->bss_type == MLAN_BSS_TYPE_UAP) { adj_rx_rate = wlan_adjust_data_rate(priv, priv->rxpd_rate, priv->rxpd_rate_info); pmadapter->callbacks.moal_hist_data_add(pmadapter->pmoal_handle, pmbuf->bss_index, adj_rx_rate, prx_pd->snr, prx_pd->nf, prx_pd->antenna); } rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); 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); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) != (t_u16)pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ puap_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); puap_pkt_hdr->frm_len = wlan_le16_to_cpu(puap_pkt_hdr->frm_len); if ((puap_pkt_hdr->wlan_header. frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *)&puap_pkt_hdr-> wlan_header, puap_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(puap_pkt_hdr-> frm_len), (RxPD *)prx_pd); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->priority = prx_pd->priority; memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) { sta_ptr = wlan_get_station_entry(priv, ta); if (sta_ptr) sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num; } /* check if UAP enable 11n */ if (!priv->is_11n_enabled || (!wlan_11n_get_rxreorder_tbl ((mlan_private *)priv, prx_pd->priority, ta) && (prx_pd->rx_pkt_type != PKT_TYPE_AMSDU) )) { if (priv->pkt_fwd) wlan_process_uap_rx_packet(priv, pmbuf); else wlan_upload_uap_rx_packet(pmadapter, pmbuf); goto done; } /* Reorder and send to OS */ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (void *)pmbuf); if (ret || (rx_pkt_type == PKT_TYPE_BAR)) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return ret; }
/** * @brief This function checks the interrupt status and handle it accordingly. * * @param pmadapter A pointer to mlan_adapter structure * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_process_int_status(mlan_adapter * pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; t_u8 sdio_ireg; mlan_buffer *pmbuf = MNULL; t_u8 port = 0; t_u32 len_reg_l, len_reg_u; t_u32 rx_blocks; t_u32 ps_state = pmadapter->ps_state; t_u16 rx_len; #if !defined(SDIO_MULTI_PORT_RX_AGGR) t_u32 upld_typ = 0; #endif t_u32 cr = 0; ENTER(); pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pint_lock); sdio_ireg = pmadapter->sdio_ireg; pmadapter->sdio_ireg = 0; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pint_lock); if (!sdio_ireg) goto done; if (sdio_ireg & DN_LD_HOST_INT_STATUS) { pmadapter->mp_wr_bitmap = (t_u32) pmadapter->mp_regs[WR_BITMAP_L]; pmadapter->mp_wr_bitmap |= ((t_u32) pmadapter->mp_regs[WR_BITMAP_U]) << 8; PRINTM(MINTR, "DNLD: wr_bitmap=0x%08x\n", pmadapter->mp_wr_bitmap); if (pmadapter->data_sent && (pmadapter->mp_wr_bitmap & pmadapter->mp_data_port_mask)) { PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n"); pmadapter->data_sent = MFALSE; } } /* As firmware will not generate download ready interrupt if the port updated is command port only, cmd_sent should be done for any SDIO interrupt. */ if (pmadapter->cmd_sent == MTRUE) { /* Check if firmware has attach buffer at command port and update just that in wr_bit_map. */ pmadapter->mp_wr_bitmap |= (t_u32) pmadapter-> mp_regs[WR_BITMAP_L] & CTRL_PORT_MASK; if (pmadapter->mp_wr_bitmap & CTRL_PORT_MASK) pmadapter->cmd_sent = MFALSE; } PRINTM(MINFO, "cmd_sent=%d, data_sent=%d\n", pmadapter->cmd_sent, pmadapter->data_sent); if (sdio_ireg & UP_LD_HOST_INT_STATUS) { pmadapter->mp_rd_bitmap = (t_u32) pmadapter->mp_regs[RD_BITMAP_L]; pmadapter->mp_rd_bitmap |= ((t_u32) pmadapter->mp_regs[RD_BITMAP_U]) << 8; PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n", pmadapter->mp_rd_bitmap); while (MTRUE) { ret = wlan_get_rd_port(pmadapter, &port); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MINFO, "no more rd_port to be handled\n"); break; } len_reg_l = RD_LEN_P0_L + (port << 1); len_reg_u = RD_LEN_P0_U + (port << 1); rx_len = ((t_u16) pmadapter->mp_regs[len_reg_u]) << 8; rx_len |= (t_u16) pmadapter->mp_regs[len_reg_l]; PRINTM(MINFO, "RX: port=%d rx_len=%u\n", port, rx_len); rx_blocks = (rx_len + MLAN_SDIO_BLOCK_SIZE - 1) / MLAN_SDIO_BLOCK_SIZE; if (rx_len <= INTF_HEADER_LEN || (rx_blocks * MLAN_SDIO_BLOCK_SIZE) > ALLOC_BUF_SIZE) { PRINTM(MERROR, "invalid rx_len=%d\n", rx_len); ret = MLAN_STATUS_FAILURE; goto done; } rx_len = (t_u16) (rx_blocks * MLAN_SDIO_BLOCK_SIZE); if (port == CTRL_PORT) pmbuf = wlan_alloc_mlan_buffer(pmadapter, rx_len, 0, MOAL_MALLOC_BUFFER); else pmbuf = wlan_alloc_mlan_buffer(pmadapter, rx_len, MLAN_RX_HEADER_LEN, MOAL_ALLOC_MLAN_BUFFER); if (pmbuf == MNULL) { PRINTM(MERROR, "Failed to allocate 'mlan_buffer'\n"); ret = MLAN_STATUS_FAILURE; goto done; } PRINTM(MINFO, "rx_len = %d\n", rx_len); #ifdef SDIO_MULTI_PORT_RX_AGGR if (MLAN_STATUS_SUCCESS != wlan_sdio_card_to_host_mp_aggr(pmadapter, pmbuf, port, rx_len)) { #else /* Transfer data from card */ if (MLAN_STATUS_SUCCESS != wlan_sdio_card_to_host(pmadapter, &upld_typ, (t_u32 *) & pmadapter-> upld_len, pmbuf, rx_len, pmadapter->ioport + port)) { #endif /* SDIO_MULTI_PORT_RX_AGGR */ if (port == CTRL_PORT) pmadapter->dbg. num_cmdevt_card_to_host_failure++; else pmadapter->dbg. num_rx_card_to_host_failure++; PRINTM(MERROR, "Card to host failed: int status=0x%x\n", sdio_ireg); #ifndef SDIO_MULTI_PORT_RX_AGGR wlan_free_mlan_buffer(pmadapter, pmbuf); #endif ret = MLAN_STATUS_FAILURE; goto term_cmd53; } #ifndef SDIO_MULTI_PORT_RX_AGGR wlan_decode_rx_packet(pmadapter, pmbuf, upld_typ); #endif } /* We might receive data/sleep_cfm at the same time */ /* reset data_receive flag to avoid ps_state change */ if ((ps_state == PS_STATE_SLEEP_CFM) && (pmadapter->ps_state == PS_STATE_SLEEP)) pmadapter->data_received = MFALSE; } ret = MLAN_STATUS_SUCCESS; goto done; term_cmd53: /* terminate cmd53 */ if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle, HOST_TO_CARD_EVENT_REG, &cr)) PRINTM(MERROR, "read CFG reg failed\n"); PRINTM(MINFO, "Config Reg val = %d\n", cr); if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle, HOST_TO_CARD_EVENT_REG, (cr | HOST_TERM_CMD53))) PRINTM(MERROR, "write CFG reg failed\n"); PRINTM(MINFO, "write success\n"); if (MLAN_STATUS_SUCCESS != pcb->moal_read_reg(pmadapter->pmoal_handle, HOST_TO_CARD_EVENT_REG, &cr)) PRINTM(MERROR, "read CFG reg failed\n"); PRINTM(MINFO, "Config reg val =%x\n", cr); done: LEAVE(); return ret; } /** * @brief This function sends data to the card. * * @param pmadapter A pointer to mlan_adapter structure * @param type data or command * @param pmbuf A pointer to mlan_buffer (pmbuf->data_len should include SDIO header) * @param tx_param A pointer to mlan_tx_param * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_sdio_host_to_card(mlan_adapter * pmadapter, t_u8 type, mlan_buffer * pmbuf, mlan_tx_param * tx_param) { mlan_status ret = MLAN_STATUS_SUCCESS; t_u32 buf_block_len; t_u32 blksz; t_u8 port = 0; t_u32 cmd53_port = 0; t_u8 *payload = pmbuf->pbuf + pmbuf->data_offset; ENTER(); /* Allocate buffer and copy payload */ blksz = MLAN_SDIO_BLOCK_SIZE; buf_block_len = (pmbuf->data_len + blksz - 1) / blksz; *(t_u16 *) & payload[0] = wlan_cpu_to_le16((t_u16) pmbuf->data_len); *(t_u16 *) & payload[2] = wlan_cpu_to_le16(type); /* * This is SDIO specific header * t_u16 length, * t_u16 type (MLAN_TYPE_DATA = 0, MLAN_TYPE_CMD = 1, MLAN_TYPE_EVENT = 3) */ if (type == MLAN_TYPE_DATA) { ret = wlan_get_wr_port_data(pmadapter, &port); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "no wr_port available: %d\n", ret); goto exit; } /* Transfer data to card */ pmbuf->data_len = buf_block_len * blksz; #ifdef SDIO_MULTI_PORT_TX_AGGR if (tx_param) ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port, tx_param->next_pkt_len); else ret = wlan_host_to_card_mp_aggr(pmadapter, pmbuf, port, 0); #else ret = wlan_write_data_sync(pmadapter, pmbuf, pmadapter->ioport + port); #endif /* SDIO_MULTI_PORT_TX_AGGR */ } else { /* Type must be MLAN_TYPE_CMD */ pmadapter->cmd_sent = MTRUE; /* clear CTRL PORT */ pmadapter->mp_wr_bitmap &= (t_u32) (~(1 << CTRL_PORT)); if (pmbuf->data_len <= INTF_HEADER_LEN || pmbuf->data_len > WLAN_UPLD_SIZE) PRINTM(MWARN, "wlan_sdio_host_to_card(): Error: payload=%p, nb=%d\n", payload, pmbuf->data_len); /* Transfer data to card */ pmbuf->data_len = buf_block_len * blksz; cmd53_port = pmadapter->ioport + CTRL_PORT; ret = wlan_write_data_sync(pmadapter, pmbuf, cmd53_port); } if (ret != MLAN_STATUS_SUCCESS) { if (type == MLAN_TYPE_CMD) pmadapter->cmd_sent = MFALSE; if (type == MLAN_TYPE_DATA) pmadapter->data_sent = MFALSE; } else { if (type == MLAN_TYPE_DATA) { if (! (pmadapter-> mp_wr_bitmap & (1 << pmadapter->curr_wr_port))) pmadapter->data_sent = MTRUE; else pmadapter->data_sent = MFALSE; } DBG_HEXDUMP(MIF_D, "SDIO Blk Wr", pmbuf->pbuf + pmbuf->data_offset, MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN)); } exit: LEAVE(); return ret; }
/** * @brief This function decodes the rx packet & * calls corresponding handlers according to the packet type * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to the SDIO data/cmd buffer * @param upld_typ Type of rx packet * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_decode_rx_packet(mlan_adapter * pmadapter, mlan_buffer * pmbuf, t_u32 upld_typ) { t_u8 *cmdBuf; t_u32 event; ENTER(); switch (upld_typ) { case MLAN_TYPE_DATA: PRINTM(MINFO, "--- Rx: Data packet ---\n"); pmbuf->data_len = (pmadapter->upld_len - INTF_HEADER_LEN); pmbuf->data_offset += INTF_HEADER_LEN; util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->rx_data_queue, (pmlan_linked_list) pmbuf, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); util_scalar_increment(pmadapter->pmoal_handle, &pmadapter->rx_pkts_queued, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); pmadapter->data_received = MTRUE; break; case MLAN_TYPE_CMD: PRINTM(MINFO, "--- Rx: Cmd Response ---\n"); /* take care of curr_cmd = NULL case */ if (!pmadapter->curr_cmd) { cmdBuf = pmadapter->upld_buf; if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) { wlan_process_sleep_confirm_resp(pmadapter, pmbuf->pbuf + pmbuf-> data_offset + INTF_HEADER_LEN, pmadapter-> upld_len - INTF_HEADER_LEN); } pmadapter->upld_len -= INTF_HEADER_LEN; memcpy(pmadapter, cmdBuf, pmbuf->pbuf + pmbuf->data_offset + INTF_HEADER_LEN, MIN(MRVDRV_SIZE_OF_CMD_BUFFER, pmadapter->upld_len - INTF_HEADER_LEN)); wlan_free_mlan_buffer(pmadapter, pmbuf); } else { pmadapter->cmd_resp_received = MTRUE; pmadapter->upld_len -= INTF_HEADER_LEN; pmbuf->data_len = pmadapter->upld_len; pmbuf->data_offset += INTF_HEADER_LEN; pmadapter->curr_cmd->respbuf = pmbuf; } break; case MLAN_TYPE_EVENT: PRINTM(MINFO, "--- Rx: Event ---\n"); event = *(t_u32 *) & pmbuf->pbuf[pmbuf->data_offset + INTF_HEADER_LEN]; pmadapter->event_cause = wlan_le32_to_cpu(event); if ((pmadapter->upld_len > MLAN_EVENT_HEADER_LEN) && ((pmadapter->upld_len - MLAN_EVENT_HEADER_LEN) < MAX_EVENT_SIZE)) { memcpy(pmadapter, pmadapter->event_body, pmbuf->pbuf + pmbuf->data_offset + MLAN_EVENT_HEADER_LEN, pmadapter->upld_len - MLAN_EVENT_HEADER_LEN); } /* event cause has been saved to adapter->event_cause */ pmadapter->event_received = MTRUE; pmbuf->data_len = pmadapter->upld_len; pmadapter->pmlan_buffer_event = pmbuf; /* remove SDIO header */ pmbuf->data_offset += INTF_HEADER_LEN; pmbuf->data_len -= INTF_HEADER_LEN; break; default: PRINTM(MERROR, "SDIO unknown upload type = 0x%x\n", upld_typ); wlan_free_mlan_buffer(pmadapter, pmbuf); break; } LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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; t_u32 sec, usec; 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, MTRUE); 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 = pmadapter->callbacks.moal_write_data_async(pmadapter->pmoal_handle, pmbuf, MLAN_USB_EP_DATA); 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; } pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, &usec); 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 receives data from the card in aggregate mode. * * @param pmadapter A pointer to mlan_adapter structure * @param pmbuf A pointer to the SDIO data/cmd buffer * @param port Current port on which packet needs to be rxed * @param rx_len Length of received packet * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_sdio_card_to_host_mp_aggr(mlan_adapter * pmadapter, mlan_buffer * pmbuf, t_u8 port, t_u16 rx_len) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; t_s32 f_do_rx_aggr = 0; t_s32 f_do_rx_cur = 0; t_s32 f_aggr_cur = 0; mlan_buffer mbuf_aggr; mlan_buffer *mbuf_deaggr; t_u32 pind = 0; t_u32 pkt_len, pkt_type = 0; t_u8 *curr_ptr; t_u32 cmd53_port = 0; ENTER(); if (port == CTRL_PORT) { /* Read the command response or event without aggr */ PRINTM(MINFO, "card_2_host_mp_aggr: No aggr for control port\n"); f_do_rx_cur = 1; goto rx_curr_single; } if (!pmadapter->mpa_rx.enabled) { PRINTM(MINFO, "card_2_host_mp_aggr: rx aggregation disabled !\n"); f_do_rx_cur = 1; goto rx_curr_single; } if (pmadapter->mp_rd_bitmap & (~((t_u32) CTRL_PORT_MASK))) { /* Some more data RX pending */ PRINTM(MINFO, "card_2_host_mp_aggr: Not last packet\n"); if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) { f_aggr_cur = 1; } else { /* No room in Aggr buf, do rx aggr now */ f_do_rx_aggr = 1; f_do_rx_cur = 1; } } else { /* Rx aggr not in progress */ f_aggr_cur = 1; } } else { /* No more data RX pending */ PRINTM(MINFO, "card_2_host_mp_aggr: Last packet\n"); if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { f_do_rx_aggr = 1; if (MP_RX_AGGR_BUF_HAS_ROOM(pmadapter, rx_len)) { f_aggr_cur = 1; } else { /* No room in Aggr buf, do rx aggr now */ f_do_rx_cur = 1; } } else { f_do_rx_cur = 1; } } if (f_aggr_cur) { PRINTM(MINFO, "Current packet aggregation.\n"); /* Curr pkt can be aggregated */ MP_RX_AGGR_SETUP(pmadapter, pmbuf, port, rx_len); if (MP_RX_AGGR_PKT_LIMIT_REACHED(pmadapter) || MP_RX_AGGR_PORT_LIMIT_REACHED(pmadapter)) { PRINTM(MINFO, "card_2_host_mp_aggr: Aggregation Packet limit reached\n"); /* No more pkts allowed in Aggr buf, rx it */ f_do_rx_aggr = 1; } } if (f_do_rx_aggr) { /* do aggr RX now */ PRINTM(MINFO, "do_rx_aggr: num of packets: %d\n", pmadapter->mpa_rx.pkt_cnt); memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer)); mbuf_aggr.pbuf = (t_u8 *) pmadapter->mpa_rx.buf; mbuf_aggr.data_len = pmadapter->mpa_rx.buf_len; cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE | (pmadapter->mpa_rx.ports << 4)) + pmadapter->mpa_rx.start_port; if (MLAN_STATUS_SUCCESS != pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf_aggr, cmd53_port, 0)) { pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL; ret = MLAN_STATUS_FAILURE; goto done; } DBG_HEXDUMP(MIF_D, "SDIO MP-A Blk Rd", pmadapter->mpa_rx.buf, MIN(pmadapter->mpa_rx.buf_len, MAX_DATA_DUMP_LEN)); curr_ptr = pmadapter->mpa_rx.buf; for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) { /* get curr PKT len & type */ pkt_len = wlan_le16_to_cpu(*(t_u16 *) & curr_ptr[0]); pkt_type = wlan_le16_to_cpu(*(t_u16 *) & curr_ptr[2]); PRINTM(MINFO, "RX: [%d] pktlen: %d pkt_type: 0x%x\n", pind, pkt_len, pkt_type); /* copy pkt to deaggr buf */ mbuf_deaggr = pmadapter->mpa_rx.mbuf_arr[pind]; if ((pkt_type == MLAN_TYPE_DATA) && (pkt_len <= pmadapter->mpa_rx.len_arr[pind])) { memcpy(pmadapter, mbuf_deaggr->pbuf + mbuf_deaggr->data_offset, curr_ptr, pkt_len); pmadapter->upld_len = pkt_len; /* Process de-aggr packet */ wlan_decode_rx_packet(pmadapter, mbuf_deaggr, pkt_type); } else { PRINTM(MERROR, "Wrong aggr packet: type=%d, len=%d, max_len=%d\n", pkt_type, pkt_len, pmadapter->mpa_rx.len_arr[pind]); wlan_free_mlan_buffer(pmadapter, mbuf_deaggr); } curr_ptr += pmadapter->mpa_rx.len_arr[pind]; } MP_RX_AGGR_BUF_RESET(pmadapter); } rx_curr_single: if (f_do_rx_cur) { PRINTM(MINFO, "RX: f_do_rx_cur: port: %d rx_len: %d\n", port, rx_len); if (MLAN_STATUS_SUCCESS != wlan_sdio_card_to_host(pmadapter, &pkt_type, (t_u32 *) & pmadapter->upld_len, pmbuf, rx_len, pmadapter->ioport + port)) { ret = MLAN_STATUS_FAILURE; goto done; } if ((port == CTRL_PORT) && ((pkt_type != MLAN_TYPE_EVENT) && (pkt_type != MLAN_TYPE_CMD))) { PRINTM(MERROR, "Wrong pkt from CTRL PORT: type=%d, len=%dd\n", pkt_type, pmbuf->data_len); pmbuf->status_code = MLAN_ERROR_DATA_RX_FAIL; ret = MLAN_STATUS_FAILURE; goto done; } wlan_decode_rx_packet(pmadapter, pmbuf, pkt_type); } done: if (ret == MLAN_STATUS_FAILURE) { if (MP_RX_AGGR_IN_PROGRESS(pmadapter)) { /* MP-A transfer failed - cleanup */ for (pind = 0; pind < pmadapter->mpa_rx.pkt_cnt; pind++) { wlan_free_mlan_buffer(pmadapter, pmadapter->mpa_rx. mbuf_arr[pind]); } MP_RX_AGGR_BUF_RESET(pmadapter); } if (f_do_rx_cur) { /* Single Transfer pending */ /* Free curr buff also */ 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; #ifndef CONFIG_MLAN_WMSDK 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 }; #endif /* CONFIG_MLAN_WMSDK */ ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Note: Important. We do not have actual data @ prx_pd->rx_pkt_offset */ /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */ /* prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc; */ /** Small debug type */ #define DBG_TYPE_SMALL 2 /** Size of debugging structure */ #define SIZE_OF_DBG_STRUCT 4 /* This additional processing does not seem to be required by us for the moment. Let skip it for now. They seem to be doing some kind of ethernet header processing. */ #ifndef CONFIG_MLAN_WMSDK 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", (t_s8 *) ((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; } /* 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)); /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */ /* 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)); */ #endif /* CONFIG_MLAN_WMSDK */ priv->rxpd_rate = prx_pd->rx_rate; priv->rxpd_htinfo = prx_pd->ht_info; #ifndef CONFIG_MLAN_WMSDK /* wmsdk: looks like only a debugging thing. disabling for now */ pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); 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); #endif /* CONFIG_MLAN_WMSDK */ 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 the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void * adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16) pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (prx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { pmbuf->data_len = prx_pd->rx_pkt_length; pmbuf->data_offset += prx_pd->rx_pkt_offset; wlan_11n_deaggregate_pkt(priv, pmbuf); goto done; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } /* Reorder and send to OS */ if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8) prx_pd->rx_pkt_type, (void *) pmbuf)) || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } 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 }; 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; }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter)adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; sta_node *sta_ptr = MNULL; ENTER(); prx_pd = (RxPD *)(pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; prx_pkt = (RxPacketHdr_t *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16)pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *)((t_u8 *)prx_pd + prx_pd->rx_pkt_offset); pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0){ wlan_process_802dot11_mgmt_pkt(pmadapter-> priv[pmbuf->bss_index], (t_u8 *)&pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr-> frm_len),prx_pd); wlan_sta_check_mgmt_frame(pmadapter->priv[pmbuf->bss_index], (t_u8 *) &pmgmt_pkt_hdr->wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len), prx_pd); } wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if ((!IS_11N_ENABLED(priv) && !(prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv) || (prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); if ((prx_pd->flags & RXPD_FLAG_PKT_DIRECT_LINK) && (prx_pd->priority < MAX_NUM_TID)) { PRINTM(MDATA, "tdls packet %p " MACSTR "\n", pmbuf, MAC2STR(ta)); sta_ptr = wlan_get_station_entry(priv, ta); if (sta_ptr) { sta_ptr->rx_seq[prx_pd->priority] = prx_pd->seq_num; sta_ptr->snr = prx_pd->snr; sta_ptr->nf = prx_pd->nf; pmadapter->callbacks. moal_updata_peer_signal(pmadapter-> pmoal_handle, pmbuf-> bss_index, ta, prx_pd->snr, prx_pd->nf); } } } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } if ((priv->port_ctrl_mode == MTRUE && priv->port_open == MFALSE) && (rx_pkt_type != PKT_TYPE_BAR)) { mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (t_void *)RX_PKT_DROPPED_IN_FW); wlan_process_rx_packet(pmadapter, pmbuf); goto done; } /* Reorder and send to OS */ ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type, (void *)pmbuf); if (ret || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } done: LEAVE(); return ret; }
/** * @brief This function processes the received buffer * * @param adapter A pointer to mlan_adapter * @param pmbuf A pointer to the received buffer * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_sta_process_rx_packet(IN t_void * adapter, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPD *prx_pd; RxPacketHdr_t *prx_pkt; pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; t_u8 ta[MLAN_MAC_ADDR_LENGTH]; t_u16 rx_pkt_type = 0; /* wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL; */ ENTER(); prx_pd = (RxPD *) (pmbuf->pbuf + pmbuf->data_offset); /* Endian conversion */ endian_convert_RxPD(prx_pd); rx_pkt_type = prx_pd->rx_pkt_type; /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */ /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */ prx_pkt = (RxPacketHdr_t *) pmbuf->pdesc; /* wmprintf("%p + %d: O: %d PL: %d DL: %d\n\r", */ /* pmbuf->pbuf, pmbuf->data_offset, */ /* prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length, pmbuf->data_len); */ if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16) pmbuf->data_len) { PRINTM(MERROR, "Wrong rx packet: len=%d,rx_pkt_offset=%d," " rx_pkt_length=%d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; ret = MLAN_STATUS_FAILURE; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length; if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME) { /* Check if this is mgmt packet and needs to forwarded to app as an event */ /* fixme */ wmprintf("Is a management packet expected here?\n\r"); os_enter_critical_section(); while(1){} #ifndef CONFIG_MLAN_WMSDK /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */ /* pmgmt_pkt_hdr = */ /* (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */ pmgmt_pkt_hdr = (wlan_mgmt_pkt *)pmbuf->pdesc; pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len); if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0) wlan_process_802dot11_mgmt_pkt(pmadapter->priv[pmbuf->bss_index], (t_u8 *) & pmgmt_pkt_hdr-> wlan_header, pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len)); wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; #endif /* CONFIG_MLAN_WMSDK */ } #ifdef DUMP_PACKET_MAC dump_mac_addr("Own: ", priv->curr_addr); dump_mac_addr("Dest: ", prx_pkt->eth803_hdr.dest_addr); #endif /* DUMP_PACKET_MAC */ /* * If the packet is not an unicast packet then send the packet * directly to os. Don't pass thru rx reordering */ if (!IS_11N_ENABLED(priv) || memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH)) { wlan_process_rx_packet(pmadapter, pmbuf); goto done; } if (queuing_ra_based(priv)) { memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH); } else { if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) priv->rx_seq[prx_pd->priority] = prx_pd->seq_num; memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH); } /* Reorder and send to OS */ if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8) prx_pd->rx_pkt_type, (void *) pmbuf)) || (rx_pkt_type == PKT_TYPE_BAR) ) { wlan_free_mlan_buffer(pmadapter, pmbuf); } 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; }