Пример #1
0
/*
 * Description
 *	Transmit xmitframe from queue
 *
 * Return
 *	_SUCCESS	ok
 *	_FAIL		something error
 */
s32 rtl8723bs_xmit_handler(PADAPTER padapter)
{
    struct xmit_priv *pxmitpriv;
    s32 ret;
    _irqL irql;


    pxmitpriv = &padapter->xmitpriv;

wait:
    ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
    if (_FAIL == ret) {
        DBG_871X_LEVEL(_drv_emerg_, "%s: down sema fail!\n", __FUNCTION__);
        return _FAIL;
    }

next:
    if ((padapter->bDriverStopped == _TRUE) ||
            (padapter->bSurpriseRemoved == _TRUE)) {
        RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
                 ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
                  __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved));
        return _FAIL;
    }

    _enter_critical_bh(&pxmitpriv->lock, &irql);
    ret = rtw_txframes_pending(padapter);
    _exit_critical_bh(&pxmitpriv->lock, &irql);
    if (ret == 0) {
        if(!padapter->registrypriv.wifi_spec)
            rtw_yield_os();
        return _SUCCESS;
    }

    // dequeue frame and write to hardware

    ret = xmit_xmitframes(padapter, pxmitpriv);
    if (ret == -2) {
        //here sleep 1ms will cause big TP loss of TX
        //from 50+ to 40+
        if(padapter->registrypriv.wifi_spec)
            rtw_msleep_os(1);
        else
            rtw_yield_os();
        goto next;
    }

    _enter_critical_bh(&pxmitpriv->lock, &irql);
    ret = rtw_txframes_pending(padapter);
    _exit_critical_bh(&pxmitpriv->lock, &irql);
    if (ret == 1) {
        //rtw_msleep_os(1);
        goto next;
    }

    return _SUCCESS;
}
Пример #2
0
/*
 * Description:
 *	Aggregation packets and send to hardware
 *
 * Return:
 *	0	Success
 *	-1	Hardware resource(TX FIFO) not ready
 *	-2	Software resource(xmitbuf) not ready
 */
static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv)
{
    s32 err, ret;
    u32 k=0;
    struct hw_xmit *hwxmits, *phwxmit;
    u8 no_res, idx, hwentry;
    _irqL irql;
    struct tx_servq *ptxservq;
    _list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
    struct xmit_frame *pxmitframe;
    _queue *pframe_queue;
    struct xmit_buf *pxmitbuf;
    u32 txlen;
    u8 txdesc_size = TXDESC_SIZE;
    int inx[4];

    err = 0;
    no_res = _FALSE;
    hwxmits = pxmitpriv->hwxmits;
    hwentry = pxmitpriv->hwxmit_entry;
    ptxservq = NULL;
    pxmitframe = NULL;
    pframe_queue = NULL;
    pxmitbuf = NULL;

    if (padapter->registrypriv.wifi_spec == 1) {
        for(idx=0; idx<4; idx++)
            inx[idx] = pxmitpriv->wmm_para_seq[idx];
    } else {
        inx[0] = 0;
        inx[1] = 1;
        inx[2] = 2;
        inx[3] = 3;
    }

    // 0(VO), 1(VI), 2(BE), 3(BK)
    for (idx = 0; idx < hwentry; idx++)
    {
        phwxmit = hwxmits + inx[idx];

        if((check_pending_xmitbuf(pxmitpriv) == _TRUE) && (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
            if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
                err = -2;
                break;
            }
        }

        _enter_critical_bh(&pxmitpriv->lock, &irql);

        sta_phead = get_list_head(phwxmit->sta_queue);
        sta_plist = get_next(sta_phead);
        //because stop_sta_xmit may delete sta_plist at any time
        //so we should add lock here, or while loop can not exit
        while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE)
        {
            ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
            sta_plist = get_next(sta_plist);

#ifdef DBG_XMIT_BUF
            DBG_871X("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __func__, idx, phwxmit->accnt, ptxservq->qcnt);
            DBG_871X("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d \n",
                     __func__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
                     pxmitpriv->free_xmitframe_cnt);
#endif
            pframe_queue = &ptxservq->sta_pending;

            frame_phead = get_list_head(pframe_queue);

            while (rtw_is_list_empty(frame_phead) == _FALSE)
            {
                frame_plist = get_next(frame_phead);
                pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);

                // check xmit_buf size enough or not
                txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
                if ((NULL == pxmitbuf) ||
                        ((pxmitbuf->ptail + txlen) > pxmitbuf->pend)
#ifdef SDIO_TX_AGG_MAX
                        || (k >= SDIO_TX_AGG_MAX)
#endif
                   )
                {
                    if (pxmitbuf)
                    {
                        //pxmitbuf->priv_data will be NULL, and will crash here
                        if (pxmitbuf->len > 0 && pxmitbuf->priv_data)
                        {
                            struct xmit_frame *pframe;
                            pframe = (struct xmit_frame*)pxmitbuf->priv_data;
                            pframe->agg_num = k;
                            pxmitbuf->agg_num = k;
                            rtl8723b_update_txdesc(pframe, pframe->buf_addr);
                            rtw_free_xmitframe(pxmitpriv, pframe);
                            pxmitbuf->priv_data = NULL;
                            enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
                            //can not yield under lock
                            //rtw_yield_os();
                        } else {
                            rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
                        }
                    }

                    pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
                    if (pxmitbuf == NULL) {
#ifdef DBG_XMIT_BUF
                        DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __FUNCTION__);
#endif
                        err = -2;
                        break;
                    }
                    k = 0;
                }

                // ok to send, remove frame from queue
#ifdef CONFIG_AP_MODE
                if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
                    if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
                            (pxmitframe->attrib.triggered == 0)) {
                        DBG_871X("%s: one not triggered pkt in queue when this STA sleep,"
                                 " break and goto next sta\n", __func__);
                        break;
                    }
                }
