Module Name:    src
Committed By:   nonaka
Date:           Fri Jan 16 07:48:16 UTC 2015

Modified Files:
        src/sys/arch/powerpc/booke/dev: pq3etsec.c

Log Message:
Fix various conditions with setting IMASK.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/powerpc/booke/dev/pq3etsec.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/powerpc/booke/dev/pq3etsec.c
diff -u src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.22 src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.23
--- src/sys/arch/powerpc/booke/dev/pq3etsec.c:1.22	Fri Jan 16 06:38:27 2015
+++ src/sys/arch/powerpc/booke/dev/pq3etsec.c	Fri Jan 16 07:48:16 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pq3etsec.c,v 1.22 2015/01/16 06:38:27 nonaka Exp $	*/
+/*	$NetBSD: pq3etsec.c,v 1.23 2015/01/16 07:48:16 nonaka Exp $	*/
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v 1.22 2015/01/16 06:38:27 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pq3etsec.c,v 1.23 2015/01/16 07:48:16 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -212,6 +212,7 @@ struct pq3etsec_softc {
 	void *sc_soft_ih;
 
 	kmutex_t *sc_lock;
+	kmutex_t *sc_hwlock;
 
 	struct evcnt sc_ev_tx_stall;
 	struct evcnt sc_ev_tx_intr;
@@ -617,14 +618,14 @@ pq3etsec_attach(device_t parent, device_
 #endif
 	}
 
-	char enaddr[ETHER_ADDR_LEN] = {
-	    [0] = sc->sc_macstnaddr2 >> 16,
-	    [1] = sc->sc_macstnaddr2 >> 24,
-	    [2] = sc->sc_macstnaddr1 >>  0,
-	    [3] = sc->sc_macstnaddr1 >>  8,
-	    [4] = sc->sc_macstnaddr1 >> 16,
-	    [5] = sc->sc_macstnaddr1 >> 24,
-	};
+	sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET);
+	sc->sc_hwlock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
+
+	callout_init(&sc->sc_mii_callout, CALLOUT_MPSAFE);
+	callout_setfunc(&sc->sc_mii_callout, pq3etsec_mii_tick, sc);
+
+	/* Disable interrupts */
+	etsec_write(sc, IMASK, 0);
 
 	error = pq3etsec_rxq_attach(sc, &sc->sc_rxq, 0);
 	if (error) {
@@ -704,11 +705,14 @@ pq3etsec_attach(device_t parent, device_
 	etsec_write(sc, ATTR, ATTR_DEFAULT);
 	etsec_write(sc, ATTRELI, ATTRELI_DEFAULT);
 
-	sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SOFTNET);
-
-	callout_init(&sc->sc_mii_callout, CALLOUT_MPSAFE);
-	callout_setfunc(&sc->sc_mii_callout, pq3etsec_mii_tick, sc);
-
+	char enaddr[ETHER_ADDR_LEN] = {
+	    [0] = sc->sc_macstnaddr2 >> 16,
+	    [1] = sc->sc_macstnaddr2 >> 24,
+	    [2] = sc->sc_macstnaddr1 >>  0,
+	    [3] = sc->sc_macstnaddr1 >>  8,
+	    [4] = sc->sc_macstnaddr1 >> 16,
+	    [5] = sc->sc_macstnaddr1 >> 24,
+	};
 	aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
 	   ether_sprintf(enaddr));
 
