Module Name:    src
Committed By:   martin
Date:           Sat Apr  6 16:50:48 UTC 2013

Modified Files:
        src/sys/dev/ic: athn.c athnvar.h

Log Message:
Fix return type and value of athn_resume (true for success, not 0 for no
error).
Avoid endless recursion in athn_init when the device had been suspended
via pmf_device_recursive_resume -> athn_resume -> athn_init.
Avoid touching the hardware when the device is not fully powered up yet.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/athn.c src/sys/dev/ic/athnvar.h

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

Modified files:

Index: src/sys/dev/ic/athn.c
diff -u src/sys/dev/ic/athn.c:1.3 src/sys/dev/ic/athn.c:1.4
--- src/sys/dev/ic/athn.c:1.3	Sat Apr  6 14:57:38 2013
+++ src/sys/dev/ic/athn.c	Sat Apr  6 16:50:48 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: athn.c,v 1.3 2013/04/06 14:57:38 martin Exp $	*/
+/*	$NetBSD: athn.c,v 1.4 2013/04/06 16:50:48 martin Exp $	*/
 /*	$OpenBSD: athn.c,v 1.75 2013/01/14 09:50:31 jsing Exp $	*/
 
 /*-
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: athn.c,v 1.3 2013/04/06 14:57:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: athn.c,v 1.4 2013/04/06 16:50:48 martin Exp $");
 
 #ifndef _MODULE
 #include "athn_usb.h"		/* for NATHN_USB */
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: athn.c,v 1.3
 #include <sys/queue.h>
 #include <sys/callout.h>
 #include <sys/conf.h>
+#include <sys/cpu.h>
 #include <sys/device.h>
 
 #include <sys/bus.h>
@@ -527,6 +528,13 @@ athn_intr(void *xsc)
 	if (!IS_UP_AND_RUNNING(ifp))
 		return 0;
 
+	if (!device_activation(sc->sc_dev, DEVACT_LEVEL_DRIVER))
+		/*
+		 * The hardware is not ready/present, don't touch anything.
+		 * Note this can happen early on if the IRQ is shared.
+		 */
+		return 0;
+
 	return sc->sc_ops.intr(sc);
 }
 
@@ -2605,7 +2613,8 @@ athn_start(struct ifnet *ifp)
 	struct ieee80211_node *ni;
 	struct mbuf *m;
 
-	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING
+	    || !device_is_active(sc->sc_dev))
 		return;
 
 	for (;;) {
@@ -2806,11 +2815,22 @@ athn_init(struct ifnet *ifp)
 	size_t i;
 	int error;
 
-	if (device_is_active(sc->sc_dev))
+	KASSERT(!cpu_intr_p());
+
+	if (device_is_active(sc->sc_dev)) {
 		athn_stop(ifp, 0);	/* XXX: necessary? */
-	else if (!pmf_device_subtree_resume(sc->sc_dev, &sc->sc_qual) ||
-	    !device_is_active(sc->sc_dev))
-		return 0;
+	} else {
+		short flags = ifp->if_flags;
+		ifp->if_flags &= ~IFF_UP;
+		/* avoid recursion in athn_resume */
+		if (!pmf_device_subtree_resume(sc->sc_dev, &sc->sc_qual) ||
+		    !device_is_active(sc->sc_dev)) {
+			printf("%s: failed to power up device\n",
+			    device_xname(sc->sc_dev));
+			return 0;
+		}
+		ifp->if_flags = flags;
+	}
 
 	curchan = ic->ic_curchan;
 	extchan = NULL;
@@ -2977,12 +2997,13 @@ athn_suspend(struct athn_softc *sc)
 		athn_stop(ifp, 1);
 }
 
-PUBLIC int
+PUBLIC bool
 athn_resume(struct athn_softc *sc)
 {
 	struct ifnet *ifp = &sc->sc_if;
 
 	if (ifp->if_flags & IFF_UP)
-		return athn_init(ifp);
-	return 0;
+		athn_init(ifp);
+
+	return true;
 }
Index: src/sys/dev/ic/athnvar.h
diff -u src/sys/dev/ic/athnvar.h:1.3 src/sys/dev/ic/athnvar.h:1.4
--- src/sys/dev/ic/athnvar.h:1.3	Wed Apr  3 14:20:03 2013
+++ src/sys/dev/ic/athnvar.h	Sat Apr  6 16:50:48 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: athnvar.h,v 1.3 2013/04/03 14:20:03 christos Exp $	*/
+/*	$NetBSD: athnvar.h,v 1.4 2013/04/06 16:50:48 martin Exp $	*/
 /*	$OpenBSD: athnvar.h,v 1.33 2012/10/20 09:54:20 stsp Exp $	*/
 
 /*-
@@ -621,7 +621,7 @@ struct athn_softc {
 int	athn_attach(struct athn_softc *);
 void	athn_detach(struct athn_softc *);
 void	athn_suspend(struct athn_softc *);
-int	athn_resume(struct athn_softc *);
+bool	athn_resume(struct athn_softc *);
 int	athn_intr(void *);
 
 /* used by if_athn_usb.c */

Reply via email to