From owner-svn-src-stable-8@FreeBSD.ORG Sun May 23 11:29:35 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 11D391065670; Sun, 23 May 2010 11:29:35 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (unknown [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id F3B928FC18; Sun, 23 May 2010 11:29:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o4NBTYGK062835; Sun, 23 May 2010 11:29:34 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o4NBTY5V062830; Sun, 23 May 2010 11:29:34 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201005231129.o4NBTY5V062830@svn.freebsd.org> From: Alexander Motin Date: Sun, 23 May 2010 11:29:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r208448 - in stable/8/sys/dev: ahci ata mvs siis X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 May 2010 11:29:35 -0000 Author: mav Date: Sun May 23 11:29:34 2010 New Revision: 208448 URL: http://svn.freebsd.org/changeset/base/208448 Log: MFC r208375, r208393: Improve suspend/resume support. Make sure controller is idle on suspend and reset it on resume. Modified: stable/8/sys/dev/ahci/ahci.c stable/8/sys/dev/ata/ata-all.c stable/8/sys/dev/mvs/mvs.c stable/8/sys/dev/siis/siis.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) stable/8/sys/geom/sched/ (props changed) Modified: stable/8/sys/dev/ahci/ahci.c ============================================================================== --- stable/8/sys/dev/ahci/ahci.c Sun May 23 11:28:04 2010 (r208447) +++ stable/8/sys/dev/ahci/ahci.c Sun May 23 11:29:34 2010 (r208448) @@ -60,6 +60,8 @@ static void ahci_intr(void *data); static void ahci_intr_one(void *data); static int ahci_suspend(device_t dev); static int ahci_resume(device_t dev); +static int ahci_ch_init(device_t dev); +static int ahci_ch_deinit(device_t dev); static int ahci_ch_suspend(device_t dev); static int ahci_ch_resume(device_t dev); static void ahci_ch_pm(void *arg); @@ -871,7 +873,7 @@ ahci_ch_attach(device_t dev) return (ENXIO); ahci_dmainit(dev); ahci_slotsalloc(dev); - ahci_ch_resume(dev); + ahci_ch_init(dev); mtx_lock(&ch->mtx); rid = ATA_IRQ_RID; if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, @@ -963,7 +965,7 @@ ahci_ch_detach(device_t dev) bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); - ahci_ch_suspend(dev); + ahci_ch_deinit(dev); ahci_slotsfree(dev); ahci_dmafini(dev); @@ -973,7 +975,32 @@ ahci_ch_detach(device_t dev) } static int -ahci_ch_suspend(device_t dev) +ahci_ch_init(device_t dev) +{ + struct ahci_channel *ch = device_get_softc(dev); + uint64_t work; + + /* Disable port interrupts */ + ATA_OUTL(ch->r_mem, AHCI_P_IE, 0); + /* Setup work areas */ + work = ch->dma.work_bus + AHCI_CL_OFFSET; + ATA_OUTL(ch->r_mem, AHCI_P_CLB, work & 0xffffffff); + ATA_OUTL(ch->r_mem, AHCI_P_CLBU, work >> 32); + work = ch->dma.rfis_bus; + ATA_OUTL(ch->r_mem, AHCI_P_FB, work & 0xffffffff); + ATA_OUTL(ch->r_mem, AHCI_P_FBU, work >> 32); + /* Activate the channel and power/spin up device */ + ATA_OUTL(ch->r_mem, AHCI_P_CMD, + (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD | + ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) | + ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 ))); + ahci_start_fr(dev); + ahci_start(dev, 1); + return (0); +} + +static int +ahci_ch_deinit(device_t dev) { struct ahci_channel *ch = device_get_softc(dev); @@ -994,27 +1021,29 @@ ahci_ch_suspend(device_t dev) } static int +ahci_ch_suspend(device_t dev) +{ + struct ahci_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + xpt_freeze_simq(ch->sim, 1); + while (ch->oslots) + msleep(ch, &ch->mtx, PRIBIO, "ahcisusp", hz/100); + ahci_ch_deinit(dev); + mtx_unlock(&ch->mtx); + return (0); +} + +static int ahci_ch_resume(device_t dev) { struct ahci_channel *ch = device_get_softc(dev); - uint64_t work; - /* Disable port interrupts */ - ATA_OUTL(ch->r_mem, AHCI_P_IE, 0); - /* Setup work areas */ - work = ch->dma.work_bus + AHCI_CL_OFFSET; - ATA_OUTL(ch->r_mem, AHCI_P_CLB, work & 0xffffffff); - ATA_OUTL(ch->r_mem, AHCI_P_CLBU, work >> 32); - work = ch->dma.rfis_bus; - ATA_OUTL(ch->r_mem, AHCI_P_FB, work & 0xffffffff); - ATA_OUTL(ch->r_mem, AHCI_P_FBU, work >> 32); - /* Activate the channel and power/spin up device */ - ATA_OUTL(ch->r_mem, AHCI_P_CMD, - (AHCI_P_CMD_ACTIVE | AHCI_P_CMD_POD | AHCI_P_CMD_SUD | - ((ch->pm_level == 2 || ch->pm_level == 3) ? AHCI_P_CMD_ALPE : 0) | - ((ch->pm_level > 2) ? AHCI_P_CMD_ASP : 0 ))); - ahci_start_fr(dev); - ahci_start(dev, 1); + mtx_lock(&ch->mtx); + ahci_ch_init(dev); + ahci_reset(dev); + xpt_release_simq(ch->sim, TRUE); + mtx_unlock(&ch->mtx); return (0); } Modified: stable/8/sys/dev/ata/ata-all.c ============================================================================== --- stable/8/sys/dev/ata/ata-all.c Sun May 23 11:28:04 2010 (r208447) +++ stable/8/sys/dev/ata/ata-all.c Sun May 23 11:29:34 2010 (r208448) @@ -432,7 +432,13 @@ ata_suspend(device_t dev) if (!dev || !(ch = device_get_softc(dev))) return ENXIO; -#ifndef ATA_CAM +#ifdef ATA_CAM + mtx_lock(&ch->state_mtx); + xpt_freeze_simq(ch->sim, 1); + while (ch->state != ATA_IDLE) + msleep(ch, &ch->state_mtx, PRIBIO, "atasusp", hz/100); + mtx_unlock(&ch->state_mtx); +#else /* wait for the channel to be IDLE or detached before suspending */ while (ch->r_irq) { mtx_lock(&ch->state_mtx); @@ -452,16 +458,21 @@ ata_suspend(device_t dev) int ata_resume(device_t dev) { + struct ata_channel *ch; int error; /* check for valid device */ - if (!dev || !device_get_softc(dev)) + if (!dev || !(ch = device_get_softc(dev))) return ENXIO; +#ifdef ATA_CAM + mtx_lock(&ch->state_mtx); + error = ata_reinit(dev); + xpt_release_simq(ch->sim, TRUE); + mtx_unlock(&ch->state_mtx); +#else /* reinit the devices, we dont know what mode/state they are in */ error = ata_reinit(dev); - -#ifndef ATA_CAM /* kick off requests on the queue */ ata_start(dev); #endif Modified: stable/8/sys/dev/mvs/mvs.c ============================================================================== --- stable/8/sys/dev/mvs/mvs.c Sun May 23 11:28:04 2010 (r208447) +++ stable/8/sys/dev/mvs/mvs.c Sun May 23 11:29:34 2010 (r208448) @@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include /* local prototypes */ +static int mvs_ch_init(device_t dev); +static int mvs_ch_deinit(device_t dev); static int mvs_ch_suspend(device_t dev); static int mvs_ch_resume(device_t dev); static void mvs_dmainit(device_t dev); @@ -133,7 +135,7 @@ mvs_ch_attach(device_t dev) return (ENXIO); mvs_dmainit(dev); mvs_slotsalloc(dev); - mvs_ch_resume(dev); + mvs_ch_init(dev); mtx_lock(&ch->mtx); rid = ATA_IRQ_RID; if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, @@ -215,7 +217,7 @@ mvs_ch_detach(device_t dev) bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); - mvs_ch_suspend(dev); + mvs_ch_deinit(dev); mvs_slotsfree(dev); mvs_dmafini(dev); @@ -225,19 +227,7 @@ mvs_ch_detach(device_t dev) } static int -mvs_ch_suspend(device_t dev) -{ - struct mvs_channel *ch = device_get_softc(dev); - - /* Stop EDMA */ - mvs_set_edma_mode(dev, MVS_EDMA_OFF); - /* Disable port interrupts. */ - ATA_OUTL(ch->r_mem, EDMA_IEM, 0); - return (0); -} - -static int -mvs_ch_resume(device_t dev) +mvs_ch_init(device_t dev) { struct mvs_channel *ch = device_get_softc(dev); uint32_t reg; @@ -264,6 +254,45 @@ mvs_ch_resume(device_t dev) return (0); } +static int +mvs_ch_deinit(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + /* Stop EDMA */ + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + /* Disable port interrupts. */ + ATA_OUTL(ch->r_mem, EDMA_IEM, 0); + return (0); +} + +static int +mvs_ch_suspend(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + xpt_freeze_simq(ch->sim, 1); + while (ch->oslots) + msleep(ch, &ch->mtx, PRIBIO, "mvssusp", hz/100); + mvs_ch_deinit(dev); + mtx_unlock(&ch->mtx); + return (0); +} + +static int +mvs_ch_resume(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + mvs_ch_init(dev); + mvs_reset(dev); + xpt_release_simq(ch->sim, TRUE); + mtx_unlock(&ch->mtx); + return (0); +} + struct mvs_dc_cb_args { bus_addr_t maddr; int error; Modified: stable/8/sys/dev/siis/siis.c ============================================================================== --- stable/8/sys/dev/siis/siis.c Sun May 23 11:28:04 2010 (r208447) +++ stable/8/sys/dev/siis/siis.c Sun May 23 11:29:34 2010 (r208448) @@ -59,6 +59,8 @@ static int siis_setup_interrupt(device_t static void siis_intr(void *data); static int siis_suspend(device_t dev); static int siis_resume(device_t dev); +static int siis_ch_init(device_t dev); +static int siis_ch_deinit(device_t dev); static int siis_ch_suspend(device_t dev); static int siis_ch_resume(device_t dev); static void siis_ch_intr_locked(void *data); @@ -458,7 +460,7 @@ siis_ch_attach(device_t dev) return (ENXIO); siis_dmainit(dev); siis_slotsalloc(dev); - siis_ch_resume(dev); + siis_ch_init(dev); mtx_lock(&ch->mtx); rid = ATA_IRQ_RID; if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, @@ -528,7 +530,7 @@ siis_ch_detach(device_t dev) bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); - siis_ch_suspend(dev); + siis_ch_deinit(dev); siis_slotsfree(dev); siis_dmafini(dev); @@ -538,7 +540,24 @@ siis_ch_detach(device_t dev) } static int -siis_ch_suspend(device_t dev) +siis_ch_init(device_t dev) +{ + struct siis_channel *ch = device_get_softc(dev); + + /* Get port out of reset state. */ + ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PORT_RESET); + ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_32BIT); + if (ch->pm_present) + ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PME); + else + ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME); + /* Enable port interrupts */ + ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED); + return (0); +} + +static int +siis_ch_deinit(device_t dev) { struct siis_channel *ch = device_get_softc(dev); @@ -548,19 +567,29 @@ siis_ch_suspend(device_t dev) } static int +siis_ch_suspend(device_t dev) +{ + struct siis_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + xpt_freeze_simq(ch->sim, 1); + while (ch->oslots) + msleep(ch, &ch->mtx, PRIBIO, "siissusp", hz/100); + siis_ch_deinit(dev); + mtx_unlock(&ch->mtx); + return (0); +} + +static int siis_ch_resume(device_t dev) { struct siis_channel *ch = device_get_softc(dev); - /* Get port out of reset state. */ - ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PORT_RESET); - ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_32BIT); - if (ch->pm_present) - ATA_OUTL(ch->r_mem, SIIS_P_CTLSET, SIIS_P_CTL_PME); - else - ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME); - /* Enable port interrupts */ - ATA_OUTL(ch->r_mem, SIIS_P_IESET, SIIS_P_IX_ENABLED); + mtx_lock(&ch->mtx); + siis_ch_init(dev); + siis_reset(dev); + xpt_release_simq(ch->sim, TRUE); + mtx_unlock(&ch->mtx); return (0); }