Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162221575
D58033.id181276.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D58033.id181276.diff
View Options
diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c
--- a/sys/dev/firewire/fwohci.c
+++ b/sys/dev/firewire/fwohci.c
@@ -155,6 +155,7 @@
static void fwohci_task_busreset(void *, int);
static void fwohci_task_sid(void *, int);
static void fwohci_task_dma(void *, int);
+static void fwohci_sid_timeout(void *);
/*
* memory allocated for DMA programs
@@ -427,17 +428,20 @@
* It is not actually available port on your PC .
*/
OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
- DELAY(500);
+ /* IEEE 1394a-2000 s6.1: PHY reset completes within 10 ms of LPS. */
+ DELAY(10000);
reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
if ((reg >> 5) != 7) {
sc->fc.mode &= ~FWPHYASYST;
sc->fc.nport = reg & FW_PHY_NP;
- sc->fc.speed = reg & FW_PHY_SPD >> 6;
+ sc->fc.speed = (reg & FW_PHY_SPD) >> 6;
if (sc->fc.speed > MAX_SPEED) {
- device_printf(dev, "invalid speed %d (fixed to %d).\n",
- sc->fc.speed, MAX_SPEED);
+ if (bootverbose)
+ device_printf(dev,
+ "invalid speed %d (fixed to %d).\n",
+ sc->fc.speed, MAX_SPEED);
sc->fc.speed = MAX_SPEED;
}
device_printf(dev,
@@ -449,8 +453,10 @@
sc->fc.nport = reg & FW_PHY_NP;
sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
if (sc->fc.speed > MAX_SPEED) {
- device_printf(dev, "invalid speed %d (fixed to %d).\n",
- sc->fc.speed, MAX_SPEED);
+ if (bootverbose)
+ device_printf(dev,
+ "invalid speed %d (fixed to %d).\n",
+ sc->fc.speed, MAX_SPEED);
sc->fc.speed = MAX_SPEED;
}
device_printf(dev,
@@ -762,6 +768,7 @@
TASK_INIT(&sc->fwohci_task_busreset, 2, fwohci_task_busreset, sc);
TASK_INIT(&sc->fwohci_task_sid, 1, fwohci_task_sid, sc);
TASK_INIT(&sc->fwohci_task_dma, 0, fwohci_task_dma, sc);
+ callout_init_mtx(&sc->sid_timeout_callout, FW_GMTX(&sc->fc), 0);
fw_init(&sc->fc);
fwohci_reset(sc, dev);
@@ -804,6 +811,7 @@
fwohci_db_free(&sc->it[i]);
fwohci_db_free(&sc->ir[i]);
}
+ callout_drain(&sc->sid_timeout_callout);
if (sc->fc.taskqueue != NULL) {
taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_busreset);
taskqueue_drain(sc->fc.taskqueue, &sc->fwohci_task_sid);
@@ -1824,7 +1832,8 @@
/* Disable bus reset interrupt until sid recv. */
OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_PHY_BUS_R);
- device_printf(fc->dev, "%s: BUS reset\n", __func__);
+ if (sc->sid_timeout_count == 0 || firewire_debug)
+ device_printf(fc->dev, "%s: BUS reset\n", __func__);
OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_CYC_LOST);
OWRITE(sc, OHCI_LNKCTLCLR, OHCI_CNTL_CYCSRC);
@@ -1835,6 +1844,10 @@
if (!kdb_active)
taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_busreset);
+
+ /* SID watchdog: recover if self-ID never completes. */
+ callout_reset(&sc->sid_timeout_callout, hz / 2,
+ fwohci_sid_timeout, sc);
}
if (stat & OHCI_INT_PHY_SID) {
/* Enable bus reset interrupt */
@@ -1902,6 +1915,8 @@
}
fc->status = FWBUSINIT;
+ callout_stop(&sc->sid_timeout_callout);
+ sc->sid_timeout_count = 0;
if (!kdb_active)
taskqueue_enqueue(sc->fc.taskqueue, &sc->fwohci_task_sid);
@@ -1982,7 +1997,13 @@
device_printf(fc->dev, "unrecoverable error\n");
}
if (stat & OHCI_INT_PHY_INT) {
- device_printf(fc->dev, "phy int\n");
+ uint32_t r5;
+
+ /* Clear W1C interrupt bits; mask ISBR(6) to avoid bus reset. */
+ r5 = fwphy_rddata(sc, 5);
+ if (firewire_debug)
+ device_printf(fc->dev, "phy int: reg5=0x%02x\n", r5);
+ fwphy_wrdata(sc, 5, (r5 & ~(1 << 6)) | 0x3c);
}
}
@@ -2039,6 +2060,28 @@
fw_drain_txq(fc);
fw_sidrcv(fc, buf, plen);
free(buf, M_FW);
+
+}
+
+/* SelfID timeout: called with FW_GLOCK held (callout_init_mtx). */
+static void
+fwohci_sid_timeout(void *arg)
+{
+ struct fwohci_softc *sc = arg;
+ struct firewire_comm *fc = &sc->fc;
+
+ FW_GLOCK_ASSERT(fc);
+ if (fc->status != FWBUSRESET)
+ return;
+
+ sc->sid_timeout_count++;
+ if (sc->sid_timeout_count == 1)
+ device_printf(fc->dev, "SelfID timeout, retrying\n");
+
+ /* Reset state machine so next bus reset is recognized. */
+ fc->status = FWBUSINIT;
+ OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
+ OWRITE(sc, FWOHCI_INTMASK, OHCI_INT_PHY_BUS_R);
}
static void
diff --git a/sys/dev/firewire/fwohcivar.h b/sys/dev/firewire/fwohcivar.h
--- a/sys/dev/firewire/fwohcivar.h
+++ b/sys/dev/firewire/fwohcivar.h
@@ -36,6 +36,7 @@
*
*/
+#include <sys/callout.h>
#include <sys/taskqueue.h>
typedef struct fwohci_softc {
@@ -71,6 +72,8 @@
struct task fwohci_task_busreset;
struct task fwohci_task_sid;
struct task fwohci_task_dma;
+ struct callout sid_timeout_callout; /* fires if SID phase doesn't complete */
+ int sid_timeout_count; /* consecutive SID timeouts */
int cycle_lost;
} fwohci_softc_t;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jul 12, 12:51 AM (9 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34978330
Default Alt Text
D58033.id181276.diff (4 KB)
Attached To
Mode
D58033: fwohci: fix LPS delay, PHY_INT storm, and SID timeout recovery
Attached
Detach File
Event Timeline
Log In to Comment