Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Feb 1998 19:17:12 -0700 (MST)
From:      Steve Bauer <sbauer@hardrock.sdsmt.edu>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   kern/5694: patch to remove DELAY(300000) from if_tx.c driver
Message-ID:  <199802100217.TAA00487@hardrock.sdsmt.edu>

next in thread | raw e-mail | index | archive | help

>Number:         5694
>Category:       kern
>Synopsis:       Remove DELAY(300000) from if_tx.c driver (SMC9432)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb  9 18:20:02 PST 1998
>Last-Modified:
>Originator:     Steve Bauer
>Organization:
South Dakota School of Mines and Technology
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

	FreeBSD 3.0-Current i386 as of 7pm MST on 2/9/98
	Running On a Gateway NS7000 2 processor smp machine.

>Description:

	In the auto-negotiation function there was a DELAY(300000) which
needed to be removed if possible.  With the following patch, the DELAY
was removed from the sequence thus speeding up the testing of the different
speeds.  There are also a few other changes in how the driver reset some
interrupt status bits -- It was missing the case where RQE was turned off.

>How-To-Repeat:

	Start auto-negotiation and it would pause the machine for about
3 seconds.
>Fix:
	

*** if_tx.c	Sun Feb  8 23:10:53 1998
--- if_tx.c.new	Mon Feb  9 19:07:39 1998
***************
*** 107,112 ****
--- 107,113 ----
  	&epic_pci_count,
  	NULL };
  
+ static void epic_shutdown	__P((int, void *));
  /*
   * Append this driver to pci drivers list
   */
***************
*** 243,249 ****
  		}
  
  		/* Does not generate TXC unless ring is full more then a half */
! 		buf->desc.control =
  			(sc->pending_txs>TX_RING_SIZE/2)?0x14:0x10;
  #endif
  
--- 244,250 ----
  		}
  
  		/* Does not generate TXC unless ring is full more then a half */
! 		buf->desc.control = 
  			(sc->pending_txs>TX_RING_SIZE/2)?0x14:0x10;
  #endif
  
***************
*** 327,345 ****
  		epic_rx_done( sc );
  		outl( iobase + INTSTAT,
  			status & (INTSTAT_RQE|INTSTAT_HCC|INTSTAT_RCC) ); 
  	}
- 
- 	if( status & (INTSTAT_TXC|INTSTAT_TCC) ) {
- 		epic_tx_done( sc );
- 		outl( iobase + INTSTAT,
- 			status & (INTSTAT_TXC|INTSTAT_TCC) );
- 	}
- 
  	if( (status & INTSTAT_TQE) && !(sc->epic_if.if_flags & IFF_OACTIVE) ) {
  		epic_ifstart( &sc->epic_if );
  		outl( iobase + INTSTAT, INTSTAT_TQE );
  	}
  
  #if 0
  	if( status & INTSTAT_GP2 ){
  		printf("tx%d: GP2 int occured\n",sc->unit);
--- 328,347 ----
  		epic_rx_done( sc );
  		outl( iobase + INTSTAT,
  			status & (INTSTAT_RQE|INTSTAT_HCC|INTSTAT_RCC) ); 
+ 		/*if INTSTAT_RQE then RXQUEUED needs to be reset*/
+ 		outl( iobase + COMMAND, COMMAND_RXQUEUED);
  	}
  	if( (status & INTSTAT_TQE) && !(sc->epic_if.if_flags & IFF_OACTIVE) ) {
  		epic_ifstart( &sc->epic_if );
  		outl( iobase + INTSTAT, INTSTAT_TQE );
  	}
  
