svn commit: r214711 - stable/7/sys/dev/bge

Pyun YongHyeon yongari at FreeBSD.org
Tue Nov 2 23:49:48 UTC 2010


Author: yongari
Date: Tue Nov  2 23:49:48 2010
New Revision: 214711
URL: http://svn.freebsd.org/changeset/base/214711

Log:
  MFC r213522,213587,213711:
  r213522:
    Fix a long standing bug which regarded some revisions of controller
    as 5788. This caused BGE_MISC_LOCAL_CTL register is used to
    generate link state change interrupt for non-5788 controllers. The
    interrupt handler may or may not detect link state attention as
    status block wouldn't be updated when an interrupt was generated
    with BGE_MISC_LOCAL_CTL register. All controllers except 5700 and
    5788 should use host coalescing mode register to trigger an
    interrupt.
  
  r213587:
    Do not blindly UP the interface when interface's MTU is changed. If
    driver is not running there is no need to up the interface. While
    I'm here hold driver lock before modifying MTU as it is referenced
    in RX handler.
  
  r213711:
    The IFF_DRV_RUNNING flag is set at the end of bge_init_locked. But
    before setting the flag, interrupt was already enabled such that
    interrupt handler could be run before setting IFF_DRV_RUNNING flag.
    This can lose initial link state change interrupt which in turn
    make bge(4) think that it still does not have valid link. Fix this
    race by protecting the taskqueue with a driver lock.
    While I'm here move reenabling interrupt code after handling of link
    state chage.
  
    Reviewed by:	davidch

Modified:
  stable/7/sys/dev/bge/if_bge.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/bge/if_bge.c
==============================================================================
--- stable/7/sys/dev/bge/if_bge.c	Tue Nov  2 23:48:08 2010	(r214710)
+++ stable/7/sys/dev/bge/if_bge.c	Tue Nov  2 23:49:48 2010	(r214711)
@@ -2665,14 +2665,12 @@ bge_attach(device_t dev)
 	if (BGE_IS_5755_PLUS(sc) == 0)
 		sc->bge_flags |= BGE_FLAG_4G_BNDRY_BUG;
 
-	/*
-	 * We could possibly check for BCOM_DEVICEID_BCM5788 in bge_probe()
-	 * but I do not know the DEVICEID for the 5788M.
-	 */
-	misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID;
-	if (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
-	    misccfg == BGE_MISCCFG_BOARD_ID_5788M)
-		sc->bge_flags |= BGE_FLAG_5788;
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5705) {
+		misccfg = CSR_READ_4(sc, BGE_MISC_CFG) & BGE_MISCCFG_BOARD_ID;
+		if (misccfg == BGE_MISCCFG_BOARD_ID_5788 ||
+		    misccfg == BGE_MISCCFG_BOARD_ID_5788M)
+			sc->bge_flags |= BGE_FLAG_5788;
+	}
 
 	/*
 	 * Some controllers seem to require a special firmware to use
@@ -3634,8 +3632,11 @@ bge_intr_task(void *arg, int pending)
 	sc = (struct bge_softc *)arg;
 	ifp = sc->bge_ifp;
 
-	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+	BGE_LOCK(sc);
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+		BGE_UNLOCK(sc);
 		return;
+	}
 
 	/* Get updated status block. */
 	bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
@@ -3650,26 +3651,27 @@ bge_intr_task(void *arg, int pending)
 	bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
 	    sc->bge_cdata.bge_status_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+	if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) != 0)
+		bge_link_upd(sc);
+
 	/* Let controller work. */
 	bge_writembx(sc, BGE_MBX_IRQ0_LO, 0);
 
-	if ((status & BGE_STATFLAG_LINKSTATE_CHANGED) != 0) {
-		BGE_LOCK(sc);
-		bge_link_upd(sc);
-		BGE_UNLOCK(sc);
-	}
-	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+	    sc->bge_rx_saved_considx != rx_prod) {
 		/* Check RX return ring producer/consumer. */
+		BGE_UNLOCK(sc);
 		bge_rxeof(sc, rx_prod, 0);
+		BGE_LOCK(sc);
 	}
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-		BGE_LOCK(sc);
 		/* Check TX ring producer/consumer. */
 		bge_txeof(sc, tx_cons);
 	    	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 			bge_start_locked(ifp);
-		BGE_UNLOCK(sc);
 	}
+	BGE_UNLOCK(sc);
 }
 
 static void
@@ -4640,6 +4642,7 @@ bge_ioctl(struct ifnet *ifp, u_long comm
 
 	switch (command) {
 	case SIOCSIFMTU:
+		BGE_LOCK(sc);
 		if (ifr->ifr_mtu < ETHERMIN ||
 		    ((BGE_IS_JUMBO_CAPABLE(sc)) &&
 		    ifr->ifr_mtu > BGE_JUMBO_MTU) ||
@@ -4648,9 +4651,12 @@ bge_ioctl(struct ifnet *ifp, u_long comm
 			error = EINVAL;
 		else if (ifp->if_mtu != ifr->ifr_mtu) {
 			ifp->if_mtu = ifr->ifr_mtu;
-			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-			bge_init(sc);
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+				bge_init_locked(sc);
+			}
 		}
+		BGE_UNLOCK(sc);
 		break;
 	case SIOCSIFFLAGS:
 		BGE_LOCK(sc);


More information about the svn-src-stable-7 mailing list