Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/thorpej_scsipi]: src/sys/dev/ic Put URGENT requests in the urgent queue



details:   https://anonhg.NetBSD.org/src/rev/76174631dddb
branches:  thorpej_scsipi
changeset: 477373:76174631dddb
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Mon Jan 22 17:46:31 2001 +0000

description:
Put URGENT requests in the urgent queue
When we get CHECK CONDITION, remove and requeue all xfer for this T/L that have
not yet been queued in the device (still in a scheduler slot or in the queues),
otherwise if one of them is accepted before the request sense, sense will be
lost.
Don't allow disconnect for REQUEST SENSE commands, as others drivers do.

diffstat:

 sys/dev/ic/siop.c        |  117 +++++++++++++++++++++++++++++++++++++++++-----
 sys/dev/ic/siop_common.c |    8 ++-
 2 files changed, 110 insertions(+), 15 deletions(-)

diffs (258 lines):

diff -r 29b4786df579 -r 76174631dddb sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Mon Jan 22 17:43:02 2001 +0000
+++ b/sys/dev/ic/siop.c Mon Jan 22 17:46:31 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop.c,v 1.37.2.6 2001/01/15 09:26:26 bouyer Exp $     */
+/*     $NetBSD: siop.c,v 1.37.2.7 2001/01/22 17:46:31 bouyer Exp $     */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -81,10 +81,11 @@
 void   siop_handle_reset __P((struct siop_softc *));
 int    siop_handle_qtag_reject __P((struct siop_cmd *));
 void   siop_scsicmd_end __P((struct siop_cmd *));
+void   siop_unqueue __P((struct siop_softc *, int, int));
 void   siop_start __P((struct siop_softc *));
 void   siop_timeout __P((void *));
 int    siop_scsicmd __P((struct scsipi_xfer *));
-void   siop_scsipi_request __P(( struct scsipi_channel *,
+void   siop_scsipi_request __P((struct scsipi_channel *,
                        scsipi_adapter_req_t, void *));
 void   siop_dump_script __P((struct siop_softc *));
 int    siop_morecbd __P((struct siop_softc *));
@@ -349,6 +350,7 @@
        bus_addr_t dsa;
        struct siop_cbd *cbdp;
        int freetarget = 0;
+       int restart = 0;
 
        istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);
        if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
@@ -929,14 +931,22 @@
        panic("siop_intr: I shouldn't be there !");
        return 1;
 end:
-       CALL_SCRIPT(Ent_script_sched);
+       /*
+        * restart the script now if command completed properly
+        * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
+        * queue
+        */
+       xs->status = le32toh(siop_cmd->siop_tables.status);
+       if (xs->status == SCSI_OK)
+               CALL_SCRIPT(Ent_script_sched);
+       else
+               restart = 1;
        siop_lun->siop_tag[tag].active = NULL;
        siop_scsicmd_end(siop_cmd);
-       if (siop_cmd->status == CMDST_FREE) {
-               TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
-               if (freetarget && siop_target->status == TARST_PROBING)
-                       siop_del_dev(sc, target, lun);
-       }
+       if (freetarget && siop_target->status == TARST_PROBING)
+               siop_del_dev(sc, target, lun);
+       if (restart)
+               CALL_SCRIPT(Ent_script_sched);
        siop_start(sc);
        return 1;
 }
@@ -948,7 +958,6 @@
        struct scsipi_xfer *xs = siop_cmd->xs;
        struct siop_softc *sc = siop_cmd->siop_sc;
 
-       xs->status = le32toh(siop_cmd->siop_tables.status);
        switch(xs->status) {
        case SCSI_OK:
                xs->error = XS_NOERROR;
@@ -958,6 +967,9 @@
                break;
        case SCSI_CHECK:
                xs->error = XS_BUSY;
+               /* remove commands in the queue and scheduler */
+               siop_unqueue(sc, xs->xs_periph->periph_target,
+                   xs->xs_periph->periph_lun);
                break;
        case SCSI_QUEUE_FULL:
                INCSTAT(siop_stat_intr_qfull);
@@ -993,10 +1005,82 @@
        bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
        callout_stop(&siop_cmd->xs->xs_callout);
        siop_cmd->status = CMDST_FREE;
+       TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
        xs->resid = 0;
        scsipi_done (xs);
 }
 
