📄 zd1205.c
字号:
{
struct rx_list_elem *rx_struct = NULL;
unsigned long flags;
flags = dot11Obj.EnterCS();
if (!list_empty(&(macp->rx_struct_pool))) {
rx_struct = list_entry(macp->rx_struct_pool.next,
struct rx_list_elem, list_elem);
list_del(&(rx_struct->list_elem));
}
dot11Obj.ExitCS(flags);
return rx_struct;
}
/**
* zd1205_alloc_skb - allocate an skb for the adapter
* @macp: atapter's private data struct
*
* Allocates skb with enough room for rfd, and data, and reserve non-data space.
* Returns the new cell with sk_buff or %NULL.
*/
static struct rx_list_elem *
zd1205_alloc_skb(struct zd1205_private *macp)
{
struct sk_buff *new_skb;
u32 skb_size = sizeof (zd1205_RFD_t);
struct rx_list_elem *rx_struct;
ZENTER(4);
new_skb = (struct sk_buff *) dev_alloc_skb(skb_size);
if (new_skb) {
/* The IP data should be
DWORD aligned. since the ethernet header is 14 bytes long,
we need to reserve 2 extra bytes so that the TCP/IP headers
will be DWORD aligned. */
//skb_reserve(new_skb, 2); //for zd1202, rx dma must be 4-bytes aligmnebt
if ((rx_struct = zd1205_get_rx_struct(macp)) == NULL)
goto err;
ZD1211DEBUG(4, "zd1211: rx_struct = %x\n", (u32)rx_struct);
rx_struct->skb = new_skb;
//Rx DMA address must be 4 bytes alignment
#ifndef HOST_IF_USB
rx_struct->dma_addr = pci_map_single(macp->pdev, new_skb->data, sizeof (zd1205_RFD_t), PCI_DMA_FROMDEVICE);
#endif
ZD1211DEBUG(4, "zd1211: rx_struct->dma_addr = %x\n", (u32)rx_struct->dma_addr);
#ifndef HOST_IF_USB
if (!rx_struct->dma_addr)
goto err;
#endif
skb_reserve(new_skb, macp->rfd_size); //now skb->data point to RxBuffer
#ifdef HOST_IF_USB
rx_struct->dma_addr = (unsigned long)new_skb->data;
rx_struct->UnFinishFrmLen = 0;
#endif
ZEXIT(4);
return rx_struct;
} else {
macp->AllocSkbFailCnt++;
printk(KERN_DEBUG "zd1205: dev_alloc_skb fail\n");
return NULL;
}
err:
printk(KERN_DEBUG "zd1205: ****** err\n");
dev_kfree_skb_any(new_skb);
return NULL;
}
/**
* zd1205_add_skb_to_end - add an skb to the end of our rfd list
* @macp: atapter's private data struct
* @rx_struct: rx_list_elem with the new skb
*
* Adds a newly allocated skb to the end of our rfd list.
*/
void
zd1205_add_skb_to_end(struct zd1205_private *macp, struct rx_list_elem *rx_struct)
{
zd1205_RFD_t *rfdn; /* The new rfd */
zd1205_RFD_t *rfd; /* The old rfd */
struct rx_list_elem *rx_struct_last;
unsigned long flags;
ZENTER(4);
(rx_struct->skb)->dev = macp->device;
rfdn = RFD_POINTER(rx_struct->skb, macp);
rfdn->CbCommand = RFD_EL_BIT;
wmb();
rfdn->CbStatus = 0xffffffff;
rfdn->ActualCount = 0;
rfdn->MaxSize = MAX_WLAN_SIZE;
rfdn->NextCbPhyAddrHighPart = 0;
rfdn->NextCbPhyAddrLowPart = 0;
#ifndef HOST_IF_USB
wmb();
pci_dma_sync_single(macp->pdev, rx_struct->dma_addr, macp->rfd_size,
PCI_DMA_TODEVICE);
#endif
flags = dot11Obj.EnterCS();
if (!list_empty(&(macp->active_rx_list))) {
rx_struct_last = list_entry(macp->active_rx_list.prev,
struct rx_list_elem, list_elem);
rfd = RFD_POINTER(rx_struct_last->skb, macp);
ZD1211DEBUG(4, "zd1211: rfd = %x\n", (u32)rfd);
#ifndef HOST_IF_USB
pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,
4, PCI_DMA_FROMDEVICE);
#endif
put_unaligned(rx_struct->dma_addr,
((unsigned long *) (&(rfd->NextCbPhyAddrLowPart))));
#ifndef HOST_IF_USB
wmb();
pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,
8, PCI_DMA_TODEVICE);
#endif
rfd->CbCommand = 0;
#ifndef HOST_IF_USB
wmb();
pci_dma_sync_single(macp->pdev, rx_struct_last->dma_addr,
4, PCI_DMA_TODEVICE);
#endif
}
list_add_tail(&(rx_struct->list_elem), &(macp->active_rx_list)); //add elem to active_rx_list
dot11Obj.ExitCS(flags);
ZEXIT(4);
}
void zd1205_alloc_skbs(struct zd1205_private *macp)
{
for (; macp->skb_req > 0; macp->skb_req--) {
struct rx_list_elem *rx_struct;
if ((rx_struct = zd1205_alloc_skb(macp)) == NULL){
printk(KERN_DEBUG "zd1205: zd1205_alloc_skb fail\n");
return;
}
zd1205_add_skb_to_end(macp, rx_struct);
}
}
void zd1205_transmit_cleanup(struct zd1205_private *macp, zd1205_SwTcb_t *sw_tcb)
{
zd1205_HwTCB_t *hw_tcb;
u32 tbd_cnt;
zd1205_TBD_t *tbd_arr = sw_tcb->pFirstTbd;
ZENTER(2);
hw_tcb = sw_tcb->pTcb;
tbd_cnt = hw_tcb->TxCbTbdNumber;
tbd_arr += 2; //CtrlSetting and MacHeader
ZD1211DEBUG(2, "zd1211: umap tbd cnt = %x\n", tbd_cnt-2);
#ifndef HOST_IF_USB
for (i=0; i<tbd_cnt-2; i++, tbd_arr++) {
ZD1211DEBUG(2, "zd1211: umap body_dma = %x\n", le32_to_cpu(tbd_arr->TbdBufferAddrLowPart));
pci_unmap_single(macp->pdev,
le32_to_cpu(tbd_arr->TbdBufferAddrLowPart),
le32_to_cpu(tbd_arr->TbdCount),
PCI_DMA_TODEVICE);
}
#endif
ZD1211DEBUG(2, "zd1211: Free TcbPhys = %x\n", (u32)sw_tcb->TcbPhys);
zd1205_qlast_txq(macp, macp->freeTxQ, sw_tcb);
ZD1211DEBUG(2, "zd1211: Cnt of freeTxQ = %x\n", macp->freeTxQ->count);
//sw_tcb->HangDur = 0;
hw_tcb->CbStatus = 0xffffffff;
hw_tcb->TxCbTbdNumber = 0xaaaaaaaa; /* for debug */
hw_tcb->CbCommand = CB_S_BIT;
if ((netif_running(macp->device)) && (macp->bAssoc)){
netif_carrier_on(macp->device);
netif_wake_queue(macp->device); //resume tx
}
ZEXIT(2);
return;
}
void zd1205_tx_isr(struct zd1205_private *macp)
{
int i;
zd1205_SwTcb_t *sw_tcb = NULL;
#ifndef HOST_IF_USB
zd1250_SwTcb_t *next_sw_tcb;
#endif
u16 aid;
#ifdef HOST_IF_USB
int bRunOnce = false;
#endif
ZD1211DEBUG(2, "***** zd1205_tx_isr enter *****\n");
if (!macp->activeTxQ->count){
printk(KERN_DEBUG "No element in activeQ\n");
clear_bit(ZD1211_TX_BUSY, &macp->flags);
return;
}
/* Look at the TCB at the head of the queue. If it has been completed
then pop it off and place it at the tail of the completed list.
Repeat this process until all the completed TCBs have been moved to the
completed list */
while (macp->activeTxQ->count){
sw_tcb = macp->activeTxQ->first;
#ifdef HOST_IF_USB
// in USB modem, only run once
if (bRunOnce)
break;
bRunOnce = true;
#endif
// check to see if the TCB has been DMA'd
// Workaround for hardware problem that seems leap over a TCB
// and then fill completion token in the next TCB.
ZD1211DEBUG(2, "zd1211: hw_tcb = %x\n", (u32)sw_tcb->pTcb);
ZD1211DEBUG(2, "zd1211: CbStatus = %x\n", (u16)(sw_tcb->pTcb->CbStatus));
#ifndef HOST_IF_USB
rmb();
if ((u16)le32_to_cpu(sw_tcb->pTcb->CbStatus) != CB_STATUS_COMPLETE){
next_sw_tcb = sw_tcb;
while(1){
next_sw_tcb = next_sw_tcb->next;
if (!next_sw_tcb)
break;
if ((u16)le32_to_cpu(next_sw_tcb->pTcb->CbStatus) == CB_STATUS_COMPLETE)
break;
}
if (!next_sw_tcb)
break;
}
#endif
/* Remove the TCB from the active queue. */
sw_tcb = zd1205_first_txq(macp, macp->activeTxQ);
//Clear bit should run once only. This depends on the "bRunOnce"
//mechanism. Clear twice may interfer normal tx
clear_bit(ZD1211_TX_BUSY, &macp->flags);
ZD1211DEBUG(2, "zd1211: Cnt of activeQ = %x\n", macp->activeTxQ->count);
aid = sw_tcb->aid;
zd1205_transmit_cleanup(macp, sw_tcb);
macp->txCmpCnt++;
if (!sw_tcb->LastFrag)
continue;
#if ZDCONF_LP_SUPPORT == 1
if(dot11Obj.LP_MODE && sw_tcb->LP_bucket) {
//printk("TX_ISR Free LP_bucket\n");
struct lp_desc *lp = (struct lp_desc *)sw_tcb->LP_bucket ;
for(i=0;i<lp->pktCnt;i++) {
//printk("msgID:%d\n", lp->pkt[i].msgID);
zd_EventNotify(EVENT_TX_COMPLETE, ZD_TX_CONFIRM, (U32)lp->pkt[i].msgID, (U32)aid);
}
sw_tcb->LP_bucket = NULL;
lp->pktCnt = 0;
lp->sending = 0;
lp->createTime = 0;
lp->pktSize = 0;
lp_recycle_tx_bucket(lp);
}
else
#endif
{
zd_EventNotify(EVENT_TX_COMPLETE, ZD_TX_CONFIRM, (U32)sw_tcb->MsgID, (U32)aid);
}
macp->SequenceNum++;
macp->bDataTrafficLight = 1;
}
#ifdef HOST_IF_USB
if(sw_tcb->CalMIC[MIC_LNG] == TRUE)
zd1211_submit_tx_urb(macp,TRUE);
else
zd1211_submit_tx_urb(macp,FALSE);
#endif
ZD1211DEBUG(2, "***** zd1205_tx_isr exit *****\n");
return;
}
#ifndef HOST_IF_USB
static void zd1205_retry_failed(struct zd1205_private *macp)
{
zd1205_SwTcb_t *sw_tcb;
zd1205_SwTcb_t *next_sw_tcb = NULL;
zd1205_HwTCB_t *hw_tcb;
zd1205_Ctrl_Set_t *ctrl_set;
u8 CurrentRate, NewRate;
u8 ShortPreambleFg;
u16 Len;
u16 NextLen;
u16 LenInUs;
u16 NextLenInUs;
u8 Service;
u16 aid;
ZD1211DEBUG(2, "+++++ zd1205_retry_failed enter +++++\n");
if (!macp->activeTxQ->count){
ZD1211DEBUG(1, "**********empty activeTxQ, got retry failed");
sw_tcb = macp->freeTxQ->first;
zd1205_start_download(sw_tcb->TcbPhys | BIT_0);
return;
}
// Feature: Rate Adaption
// - During the procedure of processing a transmitting frame, we must keep
// the TaRate consistent.
// - When to fall OppositeContext.CurrentTxRate:
// Whenever RetryFail occurs, change OppositeContext.CurrentTxRate by a value
// ((Rate of this TCB) minus a degree) and modify this TCB's control-setting
// with the OppositeContext.CurrentTxRate and then Restart this TCB.
// (Set RetryMAX = 2).
// Once the TxRate is 1M and still RetryFail, abandon this frame.
// - When to rise TxRate:
// If there are 10 frames transmitted successfully
// (OppositeContext.ConsecutiveSuccessFrames >= 10), change
// OppositeContext.CurrentTxRate by a value
// ((Rate of this TCB) plus a degree).
// - Adjust OppositeContext.CurrentTxRate manually. (by application tool)
sw_tcb = macp->activeTxQ->first;
aid = sw_tcb->aid;
ctrl_set = sw_tcb->pHwCtrlPtr;
if (ctrl_set->CtrlSetting[11] & BIT_3){ //management frame
goto no_rate_adaption;
}
//CurrentRate = (ctrl_set->CtrlSetting[0] & 0x1f);
CurrentRate = sw_tcb->Rate;
ShortPreambleFg = (ctrl_set->CtrlSetting[0] & 0x20);
if (((!ShortPreambleFg) && (CurrentRate > RATE_1M)) ||
((ShortPreambleFg) && (CurrentRate > RATE_2M))){
// Fall TxRate a degree
NewRate = zd1205_RateAdaption(aid, CurrentRate, FALL_RATE);
sw_tcb->Rate = NewRate;
// Modify Control-setting
ctrl_set->CtrlSetting[0] = (ShortPreambleFg | NewRate);
ctrl_set->CtrlSetting[11] |= BIT_0; // Set need backoff
// LenInUs, Service
Len = (ctrl_set->CtrlSetting[1] + ((u16)ctrl_set->CtrlSetting[2] << 8));
Cal_Us_Service(NewRate, Len, &LenInUs, &Service);
ctrl_set->CtrlSetting[20] = (u8)LenInUs;
ctrl_set->CtrlSetting[21] = (u8)(LenInUs >> 8);
ctrl_set->CtrlSetting[22] = Service;
// NextLenInUs
#if defined(OFDM)
NextLen = (ctrl_set->CtrlSetting[25+1] + ((u16)ctrl_set->CtrlSetting[25+2] << 8));
#else
NextLen = (ctrl_set->CtrlSetting[18] + ((u16)ctrl_set->CtrlSetting[19] << 8));
#endif
Cal_Us_Service(NewRate, NextLen, &NextLenInUs, &Service);
ctrl_set->CtrlSetting[23] = (u8)NextLenInUs;
ctrl_set->CtrlSetting[24] = (u8)(NextLenInUs >> 8);
#if defined(OFDM)
if (NewRate > RATE_11M){
NewRate = OfdmRateTbl[NewRate];
}
macp->retryFailCnt++;
ctrl_set->CtrlSetting[0] = (ShortPreambleFg | NewRate);
ctrl_set->CtrlSetting[11] |= BIT_0; // Set need backoff
#endif
// Re-Start Tx-Bus master with a lower Rate
z
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -