Beispiel #1
0
static INT32 _stp_btm_put_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp)
{
	INT32 ret;

	if (!pOpQ || !pOp) {
		STP_BTM_WARN_FUNC("invalid input param: 0x%p, 0x%p\n", pOpQ, pOp);
		return 0;	/* ;MTK_WCN_BOOL_FALSE; */
	}

	ret = 0;

	osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
	/* acquire lock success */
	if (!RB_FULL(pOpQ))
		RB_PUT(pOpQ, pOp);
	else
		ret = -1;

	osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));

	if (ret) {
		STP_BTM_WARN_FUNC("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n",
			pOpQ,
			RB_COUNT(pOpQ),
			&stp_btm->rFreeOpQ,
			&stp_btm->rActiveOpQ);
		return 0;
	} else {
		/* STP_BTM_WARN_FUNC("RB_COUNT = %d\n",RB_COUNT(pOpQ)); */
		return 1;
	}
}
static P_OSAL_OP _stp_btm_get_op (
    MTKSTP_BTM_T *stp_btm,
    P_OSAL_OP_Q pOpQ
    )
{
    P_OSAL_OP pOp;
    INT32 ret = 0;

    if (!pOpQ) 
    {
        STP_BTM_WARN_FUNC("!pOpQ \n");
        return NULL;
    }
    
    osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
    if (ret) 
    {
        STP_BTM_WARN_FUNC("mutex_lock_interruptible (%d) \n", ret);
        return NULL;
    }

    /* acquire lock success */
    RB_GET(pOpQ, pOp);
    osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));

    if (!pOp) 
    {
        //STP_BTM_WARN_FUNC("RB_GET fail\n");
    }

    return pOp;
}
static inline INT32 _stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm){

    P_OSAL_OP       pOp;
    INT32           bRet;
    INT32 retval;

    if(stp_btm == NULL)
    {
        return STP_BTM_OPERATION_FAIL;
    }
    else 
    {
        pOp = _stp_btm_get_free_op(stp_btm);
        if (!pOp) 
        {
            STP_BTM_WARN_FUNC("get_free_lxop fail \n");
            return -1;//break;
        }
        pOp->op.opId = STP_OPID_BTM_RETRY;
        pOp->signal.timeoutValue= 0;
        bRet = _stp_btm_put_act_op(stp_btm, pOp);
        STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n",
            pOp->op.opId,
            pOp->op.au4OpData[0],
            bRet);
        retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS;
    }
    return retval;
}
Beispiel #4
0
static inline INT32 _stp_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm)
{

#if 0
	P_OSAL_OP pOp;
	INT32 bRet;
	INT32 retval;

	if (stp_btm == NULL) {
		return STP_BTM_OPERATION_FAIL;
	} else {
		pOp = _stp_btm_get_free_op(stp_btm);
		if (!pOp) {
			STP_BTM_WARN_FUNC("get_free_lxop fail\n");
			return -1;	/* break; */
		}
		pOp->op.opId = STP_OPID_BTM_FORCE_FW_ASSERT;
		pOp->signal.timeoutValue = 0;
		bRet = _stp_btm_put_act_op(stp_btm, pOp);
		STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet);
		retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS;
	}
	return retval;
