summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp.c
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2002-03-21 21:10:16 +0000
committermjacob <mjacob@FreeBSD.org>2002-03-21 21:10:16 +0000
commitf871caa64260041aff351887f9b08c3902a94dc4 (patch)
treeaceea3c3076a131cbc41c2d9a837c1df5eaa7c2e /sys/dev/isp/isp.c
parent15e963f1603b80258cd945e79f1194e029b58d6c (diff)
downloadFreeBSD-src-f871caa64260041aff351887f9b08c3902a94dc4.zip
FreeBSD-src-f871caa64260041aff351887f9b08c3902a94dc4.tar.gz
Limit fabric search to a default 256 entries. This will all go away
soon because it's just getting harder and harder to find switches that correctly implement the GET ALL NEXT subcommands for the SNS protocol. Latch up result out pointer and set a busy flag when we're looking at the response queue. This allows for a cleaner way to make sure we don't get multiple CPUs trying to read the same response queue entries. Change how isp_handle_other_response returns values (clarity). Make PORT UNAVAILABLE the same as PORT LOGOUT (force a LIP). Do some formatting changes. MFC after: 0 days
Diffstat (limited to 'sys/dev/isp/isp.c')
-rw-r--r--sys/dev/isp/isp.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index cfae85f..b6b9d4d 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -2298,6 +2298,9 @@ isp_scan_loop(struct ispsoftc *isp)
return (0);
}
+#ifndef HICAP_MAX
+#define HICAP_MAX 256
+#endif
static int
isp_scan_fabric(struct ispsoftc *isp)
{
@@ -2320,7 +2323,7 @@ isp_scan_fabric(struct ispsoftc *isp)
first_portid = portid = fcp->isp_portid;
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
- for (first_portid_seen = hicap = 0; hicap < 65535; hicap++) {
+ for (first_portid_seen = hicap = 0; hicap < HICAP_MAX; hicap++) {
mbreg_t mbs;
sns_screq_t *rq;
sns_ganrsp_t *rs0, *rs1;
@@ -3133,6 +3136,7 @@ again:
} else {
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
}
+ isp->isp_resodx = iptr;
if (optr == iptr && sema == 0) {
@@ -3167,9 +3171,15 @@ again:
isr, junk, iptr, optr);
}
}
+ isp->isp_resodx = iptr;
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
ISP_WRITE(isp, BIU_SEMA, 0);
+ if (isp->isp_rspbsy) {
+ return;
+ }
+ isp->isp_rspbsy = 1;
+
while (optr != iptr) {
ispstatusreq_t local, *sp = &local;
isphdr_t *hp;
@@ -3198,19 +3208,17 @@ again:
}
if (isp->isp_fpcchiwater < rio.req_header.rqs_seqno)
isp->isp_fpcchiwater = rio.req_header.rqs_seqno;
+ MEMZERO(hp, QENTRY_LEN); /* PERF */
continue;
} else {
/*
* Somebody reachable via isp_handle_other_response
* may have updated the response queue pointers for
- * us.
+ * us, so we reload our goal index.
*/
- oop = optr;
- if (!isp_handle_other_response(isp, type, hp, &optr)) {
+ if (isp_handle_other_response(isp, type, hp, &optr)) {
+ iptr = isp->isp_resodx;
MEMZERO(hp, QENTRY_LEN); /* PERF */
- if (oop != optr) {
- goto out;
- }
continue;
}
@@ -3438,7 +3446,7 @@ again:
}
isp->isp_residx = optr;
-out:
+ isp->isp_rspbsy = 0;
for (i = 0; i < ndone; i++) {
xs = complist[i];
if (xs) {
@@ -3788,7 +3796,7 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
switch (type) {
case RQSTYPE_STATUS_CONT:
isp_prt(isp, ISP_LOGINFO, "Ignored Continuation Response");
- return (0);
+ return (1);
case RQSTYPE_ATIO:
case RQSTYPE_CTIO:
case RQSTYPE_ENABLE_LUN:
@@ -3801,7 +3809,9 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
case RQSTYPE_CTIO3:
isp->isp_rsltccmplt++; /* count as a response completion */
#ifdef ISP_TARGET_MODE
- return (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp));
+ if (isp_target_notify(isp, (ispstatusreq_t *) hp, optrp)) {
+ return (1);
+ }
#else
optrp = optrp;
/* FALLTHROUGH */
@@ -3809,11 +3819,11 @@ isp_handle_other_response(struct ispsoftc *isp, int type,
case RQSTYPE_REQUEST:
default:
if (isp_async(isp, ISPASYNC_UNHANDLED_RESPONSE, hp)) {
- return (0);
+ return (1);
}
isp_prt(isp, ISP_LOGWARN, "Unhandled Response Type 0x%x",
isp_get_response_type(isp, hp));
- return (-1);
+ return (0);
}
}
@@ -4117,18 +4127,16 @@ isp_parse_status(struct ispsoftc *isp, ispstatusreq_t *sp, XS_T *xs)
/*
* No such port on the loop. Moral equivalent of SELTIMEO
*/
- isp_prt(isp, ISP_LOGINFO,
- "Port Unavailable for target %d", XS_TGT(xs));
- if (XS_NOERR(xs)) {
- XS_SETERR(xs, HBA_SELTIMEOUT);
- }
- return;
case RQCS_PORT_LOGGED_OUT:
/*
* It was there (maybe)- treat as a selection timeout.
*/
- isp_prt(isp, ISP_LOGINFO,
- "port logout for target %d", XS_TGT(xs));
+ if ((sp->req_completion_status & 0xff) == RQCS_PORT_UNAVAILABLE)
+ isp_prt(isp, ISP_LOGINFO,
+ "Port Unavailable for target %d", XS_TGT(xs));
+ else
+ isp_prt(isp, ISP_LOGINFO,
+ "port logout for target %d", XS_TGT(xs));
/*
* If we're on a local loop, force a LIP (which is overkill)
* to force a re-login of this unit.
OpenPOWER on IntegriCloud