/**
 *  @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.º 2
0
/** 
 *  @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 or MLAN_STATUS_FAILURE
 */
mlan_status
wlan_decode_rx_packet(mlan_adapter * pmadapter, mlan_buffer * pmbuf,
                      t_u32 upld_typ)
{
    t_u8 *cmdBuf;
    t_u32 event;

    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;
        wlan_handle_rx_packet(pmadapter, pmbuf);
        break;

    case MLAN_TYPE_CMD:
        PRINTM(MINFO, "--- Rx: Cmd Response ---\n");
        DBG_HEXDUMP(MDAT_D, "Cmd RESP BUFFER", pmbuf->pbuf + pmbuf->data_offset,
                    pmadapter->upld_len);
        /* 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 -= INTF_HEADER_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;
    }
    return MLAN_STATUS_SUCCESS;
}