svn commit: r208448 - in stable/8/sys/dev: ahci ata mvs siis
Alexander Motin
mav at FreeBSD.org
Sun May 23 11:29:35 UTC 2010
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 <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: 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);
}
More information about the svn-src-stable-8
mailing list