Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Avoid busy-waiting when possible if we are not polli...
details: https://anonhg.NetBSD.org/src/rev/fce19fd0d5aa
branches: trunk
changeset: 467524:fce19fd0d5aa
user: bouyer <bouyer%NetBSD.org@localhost>
date: Thu Mar 25 16:17:36 1999 +0000
description:
Avoid busy-waiting when possible if we are not polling (real IRQ or timeout
callback). Shared PCI IRQ should now work (but still untested).
diffstat:
sys/dev/ata/ata_wdc.c | 24 ++++++++++++++--------
sys/dev/ic/wdc.c | 13 +++++------
sys/dev/scsipi/atapi_wdc.c | 49 ++++++++++++++++++++++++---------------------
3 files changed, 47 insertions(+), 39 deletions(-)
diffs (264 lines):
diff -r 48cdd11875ee -r fce19fd0d5aa sys/dev/ata/ata_wdc.c
--- a/sys/dev/ata/ata_wdc.c Thu Mar 25 16:15:00 1999 +0000
+++ b/sys/dev/ata/ata_wdc.c Thu Mar 25 16:17:36 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.17 1999/03/17 10:13:56 bouyer Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.18 1999/03/25 16:17:36 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -416,7 +416,11 @@
}
/* Ack interrupt done by wait_for_unbusy */
- if (wait_for_unbusy(chp, ATA_DELAY) < 0) {
+ if (wait_for_unbusy(chp,
+ (ata_bio->flags & ATA_POLL) ? ATA_DELAY : 0) < 0) {
+ if ((ata_bio->flags & ATA_POLL) == 0 &&
+ (xfer->c_flags & C_TIMEOU) == 0)
+ return 0; /* IRQ was not for us */
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
xfer->c_bcount, xfer->c_skip);
@@ -588,8 +592,10 @@
struct ata_bio *ata_bio = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
char *errstring = NULL;
+ int delay = (ata_bio->flags & ATA_POLL) ? ATA_DELAY : 0;
+
WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
- DEBUG_FUNCS);
+ DEBUG_FUNCS);
again:
switch (drvp->state) {
@@ -599,7 +605,7 @@
case RECAL_WAIT:
errstring = "recal";
- if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
+ if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
goto timeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto error;
@@ -619,7 +625,7 @@
case PIOMODE_WAIT:
errstring = "piomode";
- if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
+ if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
goto timeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto error;
@@ -639,7 +645,7 @@
break;
case DMAMODE_WAIT:
errstring = "dmamode";
- if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
+ if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
goto timeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto error;
@@ -659,7 +665,7 @@
case GEOMETRY_WAIT:
errstring = "geometry";
- if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
+ if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
goto timeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto error;
@@ -676,7 +682,7 @@
case MULTIMODE_WAIT:
errstring = "setmulti";
- if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY))
+ if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, delay))
goto timeout;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto error;
@@ -702,7 +708,7 @@
return 1;
timeout:
- if ((xfer->c_flags & C_TIMEOU) == 0 ) {
+ if ((xfer->c_flags & C_TIMEOU) == 0 && delay == 0) {
return 0; /* IRQ was not for us */
}
printf("%s:%d:%d: %s timed out\n",
diff -r 48cdd11875ee -r fce19fd0d5aa sys/dev/ic/wdc.c
--- a/sys/dev/ic/wdc.c Thu Mar 25 16:15:00 1999 +0000
+++ b/sys/dev/ic/wdc.c Thu Mar 25 16:17:36 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.62 1999/03/10 13:11:43 bouyer Exp $ */
+/* $NetBSD: wdc.c,v 1.63 1999/03/25 16:17:36 bouyer Exp $ */
/*
@@ -1085,10 +1085,7 @@
* Wait for at last 400ns for status bit to be valid.
*/
delay(10);
- if (__wdccommand_intr(chp, xfer) == 0) {
- wdc_c->flags |= AT_TIMEOU;
- __wdccommand_done(chp, xfer);
- }
+ __wdccommand_intr(chp, xfer);
}
int
@@ -1103,8 +1100,10 @@
WDCDEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive), DEBUG_INTR);
if (wdcwait(chp, wdc_c->r_st_pmask, wdc_c->r_st_pmask,
- wdc_c->timeout)) {
- wdc_c->flags |= AT_ERROR;
+ (wdc_c->flags & AT_POLL) ? wdc_c->timeout : 0)) {
+ if ((xfer->c_flags & C_TIMEOU) == 0)
+ return 0; /* IRQ was not for us */
+ wdc_c->flags |= AT_TIMEOU;
__wdccommand_done(chp, xfer);
return 1;
}
diff -r 48cdd11875ee -r fce19fd0d5aa sys/dev/scsipi/atapi_wdc.c
--- a/sys/dev/scsipi/atapi_wdc.c Thu Mar 25 16:15:00 1999 +0000
+++ b/sys/dev/scsipi/atapi_wdc.c Thu Mar 25 16:17:36 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: atapi_wdc.c,v 1.18 1999/02/21 00:52:05 hubertf Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.19 1999/03/25 16:17:37 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -188,7 +188,6 @@
{
struct wdc_softc *wdc = (void*)sc_xfer->sc_link->adapter_softc;
struct wdc_xfer *xfer;
- struct ata_drive_datas *drvp;
int flags = sc_xfer->flags;
int channel = sc_xfer->sc_link->scsipi_atapi.channel;
int drive = sc_xfer->sc_link->scsipi_atapi.drive;
@@ -203,10 +202,6 @@
}
if (sc_xfer->flags & SCSI_POLL)
xfer->c_flags |= C_POLL;
- drvp = &wdc->channels[channel]->ch_drive[drive];
- if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
- sc_xfer->datalen > 0)
- xfer->c_flags |= C_DMA;
xfer->drive = drive;
xfer->c_flags |= C_ATAPI;
xfer->cmd = sc_xfer;
@@ -237,6 +232,12 @@
WDCDEBUG_PRINT(("wdc_atapi_start %s:%d:%d, scsi flags 0x%x \n",
chp->wdc->sc_dev.dv_xname, chp->channel, drvp->drive,
sc_xfer->flags), DEBUG_XFERS);
+ /* Adjust C_DMA, it may have changed if we are requesting sense */
+ if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
+ (sc_xfer->datalen > 0 || (xfer->c_flags & C_SENSE)))
+ xfer->c_flags |= C_DMA;
+ else
+ xfer->c_flags &= ~C_DMA;
/* Do control operations specially. */
if (drvp->state < READY) {
if (drvp->state != PIOMODE) {
@@ -291,12 +292,7 @@
while ((sc_xfer->flags & ITSDONE) == 0) {
/* Wait for at last 400ns for status bit to be valid */
delay(1);
- if (wdc_atapi_intr(chp, xfer) == 0) {
- sc_xfer->error = XS_SELTIMEOUT;
- /* do we know more ? */
- wdc_atapi_done(chp, xfer);
- return;
- }
+ wdc_atapi_intr(chp, xfer);
}
}
}
@@ -329,16 +325,23 @@
/* Ack interrupt done in wait_for_unbusy */
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | (xfer->drive << 4));
- if (wait_for_unbusy(chp, sc_xfer->timeout) != 0) {
+ if (wait_for_unbusy(chp,
+ (sc_xfer->flags & SCSI_POLL) ? sc_xfer->timeout : 0) != 0) {
+ if ((sc_xfer->flags & SCSI_POLL) == 0 &&
+ (xfer->c_flags & C_TIMEOU) == 0)
+ return 0; /* IRQ was not for us */
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
xfer->c_bcount, xfer->c_skip);
if (xfer->c_flags & C_DMA)
- drvp->n_dmaerrs++;
+ drvp->n_dmaerrs++;
sc_xfer->error = XS_TIMEOUT;
wdc_atapi_reset(chp, xfer);
return 1;
}
+ /* If we missed an IRQ and were using DMA, flag it as a DMA error */
+ if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))
+ drvp->n_dmaerrs++;
/*
* if the request sense command was aborted, report the short sense
* previously recorded, else continue normal processing
@@ -355,8 +358,8 @@
}
if (xfer->c_flags & C_DMA) {
- dma_flags = (sc_xfer->flags & SCSI_DATA_IN) ?
- WDC_DMA_READ : 0;
+ dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
+ (xfer->c_flags & C_SENSE)) ? WDC_DMA_READ : 0;
dma_flags |= sc_xfer->flags & SCSI_POLL ? WDC_DMA_POLL : 0;
}
again:
@@ -684,6 +687,7 @@
struct scsipi_xfer *sc_xfer = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
char *errstring = NULL;
+ int delay = (sc_xfer->flags & SCSI_POLL) ? ATAPI_DELAY : 0;
/* Ack interrupt done in wait_for_unbusy */
again:
@@ -706,7 +710,7 @@
break;
case PIOMODE_WAIT:
errstring = "piomode";
- if (wait_for_unbusy(chp, ATAPI_DELAY))
+ if (wait_for_unbusy(chp, delay))
goto timeout;
if (chp->ch_status & WDCS_ERR)
goto error;
@@ -726,7 +730,7 @@
break;
case DMAMODE_WAIT:
errstring = "dmamode";
- if (wait_for_unbusy(chp, ATAPI_DELAY))
+ if (wait_for_unbusy(chp, delay))
goto timeout;
if (chp->ch_status & WDCS_ERR)
goto error;
@@ -749,7 +753,7 @@
return 1;
timeout:
- if ((xfer->c_flags & C_TIMEOU) == 0 ) {
+ if ((xfer->c_flags & C_TIMEOU) == 0 && delay == 0) {
return 0; /* IRQ was not for us */
}
printf("%s:%d:%d: %s timed out\n",
@@ -785,11 +789,10 @@
xfer->c_skip = 0;
wdc_free_xfer(chp, xfer);
sc_xfer->flags |= ITSDONE;
- if (sc_xfer->error == XS_NOERROR ||
- sc_xfer->error == XS_SENSE ||
- sc_xfer->error == XS_SHORTSENSE) {
+ if (drvp->n_dmaerrs ||
+ (sc_xfer->error != XS_NOERROR && sc_xfer->error != XS_SENSE &&
+ sc_xfer->error != XS_SHORTSENSE)) {
drvp->n_dmaerrs = 0;
- } else {
wdc_downgrade_mode(drvp);
}
Home |
Main Index |
Thread Index |
Old Index