Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-3]: src/sys/dev Pull up following revision(s) (requested by bouye...
details: https://anonhg.NetBSD.org/src/rev/e7bba7ab8155
branches: netbsd-3
changeset: 577528:e7bba7ab8155
user: tron <tron%NetBSD.org@localhost>
date: Mon Nov 21 20:55:44 2005 +0000
description:
Pull up following revision(s) (requested by bouyer in ticket #973):
sys/dev/ic/siop.c: revision 1.79
sys/dev/ic/siopvar_common.h: revision 1.33
sys/dev/ic/esiopvar.h: revision 1.13
sys/dev/ic/esiop.c: revision 1.34
sys/dev/microcode/siop/esiop.ss: revision 1.20
sys/dev/ic/siopvar.h: revision 1.22
sys/dev/microcode/siop/siop.ss: revision 1.20
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 04c8c7f0a8d4 -r e7bba7ab8155 sys/dev/ic/esiop.c
--- a/sys/dev/ic/esiop.c Mon Nov 21 20:51:21 2005 +0000
+++ b/sys/dev/ic/esiop.c Mon Nov 21 20:55:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: esiop.c,v 1.32.4.1 2005/04/21 16:55:20 tron Exp $ */
+/* $NetBSD: esiop.c,v 1.32.4.2 2005/11/21 20:55:44 tron 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.32.4.1 2005/04/21 16:55:20 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.32.4.2 2005/11/21 20:55:44 tron Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -252,6 +252,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,
@@ -290,6 +298,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]] =
@@ -1071,6 +1086,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);
@@ -1125,6 +1143,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);
@@ -1213,7 +1242,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);
@@ -1294,10 +1323,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;
}
@@ -1603,14 +1637,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);
}
@@ -1958,10 +1991,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 04c8c7f0a8d4 -r e7bba7ab8155 sys/dev/ic/esiopvar.h
--- a/sys/dev/ic/esiopvar.h Mon Nov 21 20:51:21 2005 +0000
+++ b/sys/dev/ic/esiopvar.h Mon Nov 21 20:55:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: esiopvar.h,v 1.12 2005/02/27 00:27:01 perry Exp $ */
+/* $NetBSD: esiopvar.h,v 1.12.2.1 2005/11/21 20:55:44 tron 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 04c8c7f0a8d4 -r e7bba7ab8155 sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Mon Nov 21 20:51:21 2005 +0000
+++ b/sys/dev/ic/siop.c Mon Nov 21 20:55:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siop.c,v 1.78 2005/02/27 00:27:02 perry Exp $ */
+/* $NetBSD: siop.c,v 1.78.2.1 2005/11/21 20:55:44 tron 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.78 2005/02/27 00:27:02 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.78.2.1 2005/11/21 20:55:44 tron 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 04c8c7f0a8d4 -r e7bba7ab8155 sys/dev/ic/siopvar.h
--- a/sys/dev/ic/siopvar.h Mon Nov 21 20:51:21 2005 +0000
+++ b/sys/dev/ic/siopvar.h Mon Nov 21 20:55:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siopvar.h,v 1.21 2005/02/27 00:27:02 perry Exp $ */
+/* $NetBSD: siopvar.h,v 1.21.2.1 2005/11/21 20:55:44 tron 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 04c8c7f0a8d4 -r e7bba7ab8155 sys/dev/ic/siopvar_common.h
--- a/sys/dev/ic/siopvar_common.h Mon Nov 21 20:51:21 2005 +0000
+++ b/sys/dev/ic/siopvar_common.h Mon Nov 21 20:55:44 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siopvar_common.h,v 1.32 2005/02/27 00:27:02 perry Exp $ */
+/* $NetBSD: siopvar_common.h,v 1.32.2.1 2005/11/21 20:55:44 tron 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