/** * @brief Add TxPD to AMSDU header * * @param priv A pointer to mlan_private structure * @param mbuf Pointer to buffer where the TxPD will be formed * * @return N/A */ static void wlan_11n_form_amsdu_txpd(mlan_private * priv, mlan_buffer * mbuf) { TxPD *ptx_pd; mlan_adapter *pmadapter = priv->adapter; ENTER(); ptx_pd = (TxPD *) mbuf->pbuf; memset(pmadapter, ptx_pd, 0, sizeof(TxPD)); /* * Original priority has been overwritten */ ptx_pd->priority = (t_u8) mbuf->priority; ptx_pd->pkt_delay_2ms = wlan_wmm_compute_driver_packet_delay(priv, mbuf); ptx_pd->bss_num = GET_BSS_NUM(priv); ptx_pd->bss_type = priv->bss_type; /* Always zero as the data is followed by TxPD */ ptx_pd->tx_pkt_offset = sizeof(TxPD); ptx_pd->tx_pkt_type = PKT_TYPE_AMSDU; if (mbuf->flags & MLAN_BUF_FLAG_TDLS) ptx_pd->flags = MRVDRV_TxPD_FLAGS_TDLS_PACKET; if (ptx_pd->tx_control == 0) /* TxCtrl set by user or default */ ptx_pd->tx_control = priv->pkt_tx_ctrl; endian_convert_TxPD(ptx_pd); LEAVE(); }
/** * @brief This function fill the txpd for tx packet * * @param priv A pointer to mlan_private structure * @param pmbuf A pointer to the mlan_buffer for process * * @return headptr or MNULL */ t_void * wlan_ops_sta_process_txpd(IN t_void * priv, IN pmlan_buffer pmbuf) { mlan_private *pmpriv = (mlan_private *) priv; pmlan_adapter pmadapter = pmpriv->adapter; TxPD *plocal_tx_pd; t_u8 *head_ptr = MNULL; ENTER(); if (!pmbuf->data_len) { PRINTM(MERROR, "STA Tx Error: Invalid packet length: %d\n", pmbuf->data_len); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; goto done; } if (pmbuf->data_offset < (sizeof(TxPD) + INTF_HEADER_LEN + DMA_ALIGNMENT)) { PRINTM(MERROR, "not enough space for TxPD: %d\n", pmbuf->data_len); pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; goto done; } /* head_ptr should be aligned */ head_ptr = pmbuf->pbuf + pmbuf->data_offset - sizeof(TxPD) - INTF_HEADER_LEN; head_ptr = (t_u8 *) ((t_ptr) head_ptr & ~((t_ptr) (DMA_ALIGNMENT - 1))); plocal_tx_pd = (TxPD *) (head_ptr + INTF_HEADER_LEN); memset(pmadapter, plocal_tx_pd, 0, sizeof(TxPD)); /* Set the BSS number to TxPD */ plocal_tx_pd->bss_num = GET_BSS_NUM(pmpriv); plocal_tx_pd->bss_type = pmpriv->bss_type; plocal_tx_pd->tx_pkt_length = (t_u16) pmbuf->data_len; plocal_tx_pd->priority = (t_u8) pmbuf->priority; plocal_tx_pd->pkt_delay_2ms = wlan_wmm_compute_driver_packet_delay(pmpriv, pmbuf); if (plocal_tx_pd->priority < NELEMENTS(pmpriv->wmm.user_pri_pkt_tx_ctrl)) /* * Set the priority specific tx_control field, setting of 0 will * cause the default value to be used later in this function */ plocal_tx_pd->tx_control = pmpriv->wmm.user_pri_pkt_tx_ctrl[plocal_tx_pd->priority]; if (pmadapter->pps_uapsd_mode) { if (MTRUE == wlan_check_last_packet_indication(pmpriv)) { pmadapter->tx_lock_flag = MTRUE; plocal_tx_pd->flags = MRVDRV_TxPD_POWER_MGMT_LAST_PACKET; } } /* Offset of actual data */ plocal_tx_pd->tx_pkt_offset = (t_u16) ((t_ptr) pmbuf->pbuf + pmbuf->data_offset - (t_ptr) plocal_tx_pd); if (!plocal_tx_pd->tx_control) { /* TxCtrl set by user or default */ plocal_tx_pd->tx_control = pmpriv->pkt_tx_ctrl; } endian_convert_TxPD(plocal_tx_pd); /* Adjust the data offset and length to include TxPD in pmbuf */ pmbuf->data_len += pmbuf->data_offset; pmbuf->data_offset = (t_u32) (head_ptr - pmbuf->pbuf); pmbuf->data_len -= pmbuf->data_offset; done: LEAVE(); return head_ptr; }
/** * @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; }