/** * @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 queues the command to cmd list. * * @param pmadapter A pointer to mlan_adapter structure * @param pcmd_node A pointer to cmd_ctrl_node structure * @param add_tail Specify if the cmd needs to be queued in the header or tail * * @return N/A */ t_void wlan_insert_cmd_to_pending_q(IN mlan_adapter * pmadapter, IN cmd_ctrl_node * pcmd_node, IN t_u32 add_tail) { HostCmd_DS_COMMAND *pcmd = MNULL; t_u16 command; ENTER(); if (pcmd_node == MNULL) { PRINTM(MERROR, "QUEUE_CMD: pcmd_node is MNULL\n"); goto done; } pcmd = (HostCmd_DS_COMMAND *) (pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset); if (pcmd == MNULL) { PRINTM(MERROR, "QUEUE_CMD: pcmd is MNULL\n"); goto done; } command = wlan_le16_to_cpu(pcmd->command); /* Exit_PS command needs to be queued in the header always. */ if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { HostCmd_DS_802_11_PS_MODE_ENH *pm = &pcmd->params.psmode_enh; if (wlan_le16_to_cpu(pm->action) == DIS_PS) { if (pmadapter->ps_state != PS_STATE_AWAKE) add_tail = MFALSE; } } if (add_tail) { util_enqueue_list_tail(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); } else { util_enqueue_list_head(&pmadapter->cmd_pending_q, (pmlan_linked_list) pcmd_node, pmadapter->callbacks.moal_spin_lock, pmadapter->callbacks.moal_spin_unlock); } PRINTM(MCMND, "QUEUE_CMD: cmd=0x%x is queued\n", command); done: LEAVE(); return; }
/** * @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; }