#endif
                rtw_list_delete(&pxmitframe->list);
                ptxservq->qcnt--;
                phwxmit->accnt--;

                if (k == 0) {
                    pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
                    pxmitbuf->priv_data = (u8*)pxmitframe;
                }

                // coalesce the xmitframe to xmitbuf
                pxmitframe->pxmitbuf = pxmitbuf;
                pxmitframe->buf_addr = pxmitbuf->ptail;

                ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
                if (ret == _FAIL) {
                    DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __FUNCTION__);
                    // Todo: error handler
                } else {
                    k++;
                    if (k != 1)
                        rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
                    rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);

                    txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
                    pxmitframe->pg_num = (txlen + 127)/128;
                    pxmitbuf->pg_num += (txlen + 127)/128;
                    //if (k != 1)
                    //	((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num;
                    pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment
                    pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
                }

                if (k != 1)
                    rtw_free_xmitframe(pxmitpriv, pxmitframe);
                pxmitframe = NULL;
            }

            if (_rtw_queue_empty(pframe_queue) == _TRUE)
                rtw_list_delete(&ptxservq->tx_pending);

            if (err) break;
        }
        _exit_critical_bh(&pxmitpriv->lock, &irql);

        // dump xmit_buf to hw tx fifo
        if (pxmitbuf)
        {
            RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len));

            if (pxmitbuf->len > 0) {
                struct xmit_frame *pframe;
                pframe = (struct xmit_frame*)pxmitbuf->priv_data;
                pframe->agg_num = k;
                pxmitbuf->agg_num = k;
                rtl8723b_update_txdesc(pframe, pframe->buf_addr);
                rtw_free_xmitframe(pxmitpriv, pframe);
                pxmitbuf->priv_data = NULL;
                enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
                rtw_yield_os();
            }
            else
                rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
            pxmitbuf = NULL;
        }

        if (err) break;
    }

    return err;
}
/*
 * Description:
 *	Aggregation packets and send to hardware
 *
 * Return:
 *	0	Success
 *	-1	Hardware resource(TX FIFO) not ready
 *	-2	Software resource(xmitbuf) not ready
 */
