summaryrefslogtreecommitdiff
path: root/sys/dev/ic/isp.c
diff options
context:
space:
mode:
authormjacob <mjacob@cvs.openbsd.org>2001-10-24 18:31:16 +0000
committermjacob <mjacob@cvs.openbsd.org>2001-10-24 18:31:16 +0000
commit7fc6981cc9fcf51e119b92c877767f150dd930e0 (patch)
tree6cba97fa169717c09a35bfd710460243484d94f3 /sys/dev/ic/isp.c
parent3f748c5670534374035e0849501c242330e962e4 (diff)
Protect against deranged fabric name servers.
Correct the # of output mailboxes for EXECUTE IOCB A64. Comment out some redundant initialization to zero. If we get ISP_QUEUES_FULL status, remember to actually set SCSI_QFULL since the QLogic f/w, on some cards, doesn't do so. Grumble.
Diffstat (limited to 'sys/dev/ic/isp.c')
-rw-r--r--sys/dev/ic/isp.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/sys/dev/ic/isp.c b/sys/dev/ic/isp.c
index 53deaf4244e..aa7be6eb073 100644
--- a/sys/dev/ic/isp.c
+++ b/sys/dev/ic/isp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isp.c,v 1.23 2001/10/06 22:45:52 mjacob Exp $ */
+/* $OpenBSD: isp.c,v 1.24 2001/10/24 18:31:15 mjacob Exp $ */
/*
* Machine and OS Independent (well, as best as possible)
* code for the Qlogic ISP SCSI adapters.
@@ -2263,11 +2263,11 @@ static int
isp_scan_fabric(struct ispsoftc *isp)
{
fcparam *fcp = isp->isp_param;
- u_int32_t portid, first_portid;
+ u_int32_t portid, first_portid, last_portid;
sns_screq_t *reqp;
sns_scrsp_t *resp;
mbreg_t mbs;
- int hicap, first_portid_seen;
+ int hicap, first_portid_seen, last_port_same;
if (fcp->isp_onfabric == 0) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
@@ -2280,6 +2280,8 @@ isp_scan_fabric(struct ispsoftc *isp)
* Since Port IDs are 24 bits, we can check against having seen
* anything yet with this value.
*/
+ last_port_same = 0;
+ last_portid = 0xffffffff; /* not a port */
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
@@ -2358,9 +2360,20 @@ isp_scan_fabric(struct ispsoftc *isp)
fcp->isp_loopstate = LOOP_FSCAN_DONE;
return (0);
}
+ if (portid == last_portid) {
+ if (last_port_same++ > 20) {
+ isp_prt(isp, ISP_LOGWARN,
+ "tangled fabric database detected");
+ break;
+ }
+ } else {
+ last_portid = portid;
+ }
}
- isp_prt(isp, ISP_LOGWARN, "broken fabric nameserver...*wheeze*...");
+ if (hicap >= 65535) {
+ isp_prt(isp, ISP_LOGWARN, "fabric too big (> 65535)");
+ }
/*
* We either have a broken name server or a huge fabric if we get here.
@@ -2701,13 +2714,13 @@ isp_start(XS_T *xs)
else
reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
}
- reqp->req_header.rqs_flags = 0;
- reqp->req_header.rqs_seqno = 0;
+ /* reqp->req_header.rqs_flags = 0; */
+ /* reqp->req_header.rqs_seqno = 0; */
if (IS_FC(isp)) {
/*
* See comment in isp_intr
*/
- XS_RESID(xs) = 0;
+ /* XS_RESID(xs) = 0; */
/*
* Fibre Channel always requires some kind of tag.
@@ -2758,7 +2771,7 @@ isp_start(XS_T *xs)
reqp->req_time = 5;
}
if (isp_save_xs(isp, xs, &handle)) {
- isp_prt(isp, ISP_LOGDEBUG1, "out of xflist pointers");
+ isp_prt(isp, ISP_LOGDEBUG0, "out of xflist pointers");
XS_SETERR(xs, HBA_BOTCH);
return (CMD_EAGAIN);
}
@@ -3270,6 +3283,11 @@ isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
*XS_STSP(xs) = SCSI_QFULL;
XS_SETERR(xs, HBA_NOERROR);
} else if (XS_NOERR(xs)) {
+ /*
+ * ????
+ */
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "Request Queue Entry bounced back");
XS_SETERR(xs, HBA_BOTCH);
}
XS_RESID(xs) = XS_XFRLEN(xs);
@@ -3889,18 +3907,30 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
break;
case RQCS_QUEUE_FULL:
- isp_prt(isp, ISP_LOGDEBUG1,
+ isp_prt(isp, ISP_LOGDEBUG0,
"internal queues full for %d.%d.%d status 0x%x", XS_TGT(xs),
XS_LUN(xs), XS_CHANNEL(xs), *XS_STSP(xs));
+
/*
* If QFULL or some other status byte is set, then this
* isn't an error, per se.
- */
+ *
+ * Unfortunately, some QLogic f/w writers have, in
+ * some cases, ommitted to *set* status to QFULL.
+ *
+
if (*XS_STSP(xs) != SCSI_GOOD && XS_NOERR(xs)) {
XS_SETERR(xs, HBA_NOERROR);
return;
}
- break;
+
+ *
+ *
+ */
+
+ *XS_STSP(xs) = SCSI_QFULL;
+ XS_SETERR(xs, HBA_NOERROR);
+ return;
case RQCS_PHASE_SKIPPED:
isp_prt(isp, ISP_LOGERR, pskip, XS_CHANNEL(xs),
@@ -4118,7 +4148,7 @@ static u_int16_t mbpscsi[] = {
ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */
ISPOPMAP(0xdf, 0xdf), /* 0x52: INITIALIZE REQUEST QUEUE A64 */
ISPOPMAP(0xff, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */
- ISPOPMAP(0xcf, 0xff), /* 0x54: EXECUTE IOCB A64 */
+ ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */
ISPOPMAP(0x07, 0x01), /* 0x55: ENABLE TARGET MODE */
ISPOPMAP(0x03, 0x0f), /* 0x56: GET TARGET STATUS */
ISPOPMAP(0x00, 0x00), /* 0x57: */