mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-24 21:18:54 +00:00
291 lines
8.8 KiB
C
291 lines
8.8 KiB
C
/**************************************************************************************************************
|
|
* altobeam RTOS
|
|
*
|
|
* Copyright (c) 2018, altobeam.inc All rights reserved.
|
|
*
|
|
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
|
|
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
|
|
*****************************************************************************************************************/
|
|
#include "atbm_hal.h"
|
|
extern int wsm_recovery(struct atbmwifi_common *hw_priv);
|
|
int atbm_rx_bh_cb(struct atbmwifi_common *hw_priv,struct atbm_buff *skb, ATBM_BOOL checkseq)
|
|
{
|
|
struct wsm_hdr *wsm;
|
|
atbm_uint32 wsm_len;
|
|
int wsm_id;
|
|
atbm_uint8 wsm_seq;
|
|
//wifi_printk(WIFI_DBG_ERROR, "%s ++\n",__func__);
|
|
|
|
wsm = (struct wsm_hdr *)ATBM_OS_SKB_DATA(skb);
|
|
|
|
wsm_len = __atbm_le32_to_cpu(wsm->len);
|
|
|
|
wsm_id = __atbm_le32_to_cpu(wsm->id) & 0xFFF;
|
|
|
|
ATBM_BUG_ON(wsm_len > 4096);
|
|
atbm_skb_trim(skb,0);
|
|
atbm_skb_put(skb,wsm_len);
|
|
|
|
if (atbm_unlikely(wsm_id == 0x0800)) {
|
|
wsm_handle_exception(hw_priv,
|
|
&ATBM_OS_SKB_DATA(skb)[sizeof(*wsm)],
|
|
wsm_len - sizeof(*wsm));
|
|
if(wsm_recovery(hw_priv)== RECOVERY_ERR){
|
|
ATBM_BUG_ON(1);
|
|
}
|
|
goto __free;
|
|
}
|
|
if(checkseq){
|
|
wsm_seq = (__atbm_le32_to_cpu(wsm->id) >> 13) & 7;
|
|
if (ATBM_WARN_ON(wsm_seq != hw_priv->wsm_rx_seq)) {
|
|
wifi_printk(WIFI_DBG_ERROR,"rx wsm_seq error %d %d \n",wsm_seq,hw_priv->wsm_rx_seq);
|
|
if(wsm_recovery(hw_priv)== RECOVERY_ERR){
|
|
ATBM_BUG_ON(1);
|
|
}
|
|
goto __free;
|
|
}
|
|
hw_priv->wsm_rx_seq = (wsm_seq + 1) & 7;
|
|
}
|
|
|
|
if (wsm_id & 0x0400) {
|
|
int rc = wsm_release_tx_buffer(hw_priv, 1);
|
|
if (ATBM_WARN_ON(rc < 0)){
|
|
wifi_printk(WIFI_ALWAYS,"%s %d \n",__FUNCTION__,__LINE__);
|
|
ATBM_BUG_ON(1);
|
|
goto __free;
|
|
}
|
|
}
|
|
|
|
/* atbm_wsm_rx takes care on SKB livetime */
|
|
if (ATBM_WARN_ON(wsm_handle_rx(hw_priv, wsm_id, wsm,&skb))){
|
|
wifi_printk(WIFI_ALWAYS,"%s %d \n",__FUNCTION__,__LINE__);
|
|
if(wsm_recovery(hw_priv)== RECOVERY_ERR){
|
|
ATBM_BUG_ON(1);
|
|
}
|
|
goto __free;
|
|
}
|
|
|
|
__free:
|
|
//wifi_printk(WIFI_DBG_ERROR, "%s %d\n",__func__,__LINE__);
|
|
if(skb != ATBM_NULL){
|
|
atbm_dev_kfree_skb(skb);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/*Tx Task Func*/
|
|
atbm_void atbm_tx_task(struct atbmwifi_common *hw_priv)
|
|
{
|
|
int status =0;
|
|
do {
|
|
//if(hw_priv->bh_term)|| (hw_priv->bh_error))
|
|
//{
|
|
// wifi_printk(WIFI_IF,"atbm_tx_task term(%d),err(%d)\n",atbm_atomic_read(&hw_priv->bh_term),hw_priv->bh_error);
|
|
// return;
|
|
//}
|
|
/*atbm transmit packet to device*/
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
status = hw_priv->sbus_ops->sbus_memcpy_toio(hw_priv->sbus_priv,0x1,ATBM_NULL,TX_BUFFER_SIZE);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
}while(status > 0);
|
|
}
|
|
/*Rx Task Func*/
|
|
atbm_void atbm_rx_task(struct atbmwifi_common *hw_priv)
|
|
{
|
|
struct atbm_buff *skb;
|
|
#if HI_RX_MUTIL_FRAME
|
|
struct wsm_hdr *wsm;
|
|
atbm_uint32 wsm_len, wsm_id, data_len;
|
|
struct atbm_buff *skb_copy;
|
|
ATBM_BOOL checkseq;
|
|
ATBM_BOOL multirx;
|
|
#endif
|
|
|
|
#define RX_ALLOC_BUFF_OFFLOAD ( (36+16)/*RX_DESC_OVERHEAD*/+4/*FCS_LEN*/ -16 /*WSM_HI_RX_IND*/)
|
|
while ((skb = atbm_skb_dequeue(&hw_priv->rx_frame_queue)) != ATBM_NULL) {
|
|
if(hw_priv->bh_term|| hw_priv->bh_error)
|
|
break;
|
|
#if HI_RX_MUTIL_FRAME
|
|
multirx = ATBM_FALSE;
|
|
checkseq = ATBM_TRUE;
|
|
wsm = (struct wsm_hdr *)ATBM_OS_SKB_DATA(skb);
|
|
wsm_len = __atbm_le32_to_cpu(wsm->len);
|
|
wsm_id = __atbm_le32_to_cpu(wsm->id) & 0xFFF;
|
|
//wifi_printk(WIFI_DBG_ERROR, "%s rxdata %x\n",__func__,wsm_id);
|
|
|
|
if(wsm_id == WSM_MULTI_RECEIVE_INDICATION_ID){
|
|
multirx = ATBM_TRUE;
|
|
}else if(wsm_id == WSM_SINGLE_CHANNEL_MULTI_RECEIVE_INDICATION_ID){
|
|
atbm_uint8 wsm_seq;
|
|
|
|
multirx = ATBM_TRUE;
|
|
wsm_seq = (__atbm_le32_to_cpu(wsm->id) >> 13) & 7;
|
|
if (ATBM_WARN_ON(wsm_seq != hw_priv->wsm_rx_seq)) {
|
|
wifi_printk(WIFI_DBG_ERROR,"rx wsm_seq error %d %d \n",wsm_seq,hw_priv->wsm_rx_seq);
|
|
if(wsm_recovery(hw_priv)== RECOVERY_ERR){
|
|
ATBM_BUG_ON(1);
|
|
}
|
|
goto multirx_end;
|
|
}
|
|
hw_priv->wsm_rx_seq = (wsm_seq + 1) & 7;
|
|
checkseq = ATBM_FALSE;
|
|
}
|
|
if(multirx){
|
|
struct wsm_multi_rx * multi_rx = (struct wsm_multi_rx *)ATBM_OS_SKB_DATA(skb);
|
|
int RxFrameNum = multi_rx->RxFrameNum;
|
|
data_len = wsm_len ;
|
|
data_len -= sizeof(struct wsm_multi_rx);
|
|
wsm = (struct wsm_hdr *)(multi_rx+1);
|
|
wsm_len = __atbm_le32_to_cpu(wsm->len);
|
|
wsm_id = __atbm_le32_to_cpu(wsm->id) & 0xFFF;
|
|
do {
|
|
|
|
if(data_len < wsm_len){
|
|
wifi_printk(WIFI_DBG_ERROR,"skb->len %x,wsm_len %x\n",ATBM_OS_SKB_LEN(skb),wsm_len);
|
|
break;
|
|
}
|
|
ATBM_BUG_ON((wsm_id & ~WSM_TX_LINK_ID(WSM_TX_LINK_ID_MAX)) != WSM_RECEIVE_INDICATION_ID);
|
|
skb_copy = atbm_dev_alloc_skb(wsm_len + 16);
|
|
/* In AP mode RXed SKB can be looped back as a broadcast.
|
|
* Here we reserve enough space for headers. */
|
|
atbm_skb_reserve(skb_copy, (8 - (((unsigned long)ATBM_OS_SKB_DATA(skb_copy))&7))/*ATBM_ALIGN 8*/);
|
|
|
|
atbm_memmove(ATBM_OS_SKB_DATA(skb_copy), wsm, wsm_len);
|
|
atbm_skb_put(skb_copy,wsm_len);
|
|
atbm_rx_bh_cb(hw_priv,skb_copy,checkseq);
|
|
data_len -= ATBM_ALIGN(wsm_len + RX_ALLOC_BUFF_OFFLOAD,4);
|
|
RxFrameNum--;
|
|
|
|
wsm = (struct wsm_hdr *)((atbm_uint8 *)wsm +ATBM_ALIGN(( wsm_len + RX_ALLOC_BUFF_OFFLOAD),4));
|
|
wsm_len = __atbm_le32_to_cpu(wsm->len);
|
|
wsm_id = __atbm_le32_to_cpu(wsm->id) & 0xFFF;
|
|
|
|
}while((RxFrameNum>0) && (data_len > 32));
|
|
ATBM_BUG_ON(RxFrameNum != 0);
|
|
multirx_end:
|
|
#if RX_QUEUE_IMMD
|
|
if(skb->Type == RX_SKB__RX_QUEUE_PACKAGE){
|
|
/*atbm transmit packet to device*/
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
hw_priv->sbus_priv->rx_queue_qnum--;
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
atbm_dev_kfree_skb(skb);
|
|
}else
|
|
#endif
|
|
{
|
|
//wifi_printk(WIFI_ALWAYS, "1 zzzz\n");
|
|
/*atbm transmit packet to device*/
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
hw_priv->sbus_ops->sbus_read_async(hw_priv->sbus_priv,0x2,skb,RX_BUFFER_SIZE);
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
atbm_rx_bh_cb(hw_priv,skb,checkseq);
|
|
/*atbm transmit packet to device*/
|
|
hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
|
#if RX_QUEUE_IMMD
|
|
if(skb->Type == RX_SKB__RX_QUEUE_PACKAGE){
|
|
hw_priv->sbus_priv->rx_queue_qnum--;
|
|
}else
|
|
#endif
|
|
{
|
|
//wifi_printk(WIFI_ALWAYS, "2 zzzz\n");
|
|
hw_priv->sbus_ops->sbus_read_async(hw_priv->sbus_priv,0x2,ATBM_NULL,RX_BUFFER_SIZE);
|
|
}
|
|
hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
|
}
|
|
}
|
|
}
|
|
atbm_void atbm_usb_bh(atbm_void *arg)
|
|
{
|
|
struct atbmwifi_common *hw_priv = (struct atbmwifi_common *)arg;
|
|
int rx=0, tx=0,urb_compl=0;
|
|
//int pending_tx = 0;
|
|
//ATBM_BOOL powersave_enabled;
|
|
//int loop=0;
|
|
//int prink_test =0;
|
|
#define __ALL_HW_BUFS_USED (hw_priv->hw_bufs_used)
|
|
while (1){
|
|
do {
|
|
|
|
rx = atbm_atomic_xchg(&hw_priv->bh_rx, 0);
|
|
tx = atbm_atomic_xchg(&hw_priv->bh_tx, 0);
|
|
urb_compl = atbm_atomic_xchg(&hw_priv->urb_comp, 0);
|
|
//suspend = pending_tx ?0 : atbm_atomic_read(&hw_priv->bh_suspend);
|
|
if(tx || rx|| urb_compl){
|
|
//atbm_os_try_to_wait_event_timeout(&hw_priv->bh_wq,1);
|
|
break;
|
|
}
|
|
atbm_os_wait_event_timeout(&hw_priv->bh_wq,100*HZ);
|
|
|
|
//wifi_printk(WIFI_ALWAYS,"atbm_usb_bh waitevent ---atbm_usb_bh\n");
|
|
rx = atbm_atomic_xchg(&hw_priv->bh_rx, 0);
|
|
tx = atbm_atomic_xchg(&hw_priv->bh_tx, 0);
|
|
urb_compl = atbm_atomic_xchg(&hw_priv->urb_comp, 0);
|
|
|
|
}while(0);
|
|
|
|
if ( hw_priv->bh_term || hw_priv->bh_error){
|
|
wifi_printk(WIFI_DBG_ERROR,"%s BH thread break %d %d\n",__FUNCTION__,hw_priv->bh_term,hw_priv->bh_error);
|
|
break;
|
|
}
|
|
if(urb_compl){
|
|
//wifi_printk(WIFI_ALWAYS," urb_compl ----->.\n");
|
|
atbm_urb_coml(hw_priv);
|
|
}
|
|
|
|
if (rx){
|
|
atbm_rx_task(hw_priv);
|
|
}
|
|
if (tx){
|
|
atbm_tx_task(hw_priv);
|
|
}
|
|
|
|
wifi_printk(WIFI_BH,"atbm_usb_bh while--\n");
|
|
}
|
|
wifi_printk(WIFI_DBG_ERROR, "%s --\n",__func__);
|
|
|
|
atbm_ThreadStopEvent(hw_priv->bh_thread);
|
|
}
|
|
|
|
int atbm_register_bh(struct atbmwifi_common *hw_priv)
|
|
{
|
|
atbm_thread_internal_t *bh_thread;
|
|
int status =0;
|
|
atbm_atomic_set(&hw_priv->bh_rx, 0);
|
|
atbm_atomic_set(&hw_priv->bh_tx, 0);
|
|
atbm_os_init_waitevent(&hw_priv->bh_wq);
|
|
atbm_os_init_waitevent(&hw_priv->wsm_cmd_wq);
|
|
hw_priv->bh_term=0;
|
|
hw_priv->bh_error=0;
|
|
wifi_printk(WIFI_DBG_ERROR,"atbm_register_bh\n");
|
|
|
|
/*Create RxData Task*/
|
|
bh_thread=atbm_createThreadInternal("atbm_bh",atbm_usb_bh,(atbm_void*)hw_priv,BH_TASK_PRIO);
|
|
if (!bh_thread){
|
|
wifi_printk(WIFI_DBG_ERROR,"bh_thread Failed\n");
|
|
return -1;
|
|
}
|
|
hw_priv->bh_thread = bh_thread;
|
|
#if USE_MAIL_BOX
|
|
/*create the usb tx complete mailbox*/
|
|
atbm_createMailBox((atbm_void*)hw_priv);
|
|
#endif
|
|
return status;
|
|
}
|
|
atbm_void atbm_unregister_bh(struct atbmwifi_common *hw_priv)
|
|
{
|
|
//kill createThread
|
|
hw_priv->bh_term=1;
|
|
atbm_os_wakeup_event(&hw_priv->bh_wq);
|
|
atbm_stopThread(hw_priv->bh_thread);
|
|
|
|
atbm_os_delete_waitevent(&hw_priv->bh_wq);
|
|
atbm_os_delete_waitevent(&hw_priv->wsm_cmd_wq);
|
|
atbm_os_DeleteMutex(&hw_priv->wsm_cmd_mux);
|
|
}
|
|
|