#endif
	INT32 ret = -1;

	ret = _stp_trigger_firmware_assert_via_emi();

	return ret;

}
Beispiel #5
0
static P_OSAL_OP _stp_btm_get_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ)
{
	P_OSAL_OP pOp;
	/* INT32 ret = 0; */

	if (!pOpQ) {
		STP_BTM_WARN_FUNC("!pOpQ\n");
		return NULL;
	}

	osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
	/* acquire lock success */
	RB_GET(pOpQ, pOp);
	osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));

	if (!pOp)
		STP_BTM_WARN_FUNC("RB_GET fail\n");

	return pOp;
}
static inline INT32 _stp_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm){

#if 0
    P_OSAL_OP       pOp;
    INT32           bRet;
    INT32 retval;

    if(stp_btm == NULL)
    {
        return STP_BTM_OPERATION_FAIL;
    }
    else 
    {
        pOp = _stp_btm_get_free_op(stp_btm);
        if (!pOp) 
        {
            STP_BTM_WARN_FUNC("get_free_lxop fail \n");
            return -1;//break;
        }
        pOp->op.opId = STP_OPID_BTM_FORCE_FW_ASSERT;
        pOp->signal.timeoutValue= 0;
        bRet = _stp_btm_put_act_op(stp_btm, pOp);
        STP_BTM_DBG_FUNC("OPID(%d) type(%d) bRet(%d) \n\n",
            pOp->op.opId,
            pOp->op.au4OpData[0],
            bRet);
        retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS;
    }
    return retval;
#endif
	INT32 ret  = -1;

	ret = _stp_trigger_firmware_assert_via_emi();
#if 0
	if(0 != _stp_get_dump_info(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1))
	{
		STP_BTM_INFO_FUNC("EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 has not clear,reset it\n");
		_stp_set_dump_info(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1, 0x0);
	}
	else
	{
		STP_BTM_INFO_FUNC("EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 reset by fw side\n");
	}
#endif
	return ret;
	
}
Beispiel #7
0
static inline INT32 _stp_btm_dump_type(MTKSTP_BTM_T *stp_btm, ENUM_STP_BTM_OPID_T opid)
{
	P_OSAL_OP pOp;
	INT32 bRet;
	INT32 retval;

	pOp = _stp_btm_get_free_op(stp_btm);
	if (!pOp) {
		STP_BTM_WARN_FUNC("get_free_lxop fail\n");
		return -1;	/* break; */
	}

	pOp->op.opId = opid;
	pOp->signal.timeoutValue = 0;
	bRet = _stp_btm_put_act_op(stp_btm, pOp);
	STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet);
	retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS;

	return retval;
}
Beispiel #8
0
static INT32 stp_btm_dump_send_retry_handler(PINT8 tmp, INT32 len)
{
	if (NULL == tmp)
		return -1;
	INT32 rc = 0, nl_retry = 0;
	rc = stp_dbg_nl_send(tmp, 2, len+5);
	while (rc) {
		nl_retry++;
		if (rc == 32) {
			STP_BTM_ERR_FUNC("**dump send timeout : %d**\n", rc);
			return 1;
		}
		if (nl_retry > 1000) {
			STP_BTM_ERR_FUNC("**dump send fails, and retry more than 1000: %d.**\n", rc);
			return 2;
		}
		STP_BTM_WARN_FUNC("**dump send fails, and retry again.**\n");
		osal_sleep_ms(3);
		rc = stp_dbg_nl_send(tmp, 2, len+5);
		if (!rc)
			STP_BTM_DBG_FUNC("****retry again ok!**\n");
	}
	return rc;
}
static INT32 _stp_btm_put_dump_to_nl(void)
{
    #define NUM_FETCH_ENTRY 8   

    static UINT8  buf[2048];
    static UINT8  tmp[2048];

    UINT32  buf_len;       
    STP_PACKET_T  *pkt;
    STP_DBG_HDR_T *hdr;
    INT32  remain=0, index =0;
    INT32 retry = 0, rc = 0, nl_retry = 0;
    STP_BTM_INFO_FUNC("Enter..\n");
  
    index = 0;
    tmp[index++]='[';
    tmp[index++]='M';
    tmp[index++]=']'; 

    do
    {
        index = 3;
        remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len);
        if (buf_len > 0)
        {
            pkt = (STP_PACKET_T  *)buf;
            hdr = &pkt->hdr;
            if (hdr->dbg_type == STP_DBG_FW_DMP){
                memcpy(&tmp[index], pkt->raw, pkt->hdr.len);

                if(pkt->hdr.len <= 1500)
                {
                    tmp[index + pkt->hdr.len] = '\n';
                    tmp[index + pkt->hdr.len + 1] = '\0';

                    //printk("\n%s\n+++\n", tmp);
                    rc = stp_dbg_nl_send((char *)&tmp, 2);

                    while(rc){
                       nl_retry++;                       
                       if(nl_retry > 1000){
                            break;
                       }                       
                       STP_BTM_WARN_FUNC("**dump send fails, and retry again.**\n");
                       msleep(3);
                       rc = stp_dbg_nl_send((char *)&tmp, 2);
                       if(!rc){
                          STP_BTM_WARN_FUNC("****retry again ok!**\n");
                       }
                    }                    
                    //schedule();
                } else {
                    STP_BTM_INFO_FUNC("dump entry length is over long\n");
                    BUG_ON(0);
                }
                retry = 0;
            }
        }else
        {
            retry ++;
            msleep(100);
        }
    }while((remain > 0) || (retry < 2));

    STP_BTM_INFO_FUNC("Exit..\n");
    return 0;
}
static INT32 _stp_btm_proc (void *pvData)
{
    MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *)pvData;
    P_OSAL_OP pOp;
    INT32 id;
    INT32 result;
    
    if (!stp_btm) 
    {
        STP_BTM_WARN_FUNC("!stp_btm \n");
        return -1;
    }

    for (;;) 
    {
        pOp = NULL;
        
        osal_wait_for_event(&stp_btm->STPd_event, 
            _stp_btm_wait_for_msg,
            (void *)stp_btm
            );

        if (osal_thread_should_stop(&stp_btm->BTMd)) 
        {
            STP_BTM_INFO_FUNC("should stop now... \n");
            // TODO: clean up active opQ
            break;
        }

        /* get Op from activeQ */
        pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ);

        if (!pOp) 
        {
            STP_BTM_WARN_FUNC("get_lxop activeQ fail\n");
            continue;
        }

        id = osal_op_get_id(pOp);

        STP_BTM_DBG_FUNC("======> lxop_get_opid = %d, %s, remaining count = *%d*\n",
            id, (id >= 4)?("???"):(g_btm_op_name[id]), RB_COUNT(&stp_btm->rActiveOpQ));

        if (id >= STP_OPID_BTM_NUM) 
        {
            STP_BTM_WARN_FUNC("abnormal opid id: 0x%x \n", id);
            result = -1;
            goto handler_done;
        }
        
        result = _stp_btm_handler(stp_btm, &pOp->op);

