summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2003-06-28 11:11:36 +0000
committersimokawa <simokawa@FreeBSD.org>2003-06-28 11:11:36 +0000
commit065a386bdcc4180b948790e8ec4df6b9dd574e4d (patch)
tree9313de668e3daee390c423887938103217d7b3f2
parent7b25bda5637f6013ca7067e4482a40b0a4c73bc6 (diff)
downloadFreeBSD-src-065a386bdcc4180b948790e8ec4df6b9dd574e4d.zip
FreeBSD-src-065a386bdcc4180b948790e8ec4df6b9dd574e4d.tar.gz
Fix several problems related to resume:
- Initialize fc->status to process bus reset correctly after resume. - Initialize AT ring buffer pointer. - Requeue stdma to stfree for active IR buffer. - Stop DMA before suspend for safe. - Set powerstate after resume.
-rw-r--r--sys/dev/firewire/firewire.c18
-rw-r--r--sys/dev/firewire/firewirereg.h1
-rw-r--r--sys/dev/firewire/fwohci.c22
-rw-r--r--sys/dev/firewire/fwohci_pci.c4
4 files changed, 40 insertions, 5 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c
index 3b100c2..25230ed 100644
--- a/sys/dev/firewire/firewire.c
+++ b/sys/dev/firewire/firewire.c
@@ -84,6 +84,7 @@ devclass_t firewire_devclass;
static int firewire_match __P((device_t));
static int firewire_attach __P((device_t));
static int firewire_detach __P((device_t));
+static int firewire_resume __P((device_t));
#if 0
static int firewire_shutdown __P((device_t));
#endif
@@ -109,7 +110,7 @@ static device_method_t firewire_methods[] = {
DEVMETHOD(device_attach, firewire_attach),
DEVMETHOD(device_detach, firewire_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_resume, firewire_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
/* Bus interface */
@@ -367,7 +368,7 @@ firewire_attach( device_t dev )
fc = (struct firewire_comm *)device_get_softc(pa);
sc->fc = fc;
- fc->status = -1;
+ fc->status = FWBUSNOTREADY;
unitmask = UNIT2MIN(device_get_unit(dev));
@@ -434,6 +435,19 @@ firewire_add_child(device_t dev, int order, const char *name, int unit)
return child;
}
+static int
+firewire_resume(device_t dev)
+{
+ struct firewire_softc *sc;
+
+ sc = (struct firewire_softc *)device_get_softc(dev);
+ sc->fc->status = FWBUSNOTREADY;
+
+ bus_generic_resume(dev);
+
+ return(0);
+}
+
/*
* Dettach it.
*/
diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h
index f16fd32..6a462c2 100644
--- a/sys/dev/firewire/firewirereg.h
+++ b/sys/dev/firewire/firewirereg.h
@@ -121,6 +121,7 @@ struct firewire_comm{
SLIST_HEAD(, csrdir) ongocsr;
SLIST_HEAD(, csrdir) csrfree;
u_int32_t status;
+#define FWBUSNOTREADY (-1)
#define FWBUSRESET 0
#define FWBUSINIT 1
#define FWBUSCYMELECT 2
diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c
index a597a34..4dfe5cf 100644
--- a/sys/dev/firewire/fwohci.c
+++ b/sys/dev/firewire/fwohci.c
@@ -549,10 +549,17 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev)
/* Initialize async TX */
OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD);
+
/* AT Retries */
OWRITE(sc, FWOHCI_RETRY,
/* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */
(0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ;
+
+ sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq);
+ sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq);
+ sc->atrq.bottom = sc->atrq.top;
+ sc->atrs.bottom = sc->atrs.top;
+
for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ;
i ++, db_tr = STAILQ_NEXT(db_tr, link)){
db_tr->xfer = NULL;
@@ -1681,6 +1688,9 @@ fwohci_stop(struct fwohci_softc *sc, device_t dev)
| OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS
| OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS
| OHCI_INT_PHY_BUS_R);
+
+ fw_drain_txq(&sc->fc);
+
/* XXX Link down? Bus reset? */
return 0;
}
@@ -1689,14 +1699,22 @@ int
fwohci_resume(struct fwohci_softc *sc, device_t dev)
{
int i;
+ struct fw_xferq *ir;
+ struct fw_bulkxfer *chunk;
fwohci_reset(sc, dev);
/* XXX resume isochronus receive automatically. (how about TX?) */
for(i = 0; i < sc->fc.nisodma; i ++) {
- if((sc->ir[i].xferq.flag & FWXFERQ_RUNNING) != 0) {
+ ir = &sc->ir[i].xferq;
+ if((ir->flag & FWXFERQ_RUNNING) != 0) {
device_printf(sc->fc.dev,
"resume iso receive ch: %d\n", i);
- sc->ir[i].xferq.flag &= ~FWXFERQ_RUNNING;
+ ir->flag &= ~FWXFERQ_RUNNING;
+ /* requeue stdma to stfree */
+ while((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) {
+ STAILQ_REMOVE_HEAD(&ir->stdma, link);
+ STAILQ_INSERT_TAIL(&ir->stfree, chunk, link);
+ }
sc->fc.irx_enable(&sc->fc, i);
}
}
diff --git a/sys/dev/firewire/fwohci_pci.c b/sys/dev/firewire/fwohci_pci.c
index 6f45152..dcc5caa 100644
--- a/sys/dev/firewire/fwohci_pci.c
+++ b/sys/dev/firewire/fwohci_pci.c
@@ -380,13 +380,14 @@ fwohci_pci_detach(device_t self)
static int
fwohci_pci_suspend(device_t dev)
{
+ fwohci_softc_t *sc = device_get_softc(dev);
int err;
device_printf(dev, "fwohci_pci_suspend\n");
err = bus_generic_suspend(dev);
if (err)
return err;
- /* fwohci_stop(dev); */
+ fwohci_stop(sc, dev);
return 0;
}
@@ -397,6 +398,7 @@ fwohci_pci_resume(device_t dev)
device_printf(dev, "fwohci_pci_resume: power_state = 0x%08x\n",
pci_get_powerstate(dev));
+ pci_set_powerstate(dev, PCI_POWERSTATE_D0);
fwohci_pci_init(dev);
fwohci_resume(sc, dev);
return 0;
OpenPOWER on IntegriCloud