Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jun 2014 15:15:19 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        Edward Tomasz =?utf-8?q?Napiera=C5=82a?= <trasz@freebsd.org>
Cc:        jhibbits@freebsd.org, freebsd-current@freebsd.org
Subject:   Re: [patch] USB after second suspend/resume on ThinkPads.
Message-ID:  <201406181515.19927.jhb@freebsd.org>
In-Reply-To: <20140618184609.GA1297@brick.home>
References:  <20140616192155.GE13481@brick.home> <201406181303.09834.jhb@freebsd.org> <20140618184609.GA1297@brick.home>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday, June 18, 2014 2:46:09 pm Edward Tomasz Napiera=C5=82a wrote:
> On 0618T1303, John Baldwin wrote:
> > On Wednesday, June 18, 2014 12:13:15 pm Edward Tomasz Napiera=C5=82a wr=
ote:
> > > On 0618T0947, John Baldwin wrote:
> > > > On Monday, June 16, 2014 3:21:55 pm Edward Tomasz Napiera=C5=82a wr=
ote:
> > > > > Hi.  Patch below should fix a problem where USB stops working aft=
er
> > > > > _second_ suspend/resume, which happens on various ThinkPad models.
> > > > > Please test, and report both success stories and failures.  If no=
thing
> > > > > comes up, I'll commit it in a week or so.
> > > >=20
> > > > Good find.  Have you thought about a more generic fix for this wher=
ein you=20
> > > > track power resources and flip them on during resume in ACPI before=
 doing
> > > > DEVICE_RESUME() on the root bus?
> > >=20
> > > Thing is, after resume this device claims to be on already.  The foll=
owing
> > > simple hack was enough to make it work:
> >=20
> > Ahh, I think I see.  Try this instead:
> >=20
> > Index: sys/dev/acpica/acpi_powerres.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- acpi_powerres.c	(revision 267550)
> > +++ acpi_powerres.c	(working copy)
> > @@ -645,7 +645,7 @@ acpi_pwr_switch_power(void)
> >  			      acpi_name(rp->ap_resource), status));
> >  	    /* XXX is this correct?  Always switch if in doubt? */
> >  	    continue;
> > -	} else if (rp->ap_state =3D=3D ACPI_PWR_UNK)
> > +	} else
> >  	    rp->ap_state =3D cur;
> > =20
> >  	/*
> > @@ -689,7 +689,7 @@ acpi_pwr_switch_power(void)
> >  			      acpi_name(rp->ap_resource), status));
> >  	    /* XXX is this correct?  Always switch if in doubt? */
> >  	    continue;
> > -	} else if (rp->ap_state =3D=3D ACPI_PWR_UNK)
> > +	} else
> >  	    rp->ap_state =3D cur;
> > =20
> >  	/*
> >=20
> > (We were ignoring what _STA told us and believed it was ON because we h=
ad
> >  cached that state previously.)
>=20
> Works!

Hmmm.  If we go this route, ap_state is actually useless and should just be
removed.  Here is an updated version that does that.  If this works as well
then this is probably a commit candidate.

Index: acpi_powerres.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
=2D-- acpi_powerres.c	(revision 267550)
+++ acpi_powerres.c	(working copy)
@@ -64,7 +64,6 @@ ACPI_MODULE_NAME("POWERRES")
 /* Return values from _STA on a power resource */
 #define ACPI_PWR_OFF	0
 #define ACPI_PWR_ON	1
=2D#define ACPI_PWR_UNK	(-1)
=20
 /* A relationship between a power resource and a consumer. */
 struct acpi_powerreference {
@@ -90,7 +89,6 @@ struct acpi_powerresource {
     ACPI_HANDLE				ap_resource;
     UINT64				ap_systemlevel;
     UINT64				ap_order;
=2D    int					ap_state;
 };
=20
 static TAILQ_HEAD(acpi_powerresource_list, acpi_powerresource)
@@ -173,7 +171,6 @@ acpi_pwr_register_resource(ACPI_HANDLE res)
     }
     rp->ap_systemlevel =3D obj->PowerResource.SystemLevel;
     rp->ap_order =3D obj->PowerResource.ResourceOrder;
=2D    rp->ap_state =3D ACPI_PWR_UNK;
    =20
     /* Sort the resource into the list */
     status =3D AE_OK;
@@ -638,7 +635,6 @@ acpi_pwr_switch_power(void)
 	    continue;
 	}
=20
=2D	/* We could cache this if we trusted it not to change under us */
 	status =3D acpi_GetInteger(rp->ap_resource, "_STA", &cur);
 	if (ACPI_FAILURE(status)) {
 	    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n",
@@ -645,8 +641,7 @@ acpi_pwr_switch_power(void)
 			      acpi_name(rp->ap_resource), status));
 	    /* XXX is this correct?  Always switch if in doubt? */
 	    continue;
=2D	} else if (rp->ap_state =3D=3D ACPI_PWR_UNK)
=2D	    rp->ap_state =3D cur;
+	}
=20
 	/*
 	 * Switch if required.  Note that we ignore the result of the switch
@@ -653,7 +648,7 @@ acpi_pwr_switch_power(void)
 	 * effort; we don't know what to do if it fails, so checking wouldn't
 	 * help much.
 	 */
=2D	if (rp->ap_state !=3D ACPI_PWR_ON) {
+	if (cur !=3D ACPI_PWR_ON) {
 	    status =3D AcpiEvaluateObject(rp->ap_resource, "_ON", NULL, NULL);
 	    if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
@@ -661,7 +656,6 @@ acpi_pwr_switch_power(void)
 				 acpi_name(rp->ap_resource),
 				 AcpiFormatException(status)));
 	    } else {
=2D		rp->ap_state =3D ACPI_PWR_ON;
 		ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s on\n",
 				 acpi_name(rp->ap_resource)));
 	    }
@@ -682,7 +676,6 @@ acpi_pwr_switch_power(void)
 	    continue;
 	}
=20
=2D	/* We could cache this if we trusted it not to change under us */
 	status =3D acpi_GetInteger(rp->ap_resource, "_STA", &cur);
 	if (ACPI_FAILURE(status)) {
 	    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get status of %s - %d\n",
@@ -689,8 +682,7 @@ acpi_pwr_switch_power(void)
 			      acpi_name(rp->ap_resource), status));
 	    /* XXX is this correct?  Always switch if in doubt? */
 	    continue;
=2D	} else if (rp->ap_state =3D=3D ACPI_PWR_UNK)
=2D	    rp->ap_state =3D cur;
+	}
=20
 	/*
 	 * Switch if required.  Note that we ignore the result of the switch
@@ -697,7 +689,7 @@ acpi_pwr_switch_power(void)
 	 * effort; we don't know what to do if it fails, so checking wouldn't
 	 * help much.
 	 */
=2D	if (rp->ap_state !=3D ACPI_PWR_OFF) {
+	if (cur !=3D ACPI_PWR_OFF) {
 	    status =3D AcpiEvaluateObject(rp->ap_resource, "_OFF", NULL, NULL);
 	    if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
@@ -705,7 +697,6 @@ acpi_pwr_switch_power(void)
 				 acpi_name(rp->ap_resource),
 				 AcpiFormatException(status)));
 	    } else {
=2D		rp->ap_state =3D ACPI_PWR_OFF;
 		ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "switched %s off\n",
 				 acpi_name(rp->ap_resource)));
 	    }


=2D-=20
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406181515.19927.jhb>