From owner-svn-src-all@FreeBSD.ORG Wed Sep 7 16:57:44 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4E32F106564A; Wed, 7 Sep 2011 16:57:44 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 32C3E8FC0A; Wed, 7 Sep 2011 16:57:44 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p87Gviog048309; Wed, 7 Sep 2011 16:57:44 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p87GviWT048306; Wed, 7 Sep 2011 16:57:44 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201109071657.p87GviWT048306@svn.freebsd.org> From: Pyun YongHyeon Date: Wed, 7 Sep 2011 16:57:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r225440 - head/sys/dev/vge X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Sep 2011 16:57:44 -0000 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 */