handler_done:

        if (result) 
        {
            STP_BTM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, (id >= 4)?("???"):(g_btm_op_name[id]), result);
        }

        if (osal_op_is_wait_for_signal(pOp)) 
        {
            osal_op_raise_signal(pOp, result);
        }
        else 
        {
            /* put Op back to freeQ */
            _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp);
        }
        
        if (STP_OPID_BTM_EXIT == id) 
        {
            break;
        }
    }
    
    STP_BTM_INFO_FUNC("exits \n");

    return 0;
};
INT32 _stp_btm_put_act_op (
    MTKSTP_BTM_T *stp_btm,
    P_OSAL_OP pOp
    )
{
    INT32 bRet = 0;
    INT32 bCleanup = 0;
    long wait_ret = -1;

    P_OSAL_SIGNAL pSignal = NULL;

    do {
        if (!stp_btm || !pOp) 
        {
            break;
        }

        pSignal = &pOp->signal;
        
        if (pSignal->timeoutValue) 
        {
            pOp->result = -9;
            osal_signal_init(&pOp->signal);
        }

        /* put to active Q */
        bRet = _stp_btm_put_op(stp_btm, &stp_btm->rActiveOpQ, pOp);
        if(0 == bRet)
        {
            STP_BTM_WARN_FUNC("put active queue fail\n");
            bCleanup = 1;//MTK_WCN_BOOL_TRUE;
            break;
        }
        
        /* wake up wmtd */
        osal_trigger_event(&stp_btm->STPd_event);

        if (pSignal->timeoutValue == 0) 
        {
            bRet = 1;//MTK_WCN_BOOL_TRUE;
            /* clean it in wmtd */
            break;
        }
        
        /* wait result, clean it here */
        bCleanup = 1;//MTK_WCN_BOOL_TRUE;

        /* check result */
        wait_ret = osal_wait_for_signal_timeout(&pOp->signal);

        STP_BTM_DBG_FUNC("wait completion:%ld\n", wait_ret);
        if (!wait_ret) 
        {
            STP_BTM_ERR_FUNC("wait completion timeout \n");
            // TODO: how to handle it? retry?
        }
        else 
        {
            if (pOp->result) 
            {
                STP_BTM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result);
            }
            
            bRet = (pOp->result) ? 0 : 1;
        }
    } while(0);

    if (bCleanup) {
        /* put Op back to freeQ */
        _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp);
    }

    return bRet;
}
Beispiel #12
0
static INT32 _stp_btm_proc(PVOID pvData)
{
	MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData;
	P_OSAL_OP pOp;
	INT32 id;
	INT32 result;

	if (!stp_btm) {
		STP_BTM_WARN_FUNC("!stp_btm\n");
		return -1;
	}

	for (;;) {
		pOp = NULL;

		osal_wait_for_event(&stp_btm->STPd_event, _stp_btm_wait_for_msg, (PVOID)stp_btm);

		if (osal_thread_should_stop(&stp_btm->BTMd)) {
			STP_BTM_INFO_FUNC("should stop now...\n");
			/* TODO: clean up active opQ */
			break;
		}
#if 1
		if (gDumplogflag) {
			/* pr_warn("enter place1\n"); */
			if (mtk_wcn_stp_is_uart_mand_mode() || mtk_wcn_stp_is_uart_fullset_mode())
				dump_uart_history();
			gDumplogflag = 0;
			continue;
		}
#endif

		/* get Op from activeQ */
		pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ);

		if (!pOp) {
			STP_BTM_WARN_FUNC("get_lxop activeQ fail\n");
			continue;
		}

		id = osal_op_get_id(pOp);

		STP_BTM_DBG_FUNC("======> lxop_get_opid = %d, %s, remaining count = *%d*\n",
				 id, (id >= 4) ? ("???") : (g_btm_op_name[id]),
				 RB_COUNT(&stp_btm->rActiveOpQ));

		if (id >= STP_OPID_BTM_NUM) {
			STP_BTM_WARN_FUNC("abnormal opid id: 0x%x\n", id);
			result = -1;
			goto handler_done;
		}

		osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
		stp_btm_set_current_op(stp_btm, pOp);
		osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));
		result = _stp_btm_handler(stp_btm, &pOp->op);
		osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
		stp_btm_set_current_op(stp_btm, NULL);
		osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));

 handler_done:

		if (result) {
			STP_BTM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n",
				id, (id >= 4) ? ("???") : (g_btm_op_name[id]), result);
		}

		if (osal_op_is_wait_for_signal(pOp)) {
			osal_op_raise_signal(pOp, result);
		} else {
			/* put Op back to freeQ */
			_stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp);
		}

		if (STP_OPID_BTM_EXIT == id) {
			break;
		} else if (STP_OPID_BTM_RST == id) {
			/* prevent multi reset case */
			stp_btm_reset_btm_wq(stp_btm);
		}
	}

	STP_BTM_INFO_FUNC("exits\n");

	return 0;
};
Beispiel #13
0
static INT32 _stp_btm_put_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp)
{
	INT32 ret;
	P_OSAL_OP pOp_latest;
	P_OSAL_OP pOp_current;
	INT32 flag_latest = 1;
	INT32 flag_current = 1;

	if (!pOpQ || !pOp) {
		STP_BTM_WARN_FUNC("invalid input param: 0x%p, 0x%p\n", pOpQ, pOp);
		return 0;	/* ;MTK_WCN_BOOL_FALSE; */
	}

	ret = 0;

	osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock));
	/* acquire lock success */
	if (&stp_btm->rFreeOpQ == pOpQ) {
		if (!RB_FULL(pOpQ))
			RB_PUT(pOpQ, pOp);
		else
			ret = -1;
	} else if (pOp->op.opId == STP_OPID_BTM_RST || pOp->op.opId == STP_OPID_BTM_DUMP_TIMEOUT) {
			if (!RB_FULL(pOpQ)) {
				RB_PUT(pOpQ, pOp);
				STP_BTM_ERR_FUNC("RB_PUT: 0x%d\n", pOp->op.opId);
			} else
				ret = -1;
	} else {
		pOp_current = stp_btm_get_current_op(stp_btm);
		if (pOp_current) {
			if (pOp_current->op.opId == STP_OPID_BTM_RST ||
			    pOp_current->op.opId == STP_OPID_BTM_DUMP_TIMEOUT) {
				STP_BTM_ERR_FUNC("current: 0x%d\n", pOp_current->op.opId);
				flag_current = 0;
			}
		}

		RB_GET_LATEST(pOpQ, pOp_latest);
		if (pOp_latest) {
			if (pOp_latest->op.opId == STP_OPID_BTM_RST ||
				pOp_latest->op.opId == STP_OPID_BTM_DUMP_TIMEOUT) {
				STP_BTM_ERR_FUNC("latest: 0x%d\n", pOp_latest->op.opId);
				flag_latest = 0;
			}
			if (pOp_latest->op.opId == pOp->op.opId) {
				flag_latest = 0;
				STP_BTM_DBG_FUNC("With the latest a command repeat: latest 0x%d,current 0x%d\n",
						pOp_latest->op.opId, pOp->op.opId);
			}
		}
		if (flag_current && flag_latest) {
			if (!RB_FULL(pOpQ)) {
				RB_PUT(pOpQ, pOp);
				STP_BTM_ERR_FUNC("RB_PUT: 0x%d\n", pOp->op.opId);
			} else
				ret = -1;
		} else
			ret = -1;

	}
	osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock));

	if (ret) {
		STP_BTM_DBG_FUNC("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n",
			pOpQ, RB_COUNT(pOpQ), &stp_btm->rFreeOpQ, &stp_btm->rActiveOpQ);
		return 0;
	} else {
		/* STP_BTM_WARN_FUNC("RB_COUNT = %d\n",RB_COUNT(pOpQ)); */
		return 1;
	}
}