Author: mav Date: Fri May 21 17:26:16 2010 New Revision: 208393 URL: http://svn.freebsd.org/changeset/base/208393
Log: Improve suspend/resume support. Make sure controller is idle on suspend and reset it on resume. Modified: head/sys/dev/mvs/mvs.c head/sys/dev/siis/siis.c Modified: head/sys/dev/mvs/mvs.c ============================================================================== --- head/sys/dev/mvs/mvs.c Fri May 21 17:17:56 2010 (r208392) +++ head/sys/dev/mvs/mvs.c Fri May 21 17:26:16 2010 (r208393) @@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include <cam/cam_debug.h> /* 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: head/sys/dev/siis/siis.c ============================================================================== --- head/sys/dev/siis/siis.c Fri May 21 17:17:56 2010 (r208392) +++ head/sys/dev/siis/siis.c Fri May 21 17:26:16 2010 (r208393) @@ -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); } _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"