Source-Changes-HG archive

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

[src/netbsd-2]: src/sys/dev Pull up following revision(s) (requested by bouye...



details:   https://anonhg.NetBSD.org/src/rev/74f4313b8e56
branches:  netbsd-2
changeset: 564349:74f4313b8e56
user:      riz <riz%NetBSD.org@localhost>
date:      Thu Dec 01 20:05:26 2005 +0000

description:
Pull up following revision(s) (requested by bouyer in ticket #10168):
        sys/dev/ic/siop.c: revision 1.79 via patch
        sys/dev/ic/siopvar_common.h: revision 1.33 via patch
        sys/dev/ic/esiopvar.h: revision 1.13 via patch
        sys/dev/ic/esiop.c: revision 1.34 via patch
        sys/dev/microcode/siop/esiop.ss: revision 1.20 via patch
        sys/dev/ic/siopvar.h: revision 1.22 via patch
        sys/dev/microcode/siop/siop.ss: revision 1.20 via patch
Some drives disconnect after the last data phase without a save data pointer
message. In such case we would not update resid with the proper value
(eventually resid would not be updated at all if there was only one data
phase). To fix this, have the script save the offset in the data tables at
disconnect time if there was a transfer, and use this to compute the resid
if the current offset is 0.
Problem reported and patch tested by edwin, Roy Bixler and YAMAMOTO Takashi.
Fix kern/31990 by YAMAMOTO Takashi.

diffstat:

 sys/dev/ic/esiop.c              |  65 +++++++++++++++++++++++++++++++---------
 sys/dev/ic/esiopvar.h           |   6 ++-
 sys/dev/ic/siop.c               |  34 ++++++++++++++++++--
 sys/dev/ic/siopvar.h            |   3 +-
 sys/dev/ic/siopvar_common.h     |   7 +++-
 sys/dev/microcode/siop/esiop.ss |  16 +++++++--
 sys/dev/microcode/siop/siop.ss  |  10 ++++-
 7 files changed, 110 insertions(+), 31 deletions(-)

diffs (truncated from 379 to 300 lines):

diff -r c76e75fbbc82 -r 74f4313b8e56 sys/dev/ic/esiop.c
--- a/sys/dev/ic/esiop.c        Thu Dec 01 19:55:25 2005 +0000
+++ b/sys/dev/ic/esiop.c        Thu Dec 01 20:05:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esiop.c,v 1.27.4.5 2005/05/16 05:15:48 riz Exp $       */
+/*     $NetBSD: esiop.c,v 1.27.4.6 2005/12/01 20:05:26 riz Exp $       */
 
 /*
  * Copyright (c) 2002 Manuel Bouyer.
@@ -33,7 +33,7 @@
 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.27.4.5 2005/05/16 05:15:48 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.27.4.6 2005/12/01 20:05:26 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -253,6 +253,14 @@
                            sizeof(struct siop_common_xfer));
                }
                for (j = 0; j <
+                   (sizeof(E_saved_offset_offset_Used) /
+                    sizeof(E_saved_offset_offset_Used[0]));
+                   j++) {
+                       bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
+                           E_saved_offset_offset_Used[j] * 4,
+                           sizeof(struct siop_common_xfer) + 4);
+               }
+               for (j = 0; j <
                    (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
                    j++) {
                        bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
@@ -291,6 +299,13 @@
                            htole32(sizeof(struct siop_common_xfer));
                }
                for (j = 0; j <
+                   (sizeof(E_saved_offset_offset_Used) /
+                    sizeof(E_saved_offset_offset_Used[0]));
+                   j++) {
+                       sc->sc_c.sc_script[E_saved_offset_offset_Used[j]] =
+                           htole32(sizeof(struct siop_common_xfer) + 4);
+               }
+               for (j = 0; j <
                    (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
                    j++) {
                        sc->sc_c.sc_script[E_abs_msgin2_Used[j]] =
@@ -1072,6 +1087,9 @@
                        printf("disconnect offset %d\n", offset);
 #endif
                        siop_sdp(&esiop_cmd->cmd_c, offset);
+                       /* we start again with no offset */
+                       ESIOP_XFER(esiop_cmd, saved_offset) =
+                           htole32(SIOP_NOOFFSET);
                        esiop_table_sync(esiop_cmd,
                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                        CALL_SCRIPT(Ent_script_sched);
@@ -1126,6 +1144,17 @@
                esiop_lun->active = NULL;
        offset = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
            SIOP_SCRATCHA + 1);
+       /*
+        * if we got a disconnect between the last data phase
+        * and the status phase, offset will be 0. In this
+        * case, cmd_tables->saved_offset will have the proper value 
+        * if it got updated by the controller
+        */
+       if (offset == 0 &&
+           ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
+               offset =
+                   (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
+
        esiop_scsicmd_end(esiop_cmd, offset);
        if (freetarget && esiop_target->target_c.status == TARST_PROBING)
                esiop_del_dev(sc, target, lun);
@@ -1214,7 +1243,7 @@
        u_int32_t slot;
        int needsync = 0;
        int status;
-       u_int32_t sem;
+       u_int32_t sem, offset;
 
        esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        sem = esiop_script_read(sc, sc->sc_semoffset);
@@ -1295,10 +1324,15 @@
                esiop_lun->tactive[tag] = NULL;
        else
                esiop_lun->active = NULL;
-       /* scratcha was saved in tlq by script. fetch offset from it */
-       esiop_scsicmd_end(esiop_cmd,
-           (le32toh(((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq) >> 8)
-           & 0xff);
+       /*
+        * scratcha was eventually saved in saved_offset by script.
+        * fetch offset from it
+        */
+       offset = 0;
+       if (ESIOP_XFER(esiop_cmd, saved_offset) != htole32(SIOP_NOOFFSET))
+               offset =
+                   (le32toh(ESIOP_XFER(esiop_cmd, saved_offset)) >> 8) & 0xff;
+       esiop_scsicmd_end(esiop_cmd, offset);
        goto next;
 }
 
@@ -1604,14 +1638,13 @@
                else
                        esiop_cmd->cmd_c.tag = -1;
                siop_setuptables(&esiop_cmd->cmd_c);
-               ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq =
-                   htole32(A_f_c_target | A_f_c_lun);
-               ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
+               ESIOP_XFER(esiop_cmd, saved_offset) = htole32(SIOP_NOOFFSET);
+               ESIOP_XFER(esiop_cmd, tlq) = htole32(A_f_c_target | A_f_c_lun);
+               ESIOP_XFER(esiop_cmd, tlq) |=
                    htole32((target << 8) | (lun << 16));
                if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
-                       ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
-                           htole32(A_f_c_tag);
-                       ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
+                       ESIOP_XFER(esiop_cmd, tlq) |= htole32(A_f_c_tag);
+                       ESIOP_XFER(esiop_cmd, tlq) |=
                            htole32(esiop_cmd->cmd_c.tag << 24);
                }
 
@@ -1959,10 +1992,12 @@
                TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
                splx(s);
 #ifdef SIOP_DEBUG
-               printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
+               printf("tables[%d]: in=0x%x out=0x%x status=0x%x "
+                   "offset=0x%x\n", i,
                    le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
                    le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
-                   le32toh(newcbd->cmds[i].cmd_tables->t_status.addr));
+                   le32toh(newcbd->cmds[i].cmd_tables->t_status.addr,
+                   le32toh(newcbd->cmds[i].cmd_tables->t_offset.addr));
 #endif
        }
        s = splbio();
diff -r c76e75fbbc82 -r 74f4313b8e56 sys/dev/ic/esiopvar.h
--- a/sys/dev/ic/esiopvar.h     Thu Dec 01 19:55:25 2005 +0000
+++ b/sys/dev/ic/esiopvar.h     Thu Dec 01 20:05:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: esiopvar.h,v 1.8.4.1 2005/05/11 03:19:58 snj Exp $     */
+/*     $NetBSD: esiopvar.h,v 1.8.4.2 2005/12/01 20:05:26 riz Exp $     */
 
 /*
  * Copyright (c) 2002 Manuel Bouyer.
@@ -53,9 +53,11 @@
 struct esiop_xfer {
        struct siop_common_xfer siop_tables;
        u_int32_t tlq; /* target/lun/tag loaded in scratchC by script */
-                     /* will also containt scratcha at end of command */
+       u_int32_t saved_offset;/* contains scratchA if script saved an offset */
 } __attribute__((__packed__));
 
+#define ESIOP_XFER(cmd, m) (((struct esiop_xfer *)((cmd)->cmd_tables))->m)
+
 /*
  * This describes a command handled by the SCSI controller
  * These are chained in either a free list or a active list
diff -r c76e75fbbc82 -r 74f4313b8e56 sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Thu Dec 01 19:55:25 2005 +0000
+++ b/sys/dev/ic/siop.c Thu Dec 01 20:05:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siop.c,v 1.72.4.4 2005/05/11 04:06:08 snj Exp $        */
+/*     $NetBSD: siop.c,v 1.72.4.5 2005/12/01 20:05:26 riz Exp $        */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -33,7 +33,7 @@
 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.72.4.4 2005/05/11 04:06:08 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.72.4.5 2005/12/01 20:05:26 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -103,6 +103,7 @@
 static int siop_stat_intr = 0;
 static int siop_stat_intr_shortxfer = 0;
 static int siop_stat_intr_sdp = 0;
+static int siop_stat_intr_saveoffset = 0;
 static int siop_stat_intr_done = 0;
 static int siop_stat_intr_xferdisc = 0;
 static int siop_stat_intr_lunresel = 0;
@@ -911,10 +912,22 @@
                        printf("disconnect offset %d\n", offset);
 #endif
                        siop_sdp(&siop_cmd->cmd_c, offset);
+                       /* we start again with no offset */
+                       siop_cmd->saved_offset = SIOP_NOOFFSET;
                        siop_table_sync(siop_cmd,
                            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                        CALL_SCRIPT(Ent_script_sched);
                        return 1;
+               case A_int_saveoffset:
+                       INCSTAT(siop_stat_intr_saveoffset);
+                       offset = bus_space_read_1(sc->sc_c.sc_rt,
+                           sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
+#ifdef SIOP_DEBUG_DR
+                       printf("saveoffset offset %d\n", offset);
+#endif
+                       siop_cmd->saved_offset = offset;
+                       CALL_SCRIPT(Ent_script_sched);
+                       return 1;
                case A_int_resfail:
                        printf("reselect failed\n");
                        CALL_SCRIPT(Ent_script_sched);
@@ -939,6 +952,15 @@
                        /* update resid.  */
                        offset = bus_space_read_1(sc->sc_c.sc_rt,
                            sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
+                       /*
+                        * if we got a disconnect between the last data phase
+                        * and the status phase, offset will be 0. In this
+                        * case, siop_cmd->saved_offset will have the proper
+                        * value if it got updated by the controller
+                        */
+                       if (offset == 0 && 
+                           siop_cmd->saved_offset != SIOP_NOOFFSET)
+                               offset = siop_cmd->saved_offset;
                        siop_update_resid(&siop_cmd->cmd_c, offset);
                        siop_cmd->cmd_c.status = CMDST_DONE;
                        goto end;
@@ -1348,6 +1370,7 @@
                        siop_cmd->cmd_c.tag = 0;
                }
                siop_setuptables(&siop_cmd->cmd_c);
+               siop_cmd->saved_offset = SIOP_NOOFFSET;
                siop_table_sync(siop_cmd,
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                siop_start(sc, siop_cmd);
@@ -1717,10 +1740,12 @@
                TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
                splx(s);
 #ifdef SIOP_DEBUG
-               printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
+               printf("tables[%d]: in=0x%x out=0x%x status=0x%x "
+                   "offset=0x%x\n", i,
                    le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
                    le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
-                   le32toh(newcbd->cmds[i].cmd_tables->t_status.addr));
+                   le32toh(newcbd->cmds[i].cmd_tables->t_status.addr),
+                   le32toh(newcbd->cmds[i].cmd_tables->t_offset.addr));
 #endif
        }
        s = splbio();
@@ -2002,6 +2027,7 @@
        printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
        printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
        printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
+       printf("siop_stat_intr_saveoffset %d\n", siop_stat_intr_saveoffset);
        printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
        printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
        printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
diff -r c76e75fbbc82 -r 74f4313b8e56 sys/dev/ic/siopvar.h
--- a/sys/dev/ic/siopvar.h      Thu Dec 01 19:55:25 2005 +0000
+++ b/sys/dev/ic/siopvar.h      Thu Dec 01 20:05:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siopvar.h,v 1.19 2003/11/02 11:07:46 wiz Exp $ */
+/*     $NetBSD: siopvar.h,v 1.19.6.1 2005/12/01 20:05:26 riz Exp $     */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -56,6 +56,7 @@
        struct siop_common_cmd cmd_c;
        struct siop_cbd *siop_cbdp; /* pointer to our siop_cbd */
        int reselslot;
+       u_int32_t saved_offset; /* offset in table after disc without sdp */
 };
 #define cmd_tables cmd_c.siop_tables
 
diff -r c76e75fbbc82 -r 74f4313b8e56 sys/dev/ic/siopvar_common.h
--- a/sys/dev/ic/siopvar_common.h       Thu Dec 01 19:55:25 2005 +0000
+++ b/sys/dev/ic/siopvar_common.h       Thu Dec 01 20:05:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: siopvar_common.h,v 1.27.4.2 2005/05/11 03:59:14 snj Exp $      */
+/*     $NetBSD: siopvar_common.h,v 1.27.4.3 2005/12/01 20:05:26 riz Exp $      */
 
 /*
  * Copyright (c) 2000 Manuel Bouyer.
@@ -56,7 +56,7 @@
        u_int8_t msg_out[16];   /* 0 */
        u_int8_t msg_in[16];    /* 16 */
        u_int32_t status;       /* 32 */
-       u_int32_t pad1;         /* 36 */
+       u_int32_t pad1;         /* 36 */
        u_int32_t id;           /* 40 */
        u_int32_t pad2;         /* 44 */
        scr_table_t t_msgin;    /* 48 */
@@ -72,6 +72,9 @@
 #define SCSI_SIOP_NOCHECK      0xfe    /* don't check the scsi status */
 #define SCSI_SIOP_NOSTATUS     0xff    /* device didn't report status */
 
+/* offset is initialised to SIOP_NOOFFSET, used to check if it was updated */
+#define SIOP_NOOFFSET 0xffffffff
+
 /*



Home | Main Index | Thread Index | Old Index