Ejemplo n.º 1
0
/**
 *  @brief Transmit the By-passed packet awaiting in by-pass queue
 *
 *  @param pmadapter Pointer to the mlan_adapter driver data struct
 *
 *  @return        N/A
 */
t_void
wlan_process_bypass_tx(pmlan_adapter pmadapter)
{
    pmlan_buffer pmbuf;
    mlan_tx_param tx_param;
    mlan_status status = MLAN_STATUS_SUCCESS;

    ENTER();

    if ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle,
                                                  &pmadapter->bypass_txq,
                                                  pmadapter->callbacks.
                                                  moal_spin_lock,
                                                  pmadapter->callbacks.
                                                  moal_spin_unlock))) {
        PRINTM(MINFO, "Dequeuing bypassed packet %p\n", pmbuf);
        /* XXX: nex_pkt_len ??? */
        tx_param.next_pkt_len = 0;
        status =
            wlan_process_tx(pmadapter->priv[pmbuf->bss_num], pmbuf, &tx_param);

        if (status == MLAN_STATUS_RESOURCE) {
            /* Queue the packet again so that it will be TX'ed later */
            util_enqueue_list_head(pmadapter->pmoal_handle,
                                   &pmadapter->bypass_txq,
                                   (pmlan_linked_list) pmbuf,
                                   pmadapter->callbacks.moal_spin_lock,
                                   pmadapter->callbacks.moal_spin_unlock);
        }
    } else {
        PRINTM(MINFO, "Nothing to send\n");
    }

    LEAVE();
}
/** 
 *  @brief This function gets a free command node if available in
 *              command free queue.
 *  
 *  @param pmadapter        A pointer to mlan_adapter structure
 *
 *  @return cmd_ctrl_node   A pointer to cmd_ctrl_node structure or MNULL
 */
cmd_ctrl_node *
wlan_get_cmd_node(mlan_adapter * pmadapter)
{
    cmd_ctrl_node *pcmd_node;

    ENTER();

    if (pmadapter == MNULL) {
        LEAVE();
        return MNULL;
    }

    if (util_peek_list(&pmadapter->cmd_free_q,
                       pmadapter->callbacks.moal_spin_lock,
                       pmadapter->callbacks.moal_spin_unlock)) {
        pcmd_node = (cmd_ctrl_node *) util_dequeue_list(&pmadapter->cmd_free_q,
                                                        pmadapter->callbacks.
                                                        moal_spin_lock,
                                                        pmadapter->callbacks.
                                                        moal_spin_unlock);
    } else {
        PRINTM(MERROR, "GET_CMD_NODE: cmd_ctrl_node is not available\n");
        pcmd_node = MNULL;
    }

    LEAVE();
    return pcmd_node;
}
/**
 *  @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 The main process
 *
 *  @param pmlan_adapter	A pointer to mlan_adapter structure
 *
 *  @return			MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
mlan_status
mlan_rx_process(IN t_void * pmlan_adapter)
{
    mlan_status ret = MLAN_STATUS_SUCCESS;
    mlan_adapter *pmadapter = (mlan_adapter *) pmlan_adapter;
    pmlan_callbacks pcb;
    pmlan_buffer pmbuf;

    ENTER();

    MASSERT(pmlan_adapter);
    pcb = &pmadapter->callbacks;
    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
    if (pmadapter->mlan_rx_processing || pmadapter->rx_lock_flag) {
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->prx_proc_lock);
        goto exit_rx_proc;
    } else {
        pmadapter->mlan_rx_processing = MTRUE;
        pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                              pmadapter->prx_proc_lock);
    }
    /* Check for Rx data */
    while ((pmbuf =
                (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle,
                        &pmadapter->rx_data_queue,
                        pmadapter->callbacks.
                        moal_spin_lock,
                        pmadapter->callbacks.
                        moal_spin_unlock))) {
        util_scalar_decrement(pmadapter->pmoal_handle,
                              &pmadapter->rx_pkts_queued,
                              pmadapter->callbacks.moal_spin_lock,
                              pmadapter->callbacks.moal_spin_unlock);
        if (pmadapter->delay_task_flag &&
                (util_scalar_read
                 (pmadapter->pmoal_handle, &pmadapter->rx_pkts_queued,
                  pmadapter->callbacks.moal_spin_lock,
                  pmadapter->callbacks.moal_spin_unlock) <
                 LOW_RX_PENDING)) {
            PRINTM(MEVENT, "Run\n");
            pmadapter->delay_task_flag = MFALSE;
            wlan_recv_event(wlan_get_priv
                            (pmadapter, MLAN_BSS_ROLE_ANY),
                            MLAN_EVENT_ID_DRV_DEFER_HANDLING,
                            MNULL);
        }
        wlan_handle_rx_packet(pmadapter, pmbuf);
    }
    pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->prx_proc_lock);
    pmadapter->mlan_rx_processing = MFALSE;
    pcb->moal_spin_unlock(pmadapter->pmoal_handle,
                          pmadapter->prx_proc_lock);
exit_rx_proc:
    LEAVE();
    return ret;
}
Ejemplo n.º 5
0
/**
 *  @brief Transmit the By-passed packet awaiting in by-pass queue
 *
 *  @param pmadapter Pointer to the mlan_adapter driver data struct
 *
 *  @return        N/A
 */
t_void
wlan_process_bypass_tx(pmlan_adapter pmadapter)
{
	pmlan_buffer pmbuf;
	mlan_tx_param tx_param;
	mlan_status status = MLAN_STATUS_SUCCESS;
	pmlan_private priv;
	int j = 0;
	ENTER();
	for (j = 0; j < pmadapter->priv_num; ++j) {
		priv = pmadapter->priv[j];
		if (priv) {
			pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->
								 pmoal_handle,
								 &priv->
								 bypass_txq,
								 pmadapter->
								 callbacks.
								 moal_spin_lock,
								 pmadapter->
								 callbacks.
								 moal_spin_unlock);
			if (pmbuf) {
				PRINTM(MINFO, "Dequeuing bypassed packet %p\n",
				       pmbuf);
				/* XXX: nex_pkt_len ??? */
				tx_param.next_pkt_len = 0;
				status = wlan_process_tx(pmadapter->
							 priv[pmbuf->bss_index],
							 pmbuf, &tx_param);

				if (status == MLAN_STATUS_RESOURCE) {
					/* Queue the packet again so that it
					   will be TX'ed later */
					util_enqueue_list_head(pmadapter->
							       pmoal_handle,
							       &priv->
							       bypass_txq,
							       (pmlan_linked_list)
							       pmbuf,
							       pmadapter->
							       callbacks.
							       moal_spin_lock,
							       pmadapter->
							       callbacks.
							       moal_spin_unlock);
				} else {
					pmadapter->callbacks.
						moal_spin_lock(pmadapter->
							       pmoal_handle,
							       priv->bypass_txq.
							       plock);
					pmadapter->bypass_pkt_count--;
					pmadapter->callbacks.
						moal_spin_unlock(pmadapter->
								 pmoal_handle,
								 priv->
								 bypass_txq.
								 plock);
				}
				break;
			} else {
				PRINTM(MINFO, "Nothing to send\n");
			}
		}
	}
	LEAVE();
}
/**
 *  @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;
}