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"

Reply via email to