+void
+siop_unqueue(sc, target, lun)
+       struct siop_softc *sc;
+       int target;
+       int lun;
+{
+       int slot, tag;
+       struct siop_cmd *siop_cmd, *next_siop_cmd;
+       struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];
+
+       /* first make sure to read valid data */
+       siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+       for (tag = 1; tag < SIOP_NTAG; tag++) {
+               /* look for commands in the scheduler, not yet started */
+               if (siop_lun->siop_tag[tag].active == NULL) 
+                       continue;
+               siop_cmd = siop_lun->siop_tag[tag].active;
+               for (slot = 0; slot <= sc->sc_currschedslot; slot++) {
+                       if (siop_script_read(sc,
+                           (Ent_script_sched_slot0 / 4) + slot * 2 + 1) ==
+                           siop_cmd->dsa + sizeof(struct siop_xfer_common) +
+                           Ent_ldsa_select)
+                               break;
+               }
+               if (slot >  sc->sc_currschedslot)
+                       continue; /* didn't find it */
+               if (siop_script_read(sc,
+                   (Ent_script_sched_slot0 / 4) + slot * 2) == 0x80000000)
+                       continue; /* already started */
+               /* clear the slot */
+               siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
+                   0x80000000);
+               /* ask to requeue */
+               siop_cmd->xs->error = XS_REQUEUE;
+               siop_cmd->xs->status = SCSI_SIOP_NOCHECK;
+               siop_lun->siop_tag[tag].active = NULL;
+               siop_scsicmd_end(siop_cmd);
+       }
+       /* update sc_currschedslot */
+       sc->sc_currschedslot = 0;
+       for (slot = 0; slot < SIOP_NSLOTS; slot++) {
+               if (siop_script_read(sc,
+                   (Ent_script_sched_slot0 / 4) + slot * 2) != 0x80000000)
+                       sc->sc_currschedslot = slot;
+       }
+       /* clean up the urgent and ready lists */
+       for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
+           siop_cmd = next_siop_cmd) {
+               next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
+               if (siop_cmd->xs->xs_periph->periph_target == target &&
+                   siop_cmd->xs->xs_periph->periph_lun == lun) {
+                       TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
+                       siop_cmd->xs->error = XS_REQUEUE;
+                       siop_cmd->xs->status = SCSI_SIOP_NOCHECK;
+                       siop_scsicmd_end(siop_cmd);
+               }
+       }
+       for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
+           siop_cmd = next_siop_cmd) {
+               next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
+               if (siop_cmd->xs->xs_periph->periph_target == target &&
+                   siop_cmd->xs->xs_periph->periph_lun == lun) {
+                       TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
+                       siop_cmd->xs->error = XS_REQUEUE;
+                       siop_cmd->xs->status = SCSI_SIOP_NOCHECK;
+                       siop_scsicmd_end(siop_cmd);
+               }
+       }
+}
+
 /*
  * handle a rejected queue tag message: the command will run untagged,
  * has to adjust the reselect script.
@@ -1117,13 +1201,12 @@
                next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
                siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?
                    XS_TIMEOUT : XS_RESET;
-               siop_cmd->siop_tables.status = htole32(SCSI_SIOP_NOCHECK);
+               siop_cmd->xs->status = SCSI_SIOP_NOCHECK;
                printf("cmd %p (status %d) about to be processed\n", siop_cmd,
                    siop_cmd->status);
                siop_cmd->status = CMDST_DONE;
                TAILQ_REMOVE(&reset_list, siop_cmd, next);
                siop_scsicmd_end(siop_cmd);
-               TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
        }
        scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_RESET, NULL);
 }
@@ -1168,6 +1251,7 @@
                }
                if (siop_cmd == NULL) {
                        xs->error = XS_RESOURCE_SHORTAGE;
+                       scsipi_done(xs);
                        splx(s);
                        return;
                }
@@ -1187,6 +1271,7 @@
                                printf("%s: can't malloc memory for "
                                    "target %d\n", sc->sc_dev.dv_xname, target);
                                xs->error = XS_RESOURCE_SHORTAGE;
+                               scsipi_done(xs);
                                splx(s);
                                return;
                        }
@@ -1203,6 +1288,7 @@
                                printf("%s: can't alloc lunsw for target %d\n",
                                    sc->sc_dev.dv_xname, target);
                                xs->error = XS_RESOURCE_SHORTAGE;
+                               scsipi_done(xs);
                                splx(s);
                                return;
                        }
@@ -1218,6 +1304,7 @@
                                    "target %d lun %d\n",
                                    sc->sc_dev.dv_xname, target, lun);
                                xs->error = XS_RESOURCE_SHORTAGE;
+                               scsipi_done(xs);
                                splx(s);
                                return;
                        }
@@ -1236,6 +1323,7 @@
                        printf("%s: unable to load cmd DMA map: %d",
                            sc->sc_dev.dv_xname, error);
                        xs->error = XS_DRIVER_STUFFUP;
+                       scsipi_done(xs);
                        splx(s);
                        return;
                }
@@ -1247,6 +1335,7 @@
                                printf("%s: unable to load cmd DMA map: %d",
                                    sc->sc_dev.dv_xname, error);
                                xs->error = XS_DRIVER_STUFFUP;
+                               scsipi_done(xs);
                                bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
                                splx(s);
                                return;
@@ -1260,8 +1349,10 @@
                    siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
 
                siop_setuptables(siop_cmd);
-
-               TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
+               if (xs->xs_control & XS_CTL_URGENT)
+                       TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
+               else
+                       TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
                siop_start(sc);
                if (xs->xs_control & XS_CTL_POLL) {
                        /* poll for command completion */
diff -r 29b4786df579 -r 76174631dddb sys/dev/ic/siop_common.c
--- a/sys/dev/ic/siop_common.c  Mon Jan 22 17:43:02 2001 +0000
+++ b/sys/dev/ic/siop_common.c  Mon Jan 22 17:46:31 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop_common.c,v 1.11.2.5 2001/01/15 09:26:26 bouyer Exp $      */
+/*     $NetBSD: siop_common.c,v 1.11.2.6 2001/01/22 17:46:32 bouyer Exp $      */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -133,7 +133,11 @@
 
        siop_cmd->siop_tables.id = htole32(sc->targets[target]->id);
        memset(siop_cmd->siop_tables.msg_out, 0, 8);
-       siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 1);
+       /* request sense doesn't disconnect */
+       if (xs->xs_control & XS_CTL_REQSENSE)
+               siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 0);
+       else
+               siop_cmd->siop_tables.msg_out[0] = MSG_IDENTIFY(lun, 1);
        siop_cmd->siop_tables.t_msgout.count= htole32(1);
        if (sc->targets[target]->status == TARST_ASYNC) {
                if (sc->targets[target]->flags & TARF_WIDE) {



Home | Main Index | Thread Index | Old Index