/** * @brief This function allocates the command buffer and links * it to command free queue. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_alloc_cmd_buffer(IN mlan_adapter * pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; cmd_ctrl_node *pcmd_array; t_u32 buf_size; t_u32 i; ENTER(); /* Allocate and initialize cmd_ctrl_node */ buf_size = sizeof(cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER; ret = pcb->moal_malloc(buf_size, (t_u8 **) & pcmd_array); if (ret != MLAN_STATUS_SUCCESS || !pcmd_array) { PRINTM(MERROR, "ALLOC_CMD_BUF: Failed to allocate pcmd_array\n"); ret = MLAN_STATUS_FAILURE; goto done; } pmadapter->cmd_pool = pcmd_array; memset(pmadapter->cmd_pool, 0, buf_size); /* Allocate and initialize command buffers */ for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) { if (! (pcmd_array[i].pmbuf = wlan_alloc_mlan_buffer(pcb, (MRVDRV_SIZE_OF_CMD_BUFFER + HEADER_ALIGNMENT)))) { PRINTM(MERROR, "ALLOC_CMD_BUF: pcmd_buf: out of memory\n"); ret = MLAN_STATUS_FAILURE; goto done; } } for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) { wlan_insert_cmd_to_free_q(pmadapter, &pcmd_array[i]); } ret = MLAN_STATUS_SUCCESS; done: LEAVE(); return ret; }
/** * @brief This function allocates buffer for the members of adapter * structure like command buffer and BSSID list. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter) { int i; mlan_status ret = MLAN_STATUS_SUCCESS; t_u32 buf_size; BSSDescriptor_t *ptemp_scan_table; t_u8 *head_ptr = MNULL; ENTER(); /* Allocate buffer to store the BSSID list */ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; ret = pmadapter->callbacks.moal_malloc(buf_size, (t_u8 **) & ptemp_scan_table); if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { PRINTM(MERROR, "Failed to allocate scan table\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->pscan_table = ptemp_scan_table; /* Initialize cmd_free_q */ util_init_list_head(&pmadapter->cmd_free_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Initialize cmd_pending_q */ util_init_list_head(&pmadapter->cmd_pending_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Initialize scan_pending_q */ util_init_list_head(&pmadapter->scan_pending_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Allocate command buffer */ ret = wlan_alloc_cmd_buffer(pmadapter); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate command buffer\n"); LEAVE(); return MLAN_STATUS_FAILURE; } for (i = 0; i < MLAN_MAX_BSS_NUM; ++i) { util_init_list_head(&pmadapter->bssprio_tbl[i].bssprio_head, MTRUE, pmadapter->callbacks.moal_init_lock); pmadapter->bssprio_tbl[i].bssprio_cur = MNULL; } ret = pmadapter->callbacks.moal_malloc(MAX_MP_REGS + HEADER_ALIGNMENT, (t_u8 **) & pmadapter->mp_regs_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) { PRINTM(MERROR, "Failed to allocate mp_regs_buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->mp_regs = (t_u8 *) ALIGN_ADDR(pmadapter->mp_regs_buf, HEADER_ALIGNMENT); PRINTM(MINFO, "Try to assign mp_regs to handle\n"); ret = pmadapter->callbacks.moal_get_cardregs(pmadapter->pmoal_handle, pmadapter->mp_regs); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to assign mp_regs to handle\n"); LEAVE(); return MLAN_STATUS_FAILURE; } #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) ret = wlan_alloc_sdio_mpa_buffers(pmadapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE, SDIO_MP_RX_AGGR_DEF_BUF_SIZE); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n"); LEAVE(); return MLAN_STATUS_FAILURE; } #endif if ((wlan_get_priv(pmadapter, MLAN_BSS_TYPE_ANY))->bss_type == MLAN_BSS_TYPE_STA) pmadapter->psleep_cfm = wlan_alloc_mlan_buffer(&pmadapter->callbacks, HEADER_ALIGNMENT + sizeof(opt_sleep_confirm_buffer)); if (!pmadapter->psleep_cfm) { PRINTM(MERROR, "Failed to allocate sleep confirm buffers\n"); LEAVE(); return MLAN_STATUS_FAILURE; } head_ptr = (t_u8 *) ALIGN_ADDR(pmadapter->psleep_cfm->pbuf + pmadapter->psleep_cfm->data_offset, HEADER_ALIGNMENT); pmadapter->psleep_cfm->data_offset += head_ptr - (pmadapter->psleep_cfm->pbuf + pmadapter->psleep_cfm->data_offset); LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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 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_uap_recv_packet(IN mlan_private *priv, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = priv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPacketHdr_t *prx_pkt; pmlan_buffer newbuf = MNULL; ENTER(); prx_pkt = (RxPacketHdr_t *)((t_u8 *)pmbuf->pbuf + pmbuf->data_offset); DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset, MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN)); PRINTM(MDATA, "AMSDU dest " MACSTR "\n", MAC2STR(prx_pkt->eth803_hdr.dest_addr)); /* don't do packet forwarding in disconnected state */ if ((priv->media_connected == MFALSE) || (pmbuf->data_len > 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 */ memcpy(pmadapter, (t_u8 *)newbuf->pbuf + newbuf->data_offset, pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); newbuf->data_len = pmbuf->data_len; 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))) { /* Intra BSS packet */ 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 */ memcpy(pmadapter, (t_u8 *)newbuf->pbuf + newbuf->data_offset, pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); newbuf->data_len = pmbuf->data_len; 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); } goto done; } else if (MLAN_STATUS_FAILURE == wlan_check_unicast_packet(priv, prx_pkt->eth803_hdr. dest_addr)) { /* drop packet */ PRINTM(MDATA, "Drop AMSDU dest " MACSTR "\n", MAC2STR(prx_pkt->eth803_hdr.dest_addr)); goto done; } } upload: /** send packet to moal */ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); done: LEAVE(); return ret; }
/** * @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 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 Deaggregate the received AMSDU packet * * @param priv A pointer to mlan_private structure * @param pmbuf A pointer to aggregated data packet * * @return MLAN_STATUS_SUCCESS --success, otherwise fail */ mlan_status wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf) { t_u16 pkt_len; int total_pkt_len; t_u8 *data; t_u32 max_rx_data_size = MLAN_RX_DATA_BUF_SIZE; int pad; mlan_status ret = MLAN_STATUS_FAILURE; RxPacketHdr_t *prx_pkt; mlan_buffer *daggr_mbuf = MNULL; mlan_adapter *pmadapter = priv->adapter; t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; t_u8 hdr_len = sizeof(Eth803Hdr_t); ENTER(); data = (t_u8 *) (pmbuf->pbuf + pmbuf->data_offset); total_pkt_len = pmbuf->data_len; /* Sanity test */ if (total_pkt_len > max_rx_data_size) { PRINTM(MERROR, "Total packet length greater than tx buffer" " size %d\n", total_pkt_len); goto done; } pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len); while (total_pkt_len >= hdr_len) { prx_pkt = (RxPacketHdr_t *) data; /* Length will be in network format, change it to host */ pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH)))); if (pkt_len > total_pkt_len) { PRINTM(MERROR, "Error in packet length: total_pkt_len = %d, pkt_len = %d\n", total_pkt_len, pkt_len); break; } pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ? (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0; total_pkt_len -= pkt_len + pad + sizeof(Eth803Hdr_t); if (memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 * MLAN_MAC_ADDR_LENGTH)); data += LLC_SNAP_LEN; pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN; } else { *(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH)) = (t_u16) 0; pkt_len += sizeof(Eth803Hdr_t); } daggr_mbuf = wlan_alloc_mlan_buffer(pmadapter, pkt_len, 0, MOAL_ALLOC_MLAN_BUFFER); if (daggr_mbuf == MNULL) { PRINTM(MERROR, "Error allocating daggr mlan_buffer\n"); LEAVE(); return MLAN_STATUS_FAILURE; } daggr_mbuf->bss_index = pmbuf->bss_index; daggr_mbuf->buf_type = pmbuf->buf_type; daggr_mbuf->data_len = pkt_len; daggr_mbuf->in_ts_sec = pmbuf->in_ts_sec; daggr_mbuf->in_ts_usec = pmbuf->in_ts_usec; daggr_mbuf->pparent = pmbuf; daggr_mbuf->priority = pmbuf->priority; memcpy(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset, data, pkt_len); #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { ret = wlan_uap_recv_packet(priv, daggr_mbuf); } else { #endif /* UAP_SUPPORT */ ret = pmadapter->callbacks.moal_recv_packet(pmadapter-> pmoal_handle, daggr_mbuf); #ifdef UAP_SUPPORT } #endif /* UAP_SUPPORT */ switch (ret) { case MLAN_STATUS_PENDING: break; case MLAN_STATUS_FAILURE: PRINTM(MERROR, "Deaggr, send to moal failed\n"); daggr_mbuf->status_code = MLAN_ERROR_PKT_INVALID; case MLAN_STATUS_SUCCESS: wlan_recv_packet_complete(pmadapter, daggr_mbuf, ret); break; default: break; } data += pkt_len + pad; } done: LEAVE(); return ret; }
/** * @brief This function allocates buffer for the members of adapter * structure like command buffer and BSSID list. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef STA_SUPPORT t_u32 buf_size; BSSDescriptor_t *ptemp_scan_table = MNULL; #endif ENTER(); #ifdef STA_SUPPORT /* Allocate buffer to store the BSSID list */ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, (t_u8 **) & ptemp_scan_table); if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { PRINTM(MERROR, "Failed to allocate scan table\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->pscan_table = ptemp_scan_table; ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, DEFAULT_SCAN_BEACON_BUFFER, MLAN_MEM_DEF, (t_u8 **) & pmadapter->bcn_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) { PRINTM(MERROR, "Failed to allocate bcn buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->bcn_buf_size = DEFAULT_SCAN_BEACON_BUFFER; #endif /* Allocate command buffer */ ret = wlan_alloc_cmd_buffer(pmadapter); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate command buffer\n"); LEAVE(); return MLAN_STATUS_FAILURE; } ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, MAX_MP_REGS + DMA_ALIGNMENT, MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **) & pmadapter->mp_regs_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) { PRINTM(MERROR, "Failed to allocate mp_regs_buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->mp_regs = (t_u8 *) ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT); #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) ret = wlan_alloc_sdio_mpa_buffers(pmadapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE, SDIO_MP_RX_AGGR_DEF_BUF_SIZE); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n"); LEAVE(); return MLAN_STATUS_FAILURE; } #endif pmadapter->psleep_cfm = wlan_alloc_mlan_buffer(pmadapter, sizeof(opt_sleep_confirm_buffer), 0, MTRUE); LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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 allocates buffer for the members of adapter * structure like command buffer and BSSID list. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef STA_SUPPORT t_u32 buf_size; BSSDescriptor_t *ptemp_scan_table = MNULL; t_u8 chan_2g[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; t_u8 chan_5g[] = { 12, 16, 34, 38, 42, 46, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 149, 153, 157, 161, 165 }; #endif t_u32 max_mp_regs = pmadapter->psdio_device->reg->max_mp_regs; #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) t_u32 mp_tx_aggr_buf_size = pmadapter->psdio_device->mp_tx_aggr_buf_size; t_u32 mp_rx_aggr_buf_size = pmadapter->psdio_device->mp_rx_aggr_buf_size; #endif ENTER(); #ifdef STA_SUPPORT /* Allocate buffer to store the BSSID list */ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; if (pmadapter->callbacks.moal_vmalloc && pmadapter->callbacks.moal_vfree) ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle, buf_size, (t_u8 **) &ptemp_scan_table); else ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, (t_u8 **) &ptemp_scan_table); if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { PRINTM(MERROR, "Failed to allocate scan table\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->pscan_table = ptemp_scan_table; if (pmadapter->callbacks.moal_vmalloc && pmadapter->callbacks.moal_vfree) ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle, DEFAULT_SCAN_BEACON_BUFFER, (t_u8 **)&pmadapter-> bcn_buf); else ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, DEFAULT_SCAN_BEACON_BUFFER, MLAN_MEM_DEF, (t_u8 **)&pmadapter-> bcn_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->bcn_buf) { PRINTM(MERROR, "Failed to allocate bcn buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->bcn_buf_size = DEFAULT_SCAN_BEACON_BUFFER; pmadapter->num_in_chan_stats = sizeof(chan_2g); pmadapter->num_in_chan_stats += sizeof(chan_5g); buf_size = sizeof(ChanStatistics_t) * pmadapter->num_in_chan_stats; if (pmadapter->callbacks.moal_vmalloc && pmadapter->callbacks.moal_vfree) ret = pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle, buf_size, (t_u8 **)&pmadapter-> pchan_stats); else ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, (t_u8 **)&pmadapter-> pchan_stats); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->pchan_stats) { PRINTM(MERROR, "Failed to allocate channel statistics\n"); LEAVE(); return MLAN_STATUS_FAILURE; } #endif /* Allocate command buffer */ ret = wlan_alloc_cmd_buffer(pmadapter); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate command buffer\n"); LEAVE(); return MLAN_STATUS_FAILURE; } ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, max_mp_regs + DMA_ALIGNMENT, MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **)&pmadapter-> mp_regs_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) { PRINTM(MERROR, "Failed to allocate mp_regs_buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->mp_regs = (t_u8 *)ALIGN_ADDR(pmadapter->mp_regs_buf, DMA_ALIGNMENT); #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) pmadapter->max_sp_tx_size = MAX_SUPPORT_AMSDU_SIZE; pmadapter->max_sp_rx_size = MAX_SUPPORT_AMSDU_SIZE; ret = wlan_alloc_sdio_mpa_buffers(pmadapter, mp_tx_aggr_buf_size, mp_rx_aggr_buf_size); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n"); LEAVE(); return MLAN_STATUS_FAILURE; } if (mlan_drvdbg & MMPA_D) { pmadapter->mpa_buf_size = SDIO_MP_DBG_NUM * pmadapter->psdio_device->mp_aggr_pkt_limit * MLAN_SDIO_BLOCK_SIZE; if (pmadapter->callbacks.moal_vmalloc && pmadapter->callbacks.moal_vfree) ret = pmadapter->callbacks.moal_vmalloc(pmadapter-> pmoal_handle, pmadapter-> mpa_buf_size, (t_u8 **) &pmadapter-> mpa_buf); else ret = pmadapter->callbacks.moal_malloc(pmadapter-> pmoal_handle, pmadapter-> mpa_buf_size, MLAN_MEM_DEF, (t_u8 **) &pmadapter-> mpa_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mpa_buf) { PRINTM(MERROR, "Failed to allocate mpa buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } } #endif pmadapter->psleep_cfm = wlan_alloc_mlan_buffer(pmadapter, sizeof(opt_sleep_confirm_buffer), 0, MOAL_MALLOC_BUFFER); LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @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 %02x:%02x:%02x:%02x:%02x:%02x\n", prx_pkt->eth803_hdr.dest_addr[0], prx_pkt->eth803_hdr.dest_addr[1], prx_pkt->eth803_hdr.dest_addr[2], prx_pkt->eth803_hdr.dest_addr[3], prx_pkt->eth803_hdr.dest_addr[4], prx_pkt->eth803_hdr.dest_addr[5]); /* 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) { /* Multicast pkt */ if ((newbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_TX_DATA_BUF_SIZE_2K, 0, MTRUE))) { 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); pmadapter->pending_bridge_pkts++; 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 (pmadapter->pending_bridge_pkts > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); } } else { if (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; pmadapter->pending_bridge_pkts++; wlan_wmm_add_buf_txqueue(pmadapter, pmbuf); if (pmadapter->pending_bridge_pkts > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, MNULL, MLAN_USB_EP_DATA, ret); 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(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) { pmadapter->callbacks.moal_recv_complete(pmadapter->pmoal_handle, pmbuf, MLAN_USB_EP_DATA, ret); } 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_uap_recv_packet(IN mlan_private * priv, IN pmlan_buffer pmbuf) { pmlan_adapter pmadapter = priv->adapter; mlan_status ret = MLAN_STATUS_SUCCESS; RxPacketHdr_t *prx_pkt; pmlan_buffer newbuf = MNULL; ENTER(); prx_pkt = (RxPacketHdr_t *) ((t_u8 *) pmbuf->pbuf + pmbuf->data_offset); DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset, MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN)); PRINTM(MDATA, "AMSDU dest %02x:%02x:%02x:%02x:%02x:%02x\n", prx_pkt->eth803_hdr.dest_addr[0], prx_pkt->eth803_hdr.dest_addr[1], prx_pkt->eth803_hdr.dest_addr[2], prx_pkt->eth803_hdr.dest_addr[3], prx_pkt->eth803_hdr.dest_addr[4], prx_pkt->eth803_hdr.dest_addr[5]); /* don't do packet forwarding in disconnected state */ if ((priv->media_connected == MFALSE) || (pmbuf->data_len > MV_ETH_FRAME_LEN)) goto upload; if (prx_pkt->eth803_hdr.dest_addr[0] & 0x01) { /* Multicast pkt */ if ((newbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_TX_DATA_BUF_SIZE_2K, 0, MTRUE))) { 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); pmadapter->pending_bridge_pkts++; newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF; /* copy the data */ memcpy(pmadapter, (t_u8 *) newbuf->pbuf + newbuf->data_offset, pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); newbuf->data_len = pmbuf->data_len; wlan_wmm_add_buf_txqueue(pmadapter, newbuf); if (pmadapter->pending_bridge_pkts > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); } } else { if (wlan_get_station_entry(priv, prx_pkt->eth803_hdr.dest_addr)) { /* Intra BSS packet */ if ((newbuf = wlan_alloc_mlan_buffer(pmadapter, MLAN_TX_DATA_BUF_SIZE_2K, 0, MTRUE))) { 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); pmadapter->pending_bridge_pkts++; newbuf->flags |= MLAN_BUF_FLAG_BRIDGE_BUF; /* copy the data */ memcpy(pmadapter, (t_u8 *) newbuf->pbuf + newbuf->data_offset, pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); newbuf->data_len = pmbuf->data_len; wlan_wmm_add_buf_txqueue(pmadapter, newbuf); if (pmadapter->pending_bridge_pkts > RX_HIGH_THRESHOLD) wlan_drop_tx_pkts(priv); } goto done; } } upload: /** send packet to moal */ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); done: LEAVE(); return ret; }
/** * @brief This function allocates buffer for the members of adapter * structure like command buffer and BSSID list. * * @param pmadapter A pointer to mlan_adapter structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_allocate_adapter(pmlan_adapter pmadapter) { int i; mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef STA_SUPPORT t_u32 buf_size; BSSDescriptor_t *ptemp_scan_table = MNULL; #endif ENTER(); #ifdef STA_SUPPORT /* Allocate buffer to store the BSSID list */ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, MLAN_MEM_DEF, (t_u8 **) & ptemp_scan_table); if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { PRINTM(MERROR, "Failed to allocate scan table\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->pscan_table = ptemp_scan_table; #endif /* Initialize cmd_free_q */ util_init_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->cmd_free_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Initialize cmd_pending_q */ util_init_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Initialize scan_pending_q */ util_init_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->scan_pending_q, MTRUE, pmadapter->callbacks.moal_init_lock); /* Allocate command buffer */ ret = wlan_alloc_cmd_buffer(pmadapter); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate command buffer\n"); LEAVE(); return MLAN_STATUS_FAILURE; } for (i = 0; i < MLAN_MAX_BSS_NUM; ++i) { util_init_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->bssprio_tbl[i].bssprio_head, MTRUE, pmadapter->callbacks.moal_init_lock); pmadapter->bssprio_tbl[i].bssprio_cur = MNULL; } ret = pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, MAX_MP_REGS + HEADER_ALIGNMENT, MLAN_MEM_DEF | MLAN_MEM_DMA, (t_u8 **) & pmadapter->mp_regs_buf); if (ret != MLAN_STATUS_SUCCESS || !pmadapter->mp_regs_buf) { PRINTM(MERROR, "Failed to allocate mp_regs_buf\n"); LEAVE(); return MLAN_STATUS_FAILURE; } pmadapter->mp_regs = (t_u8 *) ALIGN_ADDR(pmadapter->mp_regs_buf, HEADER_ALIGNMENT); #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) ret = wlan_alloc_sdio_mpa_buffers(pmadapter, SDIO_MP_TX_AGGR_DEF_BUF_SIZE, SDIO_MP_RX_AGGR_DEF_BUF_SIZE); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to allocate sdio mp-a buffers\n"); LEAVE(); return MLAN_STATUS_FAILURE; } #endif pmadapter->psleep_cfm = wlan_alloc_mlan_buffer(pmadapter, sizeof(opt_sleep_confirm_buffer), 0, MTRUE); LEAVE(); return MLAN_STATUS_SUCCESS; }