static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv)
{
	s32 err, ret;
	u32 k;
	struct hw_xmit *hwxmits;
	u8 no_res, idx, hwentry;
	_irqL irql;
//	_irqL irqL0, irqL1;
	struct tx_servq *ptxservq;
	_list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
	struct xmit_frame *pxmitframe;
	_queue *pframe_queue;
	struct xmit_buf *pxmitbuf;
	u32 txlen;


	err = 0;
	no_res = _FALSE;
	hwxmits = pxmitpriv->hwxmits;
	hwentry = pxmitpriv->hwxmit_entry;
	ptxservq = NULL;
	pxmitframe = NULL;
	pframe_queue = NULL;
	pxmitbuf = NULL;

	// 0(VO), 1(VI), 2(BE), 3(BK)
	for (idx = 0; idx < hwentry; idx++, hwxmits++)
	{
//		_enter_critical(&hwxmits->sta_queue->lock, &irqL0);
		_enter_critical_bh(&pxmitpriv->lock, &irql);

		sta_phead = get_list_head(hwxmits->sta_queue);
		sta_plist = get_next(sta_phead);

		while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE)
		{
			ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
			sta_plist = get_next(sta_plist);

			pframe_queue = &ptxservq->sta_pending;

//			_enter_critical(&pframe_queue->lock, &irqL1);
			//_enter_critical_bh(&pxmitpriv->lock, &irql);

			frame_phead = get_list_head(pframe_queue);

			while (rtw_is_list_empty(frame_phead) == _FALSE)
			{
				frame_plist = get_next(frame_phead);
				pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);

				// check xmit_buf size enough or not
				txlen = TXDESC_SIZE + rtw_wlan_pkt_size(pxmitframe);
				if ((NULL == pxmitbuf) ||
					((pxmitbuf->ptail + txlen) > pxmitbuf->pend)
#ifdef SDIO_TX_AGG_MAX
					|| (k >= SDIO_TX_AGG_MAX)
#endif
					)
				{
					if (pxmitbuf) {
						struct xmit_frame *pframe;
						pframe = (struct xmit_frame*)pxmitbuf->priv_data;
						pframe->agg_num = k;
						pxmitbuf->agg_num = k;
						rtl8723a_update_txdesc(pframe, pframe->buf_addr);
						rtw_free_xmitframe(pxmitpriv, pframe);
						pxmitbuf->priv_data = NULL;
						enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
						//rtw_yield_os();
					}

					pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
					if (pxmitbuf == NULL) {
						RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: xmit_buf is not enough!\n", __FUNCTION__));
						err = -2;
						break;
					}
					k = 0;
				}

				// ok to send, remove frame from queue
				//_enter_critical_bh(&pxmitpriv->lock, &irql);
#ifdef CONFIG_AP_MODE
				if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
				{
					if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
						(pxmitframe->attrib.triggered == 0))
					{
						//_exit_critical_bh(&pxmitpriv->lock, &irql);
						
						DBG_8192C("%s: one not triggered pkt in queue when STA sleep\n", __func__);
						break;
					}
				}
#endif
				rtw_list_delete(&pxmitframe->list);
				ptxservq->qcnt--;
				hwxmits->accnt--;
				

				if (k == 0) {
					pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
					pxmitbuf->priv_data = (u8*)pxmitframe;
				}

				// coalesce the xmitframe to xmitbuf
				pxmitframe->pxmitbuf = pxmitbuf;
				pxmitframe->buf_addr = pxmitbuf->ptail;

				ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
				if (ret == _FAIL) {
					RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: coalesce FAIL!", __FUNCTION__));
					// Todo: error handler
					DBG_871X("%s: coalesce FAIL!", __FUNCTION__);
				} else {
					k++;
					if (k != 1)
						rtl8723a_update_txdesc(pxmitframe, pxmitframe->buf_addr);
					rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);

					txlen = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
					pxmitframe->pg_num = (txlen + 127)/128;
					pxmitbuf->pg_num += (txlen + 127)/128;					
					//if (k != 1)
					//	((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num;
					pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment
					pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
				}

				if (k != 1)
					rtw_free_xmitframe(pxmitpriv, pxmitframe);
				pxmitframe = NULL;
			}

			//_enter_critical_bh(&pxmitpriv->lock, &irql);
			if (_rtw_queue_empty(pframe_queue) == _TRUE)
				rtw_list_delete(&ptxservq->tx_pending);
			//_exit_critical_bh(&pxmitpriv->lock, &irql);

