/**
 *  @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;
}
Beispiel #4
0
/**
 *  @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;
}
Beispiel #8
0
/**
 *  @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;
}
Beispiel #10
0
/**
 *   @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);
}
Beispiel #11
0
/**
 *  @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;
}
Beispiel #12
0
/**
 *  @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;
}
Beispiel #15
0
/** 
 *  @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);
}
Beispiel #19
0
/**
 *  @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;
}
Beispiel #20
0
/**
 *   @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);
}
Beispiel #22
0
/**
 *  @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;
}