As I've pointed out before, on panic we can be running on any
CPU and our disk controller's interrupts can interrupt on the
other one.  Since we'll most likely be holding a kernel lock,
dealing with unlocking it might get hairy very fast.  Instead
what we could do to improve the chances of a clean shutdown on
panic is to instruct our disk subsystem to do polled I/O that
will be run on the same CPU with the panic.

Initially I wanted to move "cold = 1" earlier in boot(), but
after talking to Miod, it started to look like a bad idea.

Thoughts?

diff --git sys/dev/ata/ata_wdc.c sys/dev/ata/ata_wdc.c
index 1f52488..aea9ec1 100644
--- sys/dev/ata/ata_wdc.c
+++ sys/dev/ata/ata_wdc.c
@@ -199,20 +199,22 @@ wd_hibernate_io(dev_t dev, daddr_t blkno, vaddr_t addr, 
size_t size, int op, voi
  */
 int
 wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
 {
        struct wdc_xfer *xfer;
        struct channel_softc *chp = drvp->chnl_softc;
 
        xfer = wdc_get_xfer(WDC_NOSLEEP);
        if (xfer == NULL)
                return WDC_TRY_AGAIN;
+       if (panicstr)
+               ata_bio->flags |= ATA_POLL;
        if (ata_bio->flags & ATA_POLL)
                xfer->c_flags |= C_POLL;
        if (!(ata_bio->flags & ATA_POLL) &&
            (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
            (ata_bio->flags & ATA_SINGLE) == 0 &&
            (ata_bio->bcount > 512 ||
            (chp->wdc->quirks & WDC_QUIRK_NOSHORTDMA) == 0))
                xfer->c_flags |= C_DMA;
        xfer->drive = drvp->drive;
        xfer->cmd = ata_bio;
diff --git sys/scsi/scsi_base.c sys/scsi/scsi_base.c
index 9cf6b45..3afcc29 100644
--- sys/scsi/scsi_base.c
+++ sys/scsi/scsi_base.c
@@ -1267,20 +1267,22 @@ scsi_report_luns(struct scsi_link *sc_link, int 
selectreport,
        return (error);
 }
 
 void
 scsi_xs_exec(struct scsi_xfer *xs)
 {
        xs->error = XS_NOERROR;
        xs->resid = xs->datalen;
        xs->status = 0;
        CLR(xs->flags, ITSDONE);
+       if (panicstr)
+               SET(xs->flags, SCSI_AUTOCONF);
 
 #ifdef SCSIDEBUG
        if (xs->sc_link->flags & SDEV_DB1) {
                scsi_xs_show(xs);
                if (xs->datalen && (xs->flags & SCSI_DATA_OUT))
                        scsi_show_mem(xs->data, min(64, xs->datalen));
        }
 #endif
 
        /* The adapter's scsi_cmd() is responsible for calling scsi_done(). */

Reply via email to