ip1000: For compatible at PCI 66MHz issue
Subsystems (2)
PATCH 7/7 ip1000: For compatible at PCI 66MHz issue
From: Jesse Huang <[email protected]>
IP1000A on some motherboard when running at PCI 66MHz will cause transmit hold. I had change three functions to solve this problem. Sorry for lot of modify.
Change Logs:
For compatible at 66MHz issue
rewrite init_tfdlist()
rewrite ipg_nic_hard_start_xmit()
rewrite ipg_nic_txfree()
in ipg.h add:
long LastTFDHoldAddr;
int LastTFDHoldCnt;
int ResetCurrentTFD;---
drivers/net/ipg.c | 40 +++++++++++++++++++++++++++++++--------- drivers/net/ipg.h | 4 +++- 2 files changed, 34 insertions(+), 10 deletions(-)
152a32c3d36ec4ce1eee72429aa5956274bb0e6a
drivers/net/ipg.c +31 -9
@@ -886,10 +886,7 @@ static int init_tfdlist(struct net_devicIPG_DEBUG_MSG ("_init_tfdlist\n" );for (i =0 ; i <IPG_TFDLIST_LENGTH ; i++) { - sp->TFDList[i].TFDNextPtr =cpu_to_le64 (sp->TFDListDMAhandle + - ((sizeof (struct TFD )) * - ((i +1 ) % -IPG_TFDLIST_LENGTH ))); + sp->TFDList[i].TFDNextPtr =0 ; sp->TFDList[i].TFC =cpu_to_le64 (IPG_TFC_TFDDONE );if (sp->TxBuff[i] !=NULL )
@@ -907,6 +904,7 @@ static int init_tfdlist(struct net_deviciowrite32 ((u32) (sp->TFDListDMAhandle), ioaddr +TFD_LIST_PTR_0 );iowrite32 (0x00000000 , ioaddr +TFD_LIST_PTR_1 ); + sp->ResetCurrentTFD=1 ;return 0 ; }
@@ -919,6 +917,7 @@ static void ipg_nic_txfree(struct net_destruct ipg_nic_private *sp =netdev_priv (dev);int NextToFree;int maxtfdcount; +long CurrentTxTFDPtr=(ioread32 (ipg_ioaddr (dev)+TFD_LIST_PTR_0 )-(long )sp->TFDListDMAhandle)/(long )sizeof (struct TFD );IPG_DEBUG_MSG ("_nic_txfree\n" );
@@ -941,8 +940,10 @@ static void ipg_nic_txfree(struct net_de* If the TFDDone bit is set, free the associated * buffer. */ -if ((le64_to_cpu (sp->TFDList[NextToFree].TFC) & -IPG_TFC_TFDDONE ) && (NextToFree != sp->CurrentTFD)) { +if ((NextToFree != sp->CurrentTFD)&&(NextToFree!=CurrentTxTFDPtr)) + { +//JesseAdd: setup TFDDONE for compatible issue. + sp->TFDList[NextToFree].TFC =cpu_to_le64 (sp->TFDList[NextToFree].TFC|IPG_TFC_TFDDONE );/* Free the transmit buffer. */ if (sp->TxBuff[NextToFree] !=NULL ) { pci_unmap_single(sp->pdev,
@@ -965,6 +966,15 @@ static void ipg_nic_txfree(struct net_de maxtfdcount--; }while (maxtfdcount !=0 ); +if (sp->LastTFDHoldCnt>1000 ) { + sp->LastTFDHoldCnt=0 ; +ipg_reset (dev,IPG_AC_TX_RESET |IPG_AC_DMA |IPG_AC_NETWORK |IPG_AC_FIFO ); +// Re-configure after DMA reset. +if ((ipg_io_config (dev) <0 ) ||(init_tfdlist (dev) <0 )) { +printk (KERN_INFO "%s: Error during re-configuration.\n" ,dev->name); + } +iowrite32 (IPG_MC_RSVD_MASK & (ioread32 (ipg_ioaddr (dev) +MAC_CTRL ) |IPG_MC_TX_ENABLE ),ipg_ioaddr (dev) +MAC_CTRL ); + } }/*
@@ -2041,10 +2051,17 @@ static int ipg_nic_hard_start_xmit(struc* counter, modulus the length of the TFDList. */ NextTFD = (sp->CurrentTFD +1 ) %IPG_TFDLIST_LENGTH ; +if (sp->ResetCurrentTFD!=0 ) + { + sp->ResetCurrentTFD=0 ; + NextTFD=0 ; + } +/* Check for availability of next TFD. Reserve 1 for not become ring*/ +if (NextTFD == sp->LastFreedTxBuff) { + +if (sp->LastTFDHoldAddr==sp->CurrentTFD) sp->LastTFDHoldCnt++; +else {sp->LastTFDHoldAddr=sp->CurrentTFD;sp->LastTFDHoldCnt=0 ;} -/* Check for availability of next TFD. */ -if (!(le64_to_cpu (sp->TFDList[NextTFD].TFC) & -IPG_TFC_TFDDONE ) || (NextTFD == sp->LastFreedTxBuff)) {IPG_DEBUG_MSG ("Next TFD not available.\n" );/* Attempt to free any used TFDs. */
@@ -2058,8 +2075,11 @@ #ifdef IPG_DEBUG sp->TFDunavailCount++;#endif +iowrite32 (IPG_DC_RSVD_MASK & (IPG_DC_TX_DMA_POLL_NOW ),ioaddr +DMA_CTRL );return -ENOMEM ; } + + sp->TFDList[NextTFD].TFDNextPtr=0 ; sp->TxBuffDMAhandle[NextTFD].len = skb->len; sp->TxBuffDMAhandle[NextTFD].dmahandle =
@@ -2151,6 +2171,8 @@ #endif* for transfer to the IPG. */ sp->TFDList[NextTFD].TFC &=cpu_to_le64 (~IPG_TFC_TFDDONE ); + sp->TFDList[sp->CurrentTFD].TFDNextPtr=cpu_to_le64 (sp->TFDListDMAhandle+ +sizeof (struct TFD )*NextTFD);/* Record frame transmit start time (jiffies = Linux * kernel current time stamp).
drivers/net/ipg.h +3 -1
@@ -834,7 +834,9 @@ #endifstruct mutex mii_mutex;struct mii_if_info mii_if; - +long LastTFDHoldAddr; +int LastTFDHoldCnt; +int ResetCurrentTFD;#ifdef IPG_DEBUG int TFDunavailCount;int RFDlistendCount;
Signature · 1 line
1.3.GIT