//			_exit_critical(&pframe_queue->lock, &irqL1);
			//_exit_critical_bh(&pxmitpriv->lock, &irql);

			if (err) break;
		}

//		_exit_critical(&hwxmits->sta_queue->lock, &irqL0);
		_exit_critical_bh(&pxmitpriv->lock, &irql);

		// dump xmit_buf to hw tx fifo
		if (pxmitbuf)
		{
			RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len));

			if (pxmitbuf->len > 0) {
				struct xmit_frame *pframe;
				pframe = (struct xmit_frame*)pxmitbuf->priv_data;
				pframe->agg_num = k;
				pxmitbuf->agg_num = k;
				rtl8723a_update_txdesc(pframe, pframe->buf_addr);
				rtw_free_xmitframe(pxmitpriv, pframe);
				pxmitbuf->priv_data = NULL;
				enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
				rtw_yield_os();
			}
			else
				rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
			
			pxmitbuf = NULL;
		}

		if (err) break;
	}

	return err;
}
Пример #4
0
static u8 rtl8188es_query_tx_freepage(_adapter *padapter, struct xmit_buf *pxmitbuf)
{
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
	u8	TxRequiredPageNum = 0;
	u8	DedicatedPgNum = 0;
	u8	RequiredPublicFreePgNum = 0;
	u8	PageIdx = 0;
	u8	bResult = _TRUE;
	u32	n, deviceId;

	TxRequiredPageNum = pxmitbuf->pg_num;

	deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);

	// translate fifo addr to queue index
	switch (deviceId) {
		case WLAN_TX_HIQ_DEVICE_ID:
				PageIdx = HI_QUEUE_IDX;
				break;

		case WLAN_TX_MIQ_DEVICE_ID:
				PageIdx = MID_QUEUE_IDX;
				break;

		case WLAN_TX_LOQ_DEVICE_ID:
				PageIdx = LOW_QUEUE_IDX;
				break;
	}

	// check if hardware tx fifo page is enough
	n = 0;
	do {
		if ((padapter->bSurpriseRemoved == _TRUE) || (padapter->bDriverStopped == _TRUE)){
			RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
				 ("%s: bSurpriseRemoved(update TX FIFO page)\n", __FUNCTION__));
			break;
		}

		// The number of page which public page is included is available .
		if ((pHalData->SdioTxFIFOFreePage[PageIdx]+pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) > (TxRequiredPageNum+1)) {
			DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx];
			if (TxRequiredPageNum <= DedicatedPgNum) {
				pHalData->SdioTxFIFOFreePage[PageIdx] -= TxRequiredPageNum;
				break;
			} else {
				pHalData->SdioTxFIFOFreePage[PageIdx] = 0;
				RequiredPublicFreePgNum = TxRequiredPageNum - DedicatedPgNum;
				pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum;
				break;
			}
		}

		n++;
		if ((n % 60) == 0) {//or 80
			//DBG_871X("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n",
			//	__func__, n, pxmitbuf->len, pxmitbuf->agg_num, pframe->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]);
			rtw_msleep_os(10);
			rtw_yield_os();
		}

		// Total number of page is NOT available, so update current FIFO status
		HalQueryTxBufferStatus8189ESdio(padapter);
	} while (1);

	return bResult;
}
Пример #5
0
void rtl8188e_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus)
{
	JOINBSSRPT_PARM_88E	JoinBssRptParm;
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
#ifdef CONFIG_WOWLAN
	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
	struct sta_info *psta = NULL;
#endif
	BOOLEAN		bSendBeacon=_FALSE;
	BOOLEAN		bcn_valid = _FALSE;
	u8	DLBcnCount=0;
	u32 poll = 0;

_func_enter_;

	DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);

	if(mstatus == 1)
	{
		// We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
		// Suggested by filen. Added by tynli.
		rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
		// Do not set TSF again here or vWiFi beacon DMA INT will not work.
		//correct_TSF(padapter, pmlmeext);
		// Hw sequende enable by dedault. 2010.06.23. by tynli.
		//rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));
		//rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);

		//Set REG_CR bit 8. DMA beacon by SW.
		pHalData->RegCR_1 |= BIT0;
		rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);

		// Disable Hw protection for a time which revserd for Hw sending beacon.
		// Fix download reserved page packet fail that access collision with the protection time.
		// 2010.05.11. Added by tynli.
		//SetBcnCtrlReg(padapter, 0, BIT3);
		//SetBcnCtrlReg(padapter, BIT4, 0);
		rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));
		rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));

		if(pHalData->RegFwHwTxQCtrl&BIT6)
		{
			DBG_871X("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
			bSendBeacon = _TRUE;
		}

		// Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
		rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));
		pHalData->RegFwHwTxQCtrl &= (~BIT6);

		// Clear beacon valid check bit.
		rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
		DLBcnCount = 0;
		poll = 0;
		do
		{
			// download rsvd page.
			SetFwRsvdPagePkt(padapter, _FALSE);
			DLBcnCount++;
			do
			{
				rtw_yield_os();
				//rtw_mdelay_os(10);
				// check rsvd page download OK.
				rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));
				poll++;
			} while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);

		}while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);

		//RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage88ES(): 1 Download RSVD page failed!\n"));
		if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
		{
		}
		else if(!bcn_valid)
			DBG_871X(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",
				ADPT_ARG(padapter) ,DLBcnCount, poll);
		else {
			struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
			pwrctl->fw_psmode_iface_id = padapter->iface_id;
			DBG_871X(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",
				ADPT_ARG(padapter), DLBcnCount, poll);
		}
		//
		// We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower)
		// becuase we need to free the Tx BCN Desc which is used by the first reserved page packet.
		// At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return
		// the beacon TCB in the following code. 2011.11.23. by tynli.
		//
		//if(bcn_valid && padapter->bEnterPnpSleep)
		if(0)
		{
			if(bSendBeacon)
			{
				rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
				DLBcnCount = 0;
				poll = 0;
				do
				{
					SetFwRsvdPagePkt(padapter, _TRUE);
					DLBcnCount++;

					do
					{
						rtw_yield_os();
						//rtw_mdelay_os(10);
						// check rsvd page download OK.
						rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));
						poll++;
					} while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
				}while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);

				//RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage(): 2 Download RSVD page failed!\n"));
				if(padapter->bSurpriseRemoved || padapter->bDriverStopped)
				{
				}
				else if(!bcn_valid)
					DBG_871X("%s: 2 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __FUNCTION__ ,DLBcnCount, poll);
				else
					DBG_871X("%s: 2 Download RSVD success! DLBcnCount:%u, poll:%u\n", __FUNCTION__, DLBcnCount, poll);
			}
		}

		// Enable Bcn
		//SetBcnCtrlReg(padapter, BIT3, 0);
		//SetBcnCtrlReg(padapter, 0, BIT4);
		rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));
		rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));

		// To make sure that if there exists an adapter which would like to send beacon.
		// If exists, the origianl value of 0x422[6] will be 1, we should check this to
		// prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
		// the beacon cannot be sent by HW.
		// 2010.06.23. Added by tynli.
		if(bSendBeacon)
		{
			rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));
			pHalData->RegFwHwTxQCtrl |= BIT6;
		}

		//
		// Update RSVD page location H2C to Fw.
		//
		if(bcn_valid)
		{
			rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
			DBG_871X("Set RSVD page location to Fw.\n");
			//FillH2CCmd88E(Adapter, H2C_88E_RSVDPAGE, H2C_RSVDPAGE_LOC_LENGTH, pMgntInfo->u1RsvdPageLoc);
		}

		// Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.
		//if(!padapter->bEnterPnpSleep)
		{
			// Clear CR[8] or beacon packet will not be send to TxBuf anymore.
			pHalData->RegCR_1 &= (~BIT0);
			rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);
		}
	}