@@ -2261,6 +2265,10 @@ pq3etsec_ifstart(struct ifnet *ifp)
 {
 	struct pq3etsec_softc * const sc = ifp->if_softc;
 
+	if (__predict_false((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) {
+		return;
+	}
+
 	atomic_or_uint(&sc->sc_soft_flags, SOFT_TXINTR);
 	softint_schedule(sc->sc_soft_ih);
 }
@@ -2294,6 +2302,8 @@ pq3etsec_tx_intr(void *arg)
 {
 	struct pq3etsec_softc * const sc = arg;
 
+	mutex_enter(sc->sc_hwlock);
+
 	sc->sc_ev_tx_intr.ev_count++;
 
 	uint32_t ievent = etsec_read(sc, IEVENT);
@@ -2305,13 +2315,18 @@ pq3etsec_tx_intr(void *arg)
 	    __func__, ievent, etsec_read(sc, IMASK));
 #endif
 
-	if (ievent == 0)
+	if (ievent == 0) {
+		mutex_exit(sc->sc_hwlock);
 		return 0;
+	}
 
 	sc->sc_imask &= ~(IEVENT_TXF|IEVENT_TXB);
 	atomic_or_uint(&sc->sc_soft_flags, SOFT_TXINTR);
 	etsec_write(sc, IMASK, sc->sc_imask);
 	softint_schedule(sc->sc_soft_ih);
+
+	mutex_exit(sc->sc_hwlock);
+
 	return 1;
 }
 
@@ -2320,13 +2335,17 @@ pq3etsec_rx_intr(void *arg)
 {
 	struct pq3etsec_softc * const sc = arg;
 
+	mutex_enter(sc->sc_hwlock);
+
 	sc->sc_ev_rx_intr.ev_count++;
 
 	uint32_t ievent = etsec_read(sc, IEVENT);
 	ievent &= IEVENT_RXF|IEVENT_RXB;
 	etsec_write(sc, IEVENT, ievent);	/* write 1 to clear */
-	if (ievent == 0)
+	if (ievent == 0) {
+		mutex_exit(sc->sc_hwlock);
 		return 0;
+	}
 
 #if 0
 	aprint_normal_dev(sc->sc_dev, "%s: ievent=%#x\n", __func__, ievent);
@@ -2336,6 +2355,9 @@ pq3etsec_rx_intr(void *arg)
 	atomic_or_uint(&sc->sc_soft_flags, SOFT_RXINTR);
 	etsec_write(sc, IMASK, sc->sc_imask);
 	softint_schedule(sc->sc_soft_ih);
+
+	mutex_exit(sc->sc_hwlock);
+
 	return 1;
 }
 
@@ -2344,6 +2366,8 @@ pq3etsec_error_intr(void *arg)
 {
 	struct pq3etsec_softc * const sc = arg;
 
+	mutex_enter(sc->sc_hwlock);
+
 	sc->sc_ev_error_intr.ev_count++;
 
 	for (int rv = 0, soft_flags = 0;; rv = 1) {
@@ -2355,6 +2379,7 @@ pq3etsec_error_intr(void *arg)
 				atomic_or_uint(&sc->sc_soft_flags, soft_flags);
 				softint_schedule(sc->sc_soft_ih);
 			}
+			mutex_exit(sc->sc_hwlock);
 			return rv;
 		}
 #if 0
@@ -2401,6 +2426,7 @@ pq3etsec_soft_intr(void *arg)
 {
 	struct pq3etsec_softc * const sc = arg;
 	struct ifnet * const ifp = &sc->sc_if;
+	uint32_t imask = 0;
 
 	mutex_enter(sc->sc_lock);
 
@@ -2421,7 +2447,7 @@ pq3etsec_soft_intr(void *arg)
 		if (threshold >= rxq->rxq_last - rxq->rxq_first) {
 			threshold = rxq->rxq_last - rxq->rxq_first - 1;
 		} else {
-			sc->sc_imask |= IEVENT_BSY;
+			imask |= IEVENT_BSY;
 		}
 		aprint_normal_dev(sc->sc_dev,
 		    "increasing receive buffers from %zu to %zu\n",
@@ -2442,7 +2468,7 @@ pq3etsec_soft_intr(void *arg)
 		} else {
 			ifp->if_flags &= ~IFF_OACTIVE;
 		}
-		sc->sc_imask |= IEVENT_TXF;
+		imask |= IEVENT_TXF;
 	}
 
 	if (soft_flags & (SOFT_RXINTR|SOFT_RXBSY)) {
@@ -2450,17 +2476,20 @@ pq3etsec_soft_intr(void *arg)
 		 * Let's consume 
 		 */
 		pq3etsec_rxq_consume(sc, &sc->sc_rxq);
-		sc->sc_imask |= IEVENT_RXF;
+		imask |= IEVENT_RXF;
 	}
 
 	if (soft_flags & SOFT_TXERROR) {
 		pq3etsec_tx_error(sc);
-		sc->sc_imask |= IEVENT_TXE;
+		imask |= IEVENT_TXE;
 	}
 
 	if (ifp->if_flags & IFF_RUNNING) {
 		pq3etsec_rxq_produce(sc, &sc->sc_rxq);
+		mutex_spin_enter(sc->sc_hwlock);
+		sc->sc_imask |= imask;
 		etsec_write(sc, IMASK, sc->sc_imask);
+		mutex_spin_exit(sc->sc_hwlock);
 	} else {
 		KASSERT((soft_flags & SOFT_RXBSY) == 0);
 	}

Reply via email to