From owner-svn-src-projects@FreeBSD.ORG Fri May 24 03:58:32 2013 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 2474268A; Fri, 24 May 2013 03:58:32 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 1783F76E; Fri, 24 May 2013 03:58:32 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r4O3wVk7026184; Fri, 24 May 2013 03:58:31 GMT (envelope-from jhibbits@svn.freebsd.org) Received: (from jhibbits@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r4O3wVw5026183; Fri, 24 May 2013 03:58:31 GMT (envelope-from jhibbits@svn.freebsd.org) Message-Id: <201305240358.r4O3wVw5026183@svn.freebsd.org> From: Justin Hibbits Date: Fri, 24 May 2013 03:58:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r250956 - projects/pmac_pmu/sys/kern X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 May 2013 03:58:32 -0000 Author: jhibbits Date: Fri May 24 03:58:31 2013 New Revision: 250956 URL: http://svnweb.freebsd.org/changeset/base/250956 Log: Add multipass for suspend/resume. This allows some devices to be resumed before others, even their peers, as required by PowerPC Mac hardware. Modified: projects/pmac_pmu/sys/kern/subr_bus.c Modified: projects/pmac_pmu/sys/kern/subr_bus.c ============================================================================== --- projects/pmac_pmu/sys/kern/subr_bus.c Fri May 24 03:56:40 2013 (r250955) +++ projects/pmac_pmu/sys/kern/subr_bus.c Fri May 24 03:58:31 2013 (r250956) @@ -86,6 +86,7 @@ struct devclass { device_t *devices; /* array of devices indexed by unit */ int maxunit; /* size of devices array */ int flags; + int pass; #define DC_HAS_CHILDREN 1 struct sysctl_ctx_list sysctl_ctx; @@ -130,6 +131,7 @@ struct device { #define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */ #define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */ #define DF_REBID 0x80 /* Can rebid after attach */ +#define DF_SUSPENDED 0x100 /* Device is suspended. */ u_int order; /**< order from device_add_child_ordered() */ void *ivars; /**< instance variables */ void *softc; /**< current driver's variables */ @@ -1079,6 +1081,7 @@ devclass_add_driver(devclass_t dc, drive TAILQ_INSERT_TAIL(&dc->drivers, dl, link); driver->refs++; /* XXX: kobj_mtx */ dl->pass = pass; + (*dcp)->pass = pass; /* Used in suspend/resume. */ driver_register_pass(dl); devclass_driver_added(dc, driver); @@ -3532,19 +3535,29 @@ int bus_generic_suspend(device_t dev) { int error; + int again = 0; device_t child, child2; TAILQ_FOREACH(child, &dev->children, link) { - error = DEVICE_SUSPEND(child); - if (error) { - for (child2 = TAILQ_FIRST(&dev->children); - child2 && child2 != child; - child2 = TAILQ_NEXT(child2, link)) - DEVICE_RESUME(child2); - return (error); + if (!(child->flags & DF_SUSPENDED)) { + error = DEVICE_SUSPEND(child); + if (error && error != EAGAIN) { + for (child2 = TAILQ_FIRST(&dev->children); + child2 && child2 != child; + child2 = TAILQ_NEXT(child2, link)) { + DEVICE_RESUME(child2); + child2->flags &= ~DF_SUSPENDED; + } + return (error); + } + if (error == EAGAIN) { + again = EAGAIN; + continue; + } + child->flags |= DF_SUSPENDED; } } - return (0); + return (again); } /** @@ -3557,12 +3570,31 @@ int bus_generic_resume(device_t dev) { device_t child; + int error = 0; TAILQ_FOREACH(child, &dev->children, link) { - DEVICE_RESUME(child); - /* if resume fails, there's nothing we can usefully do... */ + if (child->flags & DF_SUSPENDED) { + if (child->devclass->pass > bus_current_pass) { + if (bootverbose) + printf("Skipping: %s: %d, %d\n", + child->nameunit, + child->devclass->pass, + bus_current_pass); + error = EAGAIN; + continue; + } + if (DEVICE_RESUME(child) == EAGAIN) { + error = EAGAIN; + continue; + } + /* if resume fails, there's nothing we can usefully do... */ + child->flags &= ~DF_SUSPENDED; + } + else + if (bootverbose) + printf("Skipping %s: already resumed\n", child->nameunit); } - return (0); + return (error); } /** @@ -4367,15 +4399,39 @@ bus_get_dma_tag(device_t dev) static int root_resume(device_t dev) { - int error; + struct driverlink *dl; + int error = 0; + + TAILQ_FOREACH(dl, &passes, passlink) { + bus_current_pass = dl->pass; + error = bus_generic_resume(dev); + + if (error != EAGAIN) + break; + } - error = bus_generic_resume(dev); if (error == 0) devctl_notify("kern", "power", "resume", NULL); return (error); } static int +root_suspend(device_t dev) +{ + struct driverlink *dl; + int error = 0; + + TAILQ_FOREACH_REVERSE(dl, &passes, driver_list, passlink) { + bus_current_pass = dl->pass; + error = bus_generic_suspend(dev); + if (error != EAGAIN) + break; + } + + return (error); +} + +static int root_print_child(device_t dev, device_t child) { int retval = 0; @@ -4412,7 +4468,7 @@ root_child_present(device_t dev, device_ static kobj_method_t root_methods[] = { /* Device interface */ KOBJMETHOD(device_shutdown, bus_generic_shutdown), - KOBJMETHOD(device_suspend, bus_generic_suspend), + KOBJMETHOD(device_suspend, root_suspend), KOBJMETHOD(device_resume, root_resume), /* Bus interface */