#ifdef CONFIG_WOWLAN
	if (adapter_to_pwrctl(padapter)->wowlan_mode){
		JoinBssRptParm.OpMode = mstatus;
		psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(pmlmepriv));
		if (psta != NULL) {
			JoinBssRptParm.MacID = psta->mac_id;
		} else {
			JoinBssRptParm.MacID = 0;
		}
		FillH2CCmd_88E(padapter, H2C_COM_MEDIA_STATUS_RPT, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
		DBG_871X_LEVEL(_drv_info_, "%s opmode:%d MacId:%d\n", __func__, JoinBssRptParm.OpMode, JoinBssRptParm.MacID);
	} else {
		DBG_871X_LEVEL(_drv_info_, "%s wowlan_mode is off\n", __func__);
	}
#endif //CONFIG_WOWLAN
_func_exit_;
}
Пример #6
0
static u8 rtl8188es_query_tx_freepage(_adapter *padapter, struct xmit_buf *pxmitbuf)
{
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
	u8	TxRequiredPageNum = 0;
	u8	DedicatedPgNum = 0;
	u8	RequiredPublicFreePgNum = 0;
	u8	PageIdx = 0;
	u8	bResult = _TRUE;
	u32	n, deviceId;

	TxRequiredPageNum = pxmitbuf->pg_num;

	deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);

	// translate fifo addr to queue index
	switch (deviceId) {
		case WLAN_TX_HIQ_DEVICE_ID:
				PageIdx = HI_QUEUE_IDX;
				break;

		case WLAN_TX_MIQ_DEVICE_ID:
				PageIdx = MID_QUEUE_IDX;
				break;

		case WLAN_TX_LOQ_DEVICE_ID:
				PageIdx = LOW_QUEUE_IDX;
				break;
	}

	// check if hardware tx fifo page is enough
	n = 0;
	do {
		if (
			(padapter->bSurpriseRemoved == _TRUE) || (padapter->bDriverStopped == _TRUE)

#ifdef CONFIG_CONCURRENT_MODE
		||((padapter->pbuddy_adapter) 
		&& ((padapter->pbuddy_adapter->bSurpriseRemoved) ||(padapter->pbuddy_adapter->bDriverStopped)))
#endif
		){
			RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
				 ("%s: bSurpriseRemoved(update TX FIFO page)\n", __FUNCTION__));
			break;
		}
		
		
		// The number of page which public page is included is available .
		if ((pHalData->SdioTxFIFOFreePage[PageIdx]+pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]) > (TxRequiredPageNum+1)) {
			DedicatedPgNum = pHalData->SdioTxFIFOFreePage[PageIdx];
			if (TxRequiredPageNum <= DedicatedPgNum) {
				pHalData->SdioTxFIFOFreePage[PageIdx] -= TxRequiredPageNum;
				break;
			} else {
				pHalData->SdioTxFIFOFreePage[PageIdx] = 0;
				RequiredPublicFreePgNum = TxRequiredPageNum - DedicatedPgNum;
				pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] -= RequiredPublicFreePgNum;
				break;
			}
		}

		n++;

