Module Name: src
Committed By: jakllsch
Date: Sat Jun 27 21:04:47 UTC 2009
Modified Files:
src/sys/dev/ic: siisata.c
Log Message:
Correct various siisata bugs, some old, some new.
- Move clearing of interrupts to before atastart() is called in the
xfer interrupt handler. Should fix kern/41579.
- Using cv_timedwait(9) is not possible in code that can be called from
interrupt context, fall back to DELAY(9).
- Correctly poll Port Slot Status register for soft reset PRBs.
- Only use the Recive Transfer Count register on reads, when it is valid.
- Activate PRBs in a way that takes the whole physical address into account,
even when the PRB is beyond 4GiB.
- consistently use DELAY(9)
- Use DELAY() constants in completion polling loops that are consistent with
the loop count limit. (i.e. timeout in 10 rather than 100 seconds)
To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/siisata.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/siisata.c
diff -u src/sys/dev/ic/siisata.c:1.5 src/sys/dev/ic/siisata.c:1.6
--- src/sys/dev/ic/siisata.c:1.5 Sun Jun 21 14:15:38 2009
+++ src/sys/dev/ic/siisata.c Sat Jun 27 21:04:47 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: siisata.c,v 1.5 2009/06/21 14:15:38 jakllsch Exp $ */
+/* $NetBSD: siisata.c,v 1.6 2009/06/27 21:04:47 jakllsch Exp $ */
/* from ahcisata_core.c */
@@ -494,13 +494,13 @@
}
}
+ /* clear some (ok, all) ints */
+ PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
+
KASSERT(xfer != NULL);
KASSERT(xfer->c_intr != NULL);
xfer->c_intr(chp, xfer, slot);
- /* clear some (ok, all) ints */
- PRWRITE(sc, PRX(chp->ch_channel, PRO_PIS), 0xffffffff);
-
return;
}
@@ -511,17 +511,8 @@
struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac;
struct siisata_channel *schp = (struct siisata_channel *)chp;
struct siisata_prb *prb;
- kmutex_t mtx;
- kcondvar_t cv;
int slot = SIISATA_NON_NCQ_SLOT;
int i;
- int wait;
-
- mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE);
- cv_init(&cv, "siipd");
-
- wait = mstohz(10);
- wait = wait ? wait : 1;
/* wait for ready */
while (!(PRREAD(sc, PRX(chp->ch_channel, PRO_PS)) & PR_PS_PORT_READY))
@@ -534,18 +525,18 @@
siisata_activate_prb(schp, slot);
- for(i = 0; i < (31000/(1000/(wait*hz))); i++) {
+ for(i = 0; i < 31000; i++) {
if (PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)) &
PR_PXSS(slot))
- break;
+ DELAY(1000);
else
- cv_timedwait(&cv, &mtx, wait);
+ break;
}
siisata_deactivate_prb(schp, slot);
- log(LOG_DEBUG, "%s: ch_status %x ch_error %x\n",
- __func__, chp->ch_status, chp->ch_error);
+ log(LOG_DEBUG, "%s: port %d: ch_status %x ch_error %x\n",
+ __func__, chp->ch_channel, chp->ch_status, chp->ch_error);
#if 1
/* attempt to downgrade signaling in event of CRC error */
@@ -571,9 +562,6 @@
chp->ch_error = 0;
#endif
- cv_destroy(&cv);
- mutex_destroy(&mtx);
-
return;
}
@@ -633,9 +621,6 @@
uint32_t sig;
int slot = SIISATA_NON_NCQ_SLOT;
struct siisata_prb *prb;
- kmutex_t mtx;
- kcondvar_t cv;
- int wait;
SIISATA_DEBUG_PRINT(("%s: %s: port %d start\n", SIISATANAME(sc),
__func__, chp->ch_channel), DEBUG_FUNCS);
@@ -646,12 +631,6 @@
chp->ch_drive[i].drive = i;
}
- mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE);
- cv_init(&cv, "siipd");
-
- wait = mstohz(10);
- wait = wait ? wait : 1;
-
switch (sata_reset_interface(chp, sc->sc_prt, schp->sch_scontrol,
schp->sch_sstatus)) {
case SStatus_DET_DEV:
@@ -667,12 +646,12 @@
siisata_activate_prb(schp, slot);
- for(i = 0; i < (31000/(1000/(wait*hz))); i++) {
+ for(i = 0; i < 31000; i++) {
if (PRREAD(sc, PRX(chp->ch_channel, PRO_PSS)) &
PR_PXSS(slot))
- break;
+ DELAY(1000);
else
- cv_timedwait(&cv, &mtx, wait);
+ break;
}
siisata_deactivate_prb(schp, slot);
@@ -714,9 +693,6 @@
break;
}
- cv_destroy(&cv);
- mutex_destroy(&mtx);
-
SIISATA_DEBUG_PRINT(("%s: %s: port %d done\n", SIISATANAME(sc),
__func__, chp->ch_channel), DEBUG_PROBE);
return;
@@ -836,7 +812,7 @@
if (ata_c->flags & AT_DONE)
break;
siisata_intr_port(schp);
- DELAY(10000);
+ DELAY(1000);
}
if ((ata_c->flags & AT_DONE) == 0) {
@@ -1038,7 +1014,7 @@
if (ata_bio->flags & ATA_ITSDONE)
break;
siisata_intr_port(schp);
- DELAY(10000);
+ DELAY(1000);
}
GRWRITE(sc, GR_GC, GRREAD(sc, GR_GC) | GR_GC_PXIE(chp->ch_channel));
@@ -1123,9 +1099,13 @@
SIISATA_DEBUG_PRINT(("%s: %s bcount: %ld", SIISATANAME(sc),
__func__, ata_bio->bcount), DEBUG_XFERS);
- if ((ata_bio->flags & ATA_READ) || (ata_bio->error == NOERROR))
- ata_bio->bcount -= PRREAD(sc,
- PRSX(chp->ch_channel, slot, PRSO_RTC));
+ if (ata_bio->error == NOERROR) {
+ if (ata_bio->flags & ATA_READ)
+ ata_bio->bcount -=
+ PRREAD(sc, PRSX(chp->ch_channel, slot, PRSO_RTC));
+ else
+ ata_bio->bcount = 0;
+ }
SIISATA_DEBUG_PRINT((" now %ld\n", ata_bio->bcount), DEBUG_XFERS);
if (ata_bio->flags & ATA_POLL)
return 1;
@@ -1203,34 +1183,23 @@
{
struct siisata_softc *sc;
bus_size_t offset;
- bus_addr_t pprb;
- int port;
+ uint64_t pprb;
sc = (struct siisata_softc *)schp->ata_channel.ch_atac;
KASSERTMSG(((schp->sch_active_slots & __BIT(slot)) == __BIT(slot)),
("%s: trying to activate active slot %d", SIISATANAME(sc), slot));
- port = schp->ata_channel.ch_channel;
-
- offset = PRO_CARX(port, slot);
-
- pprb = schp->sch_bus_prb[slot];
-
-
SIISATA_PRB_SYNC(sc, schp, slot, BUS_DMASYNC_PREWRITE);
/* keep track of what's going on */
schp->sch_active_slots |= __BIT(slot);
+ offset = PRO_CARX(schp->ata_channel.ch_channel, slot);
- PRWRITE(sc, offset, pprb);
- offset += 4;
-#if 0
- if (sizeof(bus_addr_t) == 8)
- PRWRITE(sc, offset, (pprb >> 32));
- else
-#endif
- PRWRITE(sc, offset, 0);
+ pprb = schp->sch_bus_prb[slot];
+
+ PRWRITE(sc, offset + 0, pprb >> 0);
+ PRWRITE(sc, offset + 4, pprb >> 32);
}
static void
@@ -1379,7 +1348,7 @@
}
/* Some ATAPI devices need a bit more time after software reset. */
- delay(5000);
+ DELAY(5000);
if (ata_get_params(drvp, AT_WAIT, id) == 0) {
#ifdef ATAPI_DEBUG_PROBE
log(LOG_DEBUG, "%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
@@ -1591,7 +1560,7 @@
if (sc_xfer->xs_status & XS_STS_DONE)
break;
siisata_intr_port(schp);
- DELAY(10000);
+ DELAY(1000);
}
if ((sc_xfer->xs_status & XS_STS_DONE) == 0) {
sc_xfer->error = XS_TIMEOUT;