svn commit: r225440 - head/sys/dev/vge

Pyun YongHyeon yongari at FreeBSD.org
Wed Sep 7 16:57:44 UTC 2011


Author: yongari
Date: Wed Sep  7 16:57:43 2011
New Revision: 225440
URL: http://svn.freebsd.org/changeset/base/225440

Log:
  vge(4) hardwares poll media status and generates an interrupt
  whenever the link state is changed.  Using software based polling
  for media status tracking is known to cause MII access failure
  under certain conditions once link is established so vge(4) used to
  rely on link status change interrupt.
  However DEVICE_POLLING completely disables generation of all kind
  of interrupts on vge(4) such that this resulted in not detecting
  link state change event.  This means vge(4) does not correctly
  detect established/lost link with DEVICE_POLLING.  Losing the
  interrupt made vge(4) not to send any packets to peer since vge(4)
  does not try to send any packets when there is no established link.
  
  Work around the issue by generating link state change interrupt
  with DEVICE_POLLING.
  
  PR:		kern/160442
  Approved by:	re (kib)

Modified:
  head/sys/dev/vge/if_vge.c
  head/sys/dev/vge/if_vgereg.h

Modified: head/sys/dev/vge/if_vge.c
==============================================================================
--- head/sys/dev/vge/if_vge.c	Wed Sep  7 14:37:51 2011	(r225439)
+++ head/sys/dev/vge/if_vge.c	Wed Sep  7 16:57:43 2011	(r225440)
@@ -1752,6 +1752,10 @@ vge_intr(void *arg)
 
 #ifdef DEVICE_POLLING
 	if  (ifp->if_capenable & IFCAP_POLLING) {
+		status = CSR_READ_4(sc, VGE_ISR);
+		CSR_WRITE_4(sc, VGE_ISR, status);
+		if (status != 0xFFFFFFFF && (status & VGE_ISR_LINKSTS) != 0)
+			vge_link_statchg(sc);
 		VGE_UNLOCK(sc);
 		return;
 	}
@@ -2109,11 +2113,10 @@ vge_init_locked(struct vge_softc *sc)
 
 #ifdef DEVICE_POLLING
 	/*
-	 * Disable interrupts if we are polling.
+	 * Disable interrupts except link state change if we are polling.
 	 */
 	if (ifp->if_capenable & IFCAP_POLLING) {
-		CSR_WRITE_4(sc, VGE_IMR, 0);
-		CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK);
+		CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS_POLLING);
 	} else	/* otherwise ... */
 #endif
 	{
@@ -2121,9 +2124,9 @@ vge_init_locked(struct vge_softc *sc)
 	 * Enable interrupts.
 	 */
 		CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS);
-		CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
-		CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
 	}
+	CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
+	CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
 
 	sc->vge_flags &= ~VGE_FLAG_LINK;
 	mii_mediachg(mii);
@@ -2280,8 +2283,9 @@ vge_ioctl(struct ifnet *ifp, u_long comm
 					return (error);
 				VGE_LOCK(sc);
 					/* Disable interrupts */
-				CSR_WRITE_4(sc, VGE_IMR, 0);
-				CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK);
+				CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS_POLLING);
+				CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
+				CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
 				ifp->if_capenable |= IFCAP_POLLING;
 				VGE_UNLOCK(sc);
 			} else {

Modified: head/sys/dev/vge/if_vgereg.h
==============================================================================
--- head/sys/dev/vge/if_vgereg.h	Wed Sep  7 14:37:51 2011	(r225439)
+++ head/sys/dev/vge/if_vgereg.h	Wed Sep  7 16:57:43 2011	(r225440)
@@ -302,6 +302,8 @@
 			 VGE_ISR_LINKSTS|VGE_ISR_RXNODESC|		\
 			 VGE_ISR_RXDMA_STALL|VGE_ISR_TXDMA_STALL)
 
+#define VGE_INTRS_POLLING	(VGE_ISR_PHYINT|VGE_ISR_LINKSTS)
+
 /* Interrupt mask register */
 
 #define VGE_IMR_RXOK_HIPRIO	0x00000001 /* hi prio RX int */


More information about the svn-src-all mailing list