#if 0
		if (n >= 5000)
		{
			u8 reg_value_1 = 0;
			u8 reg_value_2 = 0;
			u8 reg_value_3 = 0;
			
			//try to recover the transmission
			reg_value_1 = rtw_read8(padapter, REG_SYS_FUNC_EN);
			reg_value_2 = rtw_read8(padapter, REG_CR);
			reg_value_3 = rtw_read8(padapter, REG_TXPAUSE);
			DBG_871X("Before recovery: REG_SYS_FUNC_EN = 0x%X, REG_CR = 0x%X, REG_TXPAUSE = 0x%X\n", reg_value_1, reg_value_2, reg_value_3);

			rtw_write8(padapter, REG_SYS_FUNC_EN, reg_value_1 | 0x01);
			rtw_write8(padapter, REG_CR, reg_value_2 | 0xC0);
			rtw_write8(padapter, REG_TXPAUSE, 0);
			DBG_871X("After recovery: REG_SYS_FUNC_EN = 0x%X, REG_CR = 0x%X, REG_TXPAUSE = 0x%X\n", 
				rtw_read8(padapter, REG_SYS_FUNC_EN), rtw_read8(padapter, REG_CR), rtw_read8(padapter, REG_TXPAUSE));
		}
#endif	

		if ((n % 60) == 0) {//or 80
			//DBG_871X("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n",
			//	__func__, n, pxmitbuf->len, pxmitbuf->agg_num, pframe->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]);
			rtw_msleep_os(10);
			rtw_yield_os();
		}

		// Total number of page is NOT available, so update current FIFO status
		HalQueryTxBufferStatus8189ESdio(padapter);
	} while (1);

	return bResult;
}