+ 	if( status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) ) {
+ 		epic_tx_done( sc );
+ 		outl( iobase + INTSTAT,
+ 			status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) );
+ 	}
+ 
  #if 0
  	if( status & INTSTAT_GP2 ){
  		printf("tx%d: GP2 int occured\n",sc->unit);
***************
*** 781,786 ****
--- 783,789 ----
  	if( !(i & BMSR_LINK_STATUS) )
  		printf("tx%d: WARNING! no link estabilished\n",sc->unit);
  
+ 	at_shutdown(epic_shutdown, sc, SHUTDOWN_POST_SYNC);
  	/*
  	 *  Attach to if manager
  	 */
***************
*** 814,821 ****
  	/* Soft reset the chip. */
  	outl(iobase + GENCTL, GENCTL_SOFT_RESET );
  
! 	/* Reset takes 15 ticks */
! 	for(i=0;i<0x100;i++);
  
  	/* Wake up */
  	outl( iobase + GENCTL, 0 );
--- 817,824 ----
  	/* Soft reset the chip. */
  	outl(iobase + GENCTL, GENCTL_SOFT_RESET );
  
! 	/* Reset takes 15 pci ticks which depends on processor speed*/
! 	DELAY(1);
  
  	/* Wake up */
  	outl( iobase + GENCTL, 0 );
***************
*** 970,1042 ****
  	 * This is the recommended time from the DP83840A data sheet
  	 * Section 7.1
           */
-         DELAY(3000000);
  
  	epic_read_phy_register( sc->iobase, DP83840_BMSR);
- 
-         /* BMSR must be read twice to update the link status bit/
- 	 * since that bit is a latch bit
-          */
  	i = epic_read_phy_register( sc->iobase, DP83840_BMSR);
!         
!         if ((i & BMSR_LINK_STATUS) && ( i & BMSR_AUTONEG_COMPLETE)){
! 		i = epic_read_phy_register( sc->iobase, DP83840_PAR);
! 
! 		if ( i & PAR_FULL_DUPLEX )
! 			return 	EPIC_FULL_DUPLEX;
! 		else
! 			return EPIC_HALF_DUPLEX;
!         } 
! 	else {   /*Auto-negotiation or link status is not 1
! 		   Thus the auto-negotiation failed and one
! 		   must take other means to fix it.
! 		  */
! 
! 		/* ANER must be read twice to get the correct reading for the 
! 		 * Multiple link fault bit -- it is a latched bit
! 	 	 */
!  		epic_read_phy_register (sc->iobase, DP83840_ANER);
  
! 		i = epic_read_phy_register (sc->iobase, DP83840_ANER);
! 	
! 		if ( i & ANER_MULTIPLE_LINK_FAULT ) {
! 			/* it can be forced to 100Mb/s Half-Duplex */
! 	 		media = epic_read_phy_register(sc->iobase,DP83840_BMCR);
! 			media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX);
! 			media |= BMCR_100MBPS;
! 			epic_write_phy_register(sc->iobase,DP83840_BMCR,media);
! 		
! 			/* read BMSR again to determine link status */
! 			epic_read_phy_register(sc->iobase, DP83840_BMSR);
! 			i=epic_read_phy_register( sc->iobase, DP83840_BMSR);
! 		
! 			if (i & BMSR_LINK_STATUS){
! 				/* port is linked to the non Auto-Negotiation
! 				 * 100Mbs partner.
! 			 	 */
! 				return EPIC_HALF_DUPLEX;
  			}
  			else {
! 				media = epic_read_phy_register (sc->iobase, DP83840_BMCR);
! 				media &= !(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX | BMCR_100MBPS);
! 				epic_write_phy_register(sc->iobase, DP83840_BMCR, media);
  				epic_read_phy_register(sc->iobase, DP83840_BMSR);
  				i=epic_read_phy_register( sc->iobase, DP83840_BMSR);
! 
! 				if (i & BMSR_LINK_STATUS) {
! 					/*port is linked to the non
! 					 * Auto-Negotiation10Mbs partner
! 			 	 	 */
  					return EPIC_HALF_DUPLEX;
  				}
  			}
  		}
! 		/* If we get here we are most likely not connected
! 		 * so lets default it to half duplex
! 		 */
! 		return EPIC_HALF_DUPLEX;
  	}
! 	
  }
  
  /*
--- 973,1050 ----
  	 * This is the recommended time from the DP83840A data sheet
  	 * Section 7.1
           */
  
  	epic_read_phy_register( sc->iobase, DP83840_BMSR);
  	i = epic_read_phy_register( sc->iobase, DP83840_BMSR);
