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