IBM T42 freezes when going to sleep under X11

Gleb Smirnoff glebius at FreeBSD.org
Sat Dec 3 08:53:02 GMT 2005


On Fri, Dec 02, 2005 at 12:52:58PM -0800, George Hartzell wrote:
G>  > I finally found the cause of my problems: there has been changes in
G>  > the em driver (Gb ethernet), such that the machine freezes when trying
G>  > to switch automatically from the X11 VT to the system console, before
G>  > going to sleep. The interaction is surprising, but clearly the problem
G>  > disappears when I remove "device em" from the kernel configuration,
G>  > and it reappears when I do "kldload if_em". Since I'm using only ath
G>  > (wireless) anyway, this is fine with me...
G>  > 
G>  > A previous partial solution suggested to me was to add
G>  >   hw.syscons.sc_no_suspend_vtswitch=1
G>  > to sysctl.conf, but this means the screen gets garbled and I have to
G>  > do the switch by hand anyway, which is a real pain.
G>  > Worse still: the machine would still freeze when going to sleep while
G>  > the disk is active.
G>  > 
G>  > The last step is to track down the bug in em, as it still seems to
G>  > be there in yesterday's STABLE.
G> 
G> I don't seem to have any problem with my T42p using a kernel compiled
G> on 11/29 11:21
G> 
G> My copy of if_em.c is:
G> 
G> /*$FreeBSD: src/sys/dev/em/if_em.c,v 1.65.2.8 2005/11/25 14:11:59 glebius Exp $*/

George, Jacques,

what em(4) cards exactly do you have?

pciconf -lv | grep -A4 ^em

Can you please try the attached patch?

-- 
Totus tuus, Glebius.
GLEBIUS-RIPN GLEB-RIPE
-------------- next part --------------
Index: if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.85
diff -u -r1.85 if_em.c
--- if_em.c	10 Nov 2005 11:44:37 -0000	1.85
+++ if_em.c	11 Nov 2005 12:13:48 -0000
@@ -129,8 +129,11 @@
 static int  em_attach(device_t);
 static int  em_detach(device_t);
 static int  em_shutdown(device_t);
+static int  em_suspend(device_t);
+static int  em_resume(device_t);
 static void em_intr(void *);
 static void em_start(struct ifnet *);
+static void em_start_locked(struct ifnet *ifp);
 static int  em_ioctl(struct ifnet *, u_long, caddr_t);
 static void em_watchdog(struct ifnet *);
 static void em_init(void *);
@@ -208,6 +211,8 @@
 	DEVMETHOD(device_attach, em_attach),
 	DEVMETHOD(device_detach, em_detach),
 	DEVMETHOD(device_shutdown, em_shutdown),
+	DEVMETHOD(device_suspend, em_suspend),
+	DEVMETHOD(device_resume, em_resume),
 	{0, 0}
 };
 
@@ -580,6 +585,41 @@
 	return(0);
 }
 
+/*
+ * Suspend/resume device methods.
+ */
+static int
+em_suspend(device_t dev)
+{
+	struct adapter *adapter = device_get_softc(dev);
+
+	EM_LOCK(adapter);
+	em_stop(adapter);
+	EM_UNLOCK(adapter);
+
+	return bus_generic_suspend(dev);
+}
+
+static int
+em_resume(device_t dev)
+{
+	struct adapter *adapter = device_get_softc(dev);
+	struct ifnet *ifp;
+
+	EM_LOCK(adapter);
+	ifp = adapter->ifp;
+	if (ifp->if_flags & IFF_UP) {
+		em_init_locked(adapter);
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			em_start_locked(ifp);
+	}
+
+	em_init_locked(adapter);
+	EM_UNLOCK(adapter);
+
+	return bus_generic_resume(dev);
+}
+
 
 /*********************************************************************
  *  Transmit entry point


More information about the freebsd-mobile mailing list