! 	for(;;) {
!         	if ((i & BMSR_LINK_STATUS) && ( i & BMSR_AUTONEG_COMPLETE)){
! 			/* Auto negotiation finished!*/
! 			i = epic_read_phy_register( sc->iobase, DP83840_PAR);
  
! 			if ( i & PAR_FULL_DUPLEX ) {
! 				return 	EPIC_FULL_DUPLEX;
  			}
  			else {
! 				return EPIC_HALF_DUPLEX;
! 			}
! 		}
! 		else {
! 			/*Auto-negotiation or link status is not 1
! 		   	Thus the auto-negotiation failed and one
! 		   	must take other means to fix it.
! 		  	*/
! 
! 			/* ANER must be read twice to get the correct reading  
! 		 	* from theMultiple link fault bit -- it is a latched 
! 		          bit
! 	 	 	*/
!  			epic_read_phy_register (sc->iobase, DP83840_ANER);
! 
! 			i = epic_read_phy_register (sc->iobase, DP83840_ANER);
! 	
! 			if ( i & ANER_MULTIPLE_LINK_FAULT ) {
! 				/* it can be forced to 100Mb/s Half-Duplex */
! 	 			media = epic_read_phy_register(sc->iobase,DP83840_BMCR);
! 				media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX);
! 				media |= BMCR_100MBPS;
! 				epic_write_phy_register(sc->iobase,DP83840_BMCR,media);
! 		
! 				/* read BMSR again to determine link status */
  				epic_read_phy_register(sc->iobase, DP83840_BMSR);
  				i=epic_read_phy_register( sc->iobase, DP83840_BMSR);
! 		
! 				if (i & BMSR_LINK_STATUS){
! 					/* port is linked to the non 
! 				 	* Auto-Negotiation 100Mbs partner.
! 			 	 	*/
  					return EPIC_HALF_DUPLEX;
  				}
+ 				else {
+ 					media = epic_read_phy_register (sc->iobase, DP83840_BMCR);
+ 					media &= !(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX | BMCR_100MBPS);
+ 					epic_write_phy_register(sc->iobase, DP83840_BMCR, media);
+ 					epic_read_phy_register(sc->iobase, DP83840_BMSR);
+ 					i=epic_read_phy_register( sc->iobase, DP83840_BMSR);
+ 
+ 					if (i & BMSR_LINK_STATUS) {
+ 						/*port is linked to the non
+ 					 	* Auto-Negotiation10Mbs partner
+ 			 	 	 	*/
+ 						return EPIC_HALF_DUPLEX;
+ 					}
+ 					else {
+ 						break;
+ 					}
+ 				}
  			}
  		}
! 	epic_read_phy_register( sc->iobase, DP83840_BMSR);
! 	i = epic_read_phy_register( sc->iobase, DP83840_BMSR);
  	}
!     /* If we get here we are most likely not connected
!      * so lets default it to half duplex
!      */
!     return EPIC_HALF_DUPLEX;
  }
  
  /*
***************
*** 1058,1063 ****
--- 1066,1079 ----
  	return;
  }
  
+ static void
+ epic_shutdown(
+     int howto,
+     void *sc)
+ {
+     epic_stop(sc);
+ }
+ 	
  /*
   *  This function should completely stop rx and tx processes
   *  
***************
*** 1093,1099 ****
  
  	/* Reset chip */
  	outl( iobase + GENCTL, GENCTL_SOFT_RESET );
! 	for(i=0;i<0x100;i++);
  
  	/* Free memory allocated for rings */
  	epic_free_rings( sc );
--- 1109,1117 ----
  
  	/* Reset chip */
  	outl( iobase + GENCTL, GENCTL_SOFT_RESET );
! 
! 	/* need to wait for 15 pci ticks to pass before accessing again*/
! 	DELAY(1);
  
  	/* Free memory allocated for rings */
  	epic_free_rings( sc );
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802100217.TAA00487>