diff options
| author | Matt Jacob <mjacob@FreeBSD.org> | 2002-03-21 23:22:21 +0000 |
|---|---|---|
| committer | Matt Jacob <mjacob@FreeBSD.org> | 2002-03-21 23:22:21 +0000 |
| commit | 9971f53bf62c52de8c4ef9c8c1b4aa841254119b (patch) | |
| tree | 57053634841a21ea9feed9bf11e6194569ef7130 /sys/dev/isp | |
| parent | 3e211ac1e426b9280594d803319f962bd24222a5 (diff) | |
Notes
Diffstat (limited to 'sys/dev/isp')
| -rw-r--r-- | sys/dev/isp/isp.c | 65 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.h | 2 | ||||
| -rw-r--r-- | sys/dev/isp/isp_target.h | 6 | ||||
| -rw-r--r-- | sys/dev/isp/ispvar.h | 4 |
4 files changed, 54 insertions, 23 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 8f0ddaacd2dd..b6b9d4d7b838 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1250,9 +1250,20 @@ isp_fibre_init(struct ispsoftc *isp) } #ifndef ISP_NO_RIO_FC - if ((isp->isp_role & ISP_ROLE_TARGET) == 0 && - ((IS_2100(isp) && ISP_FW_REVX(isp->isp_fwrev) >= - ISP_FW_REV(1, 17, 0)) || IS_2200(isp) || IS_23XX(isp))) { + /* + * RIO seems to be enabled in 2100s for fw >= 1.17.0. + * + * I've had some questionable problems with RIO on 2200. + * More specifically, on a 2204 I had problems with RIO + * on a Linux system where I was dropping commands right + * and left. It's not clear to me what the actual problem + * was, but it seems safer to only support this on the + * 23XX cards. + * + * I have it disabled if we support a target mode role for + * reasons I can't now remember. + */ + if ((isp->isp_role & ISP_ROLE_TARGET) == 0 && IS_23XX(isp)) { icbp->icb_xfwoptions |= ICBXOPT_RIO_16BIT; icbp->icb_racctimer = 4; icbp->icb_idelaytimer = 8; @@ -2287,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) { @@ -2309,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; @@ -3122,6 +3136,7 @@ again: } else { iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp); } + isp->isp_resodx = iptr; if (optr == iptr && sema == 0) { @@ -3156,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; @@ -3187,9 +3208,16 @@ 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 { - if (!isp_handle_other_response(isp, type, hp, &optr)) { + /* + * Somebody reachable via isp_handle_other_response + * may have updated the response queue pointers for + * us, so we reload our goal index. + */ + if (isp_handle_other_response(isp, type, hp, &optr)) { + iptr = isp->isp_resodx; MEMZERO(hp, QENTRY_LEN); /* PERF */ continue; } @@ -3410,7 +3438,7 @@ again: if (nlooked) { WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr); /* - * While we're at it, reqad the requst queue out pointer. + * While we're at it, read the requst queue out pointer. */ isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp); if (isp->isp_rscchiwater < ndone) @@ -3418,6 +3446,7 @@ again: } isp->isp_residx = optr; + isp->isp_rspbsy = 0; for (i = 0; i < ndone; i++) { xs = complist[i]; if (xs) { @@ -3767,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: @@ -3780,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 */ @@ -3788,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); } } @@ -4096,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. diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index 04c4972fd42f..2735d135a0a5 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -68,7 +68,7 @@ #define HANDLE_LOOPSTATE_IN_OUTER_LAYERS 1 -typedef void ispfwfunc __P((int, int, int, const u_int16_t **)); +typedef void ispfwfunc __P((int, int, int, u_int16_t **)); #ifdef ISP_TARGET_MODE #define ISP_TARGET_FUNCTIONS 1 diff --git a/sys/dev/isp/isp_target.h b/sys/dev/isp/isp_target.h index f911a17a75b4..5362987af071 100644 --- a/sys/dev/isp/isp_target.h +++ b/sys/dev/isp/isp_target.h @@ -409,9 +409,9 @@ typedef struct { isphdr_t ct_header; u_int16_t ct_reserved; u_int16_t ct_fwhandle; /* just to match CTIO */ - u_int8_t ct_lun; /* lun */ - u_int8_t ct_iid; /* initiator id */ - u_int16_t ct_rxid; /* response ID */ + u_int8_t ct_lun; /* lun */ + u_int8_t ct_iid; /* initiator id */ + u_int16_t ct_rxid; /* response ID */ u_int16_t ct_flags; u_int16_t ct_status; /* isp status */ u_int16_t ct_timeout; diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index c89f7d06207c..53025f1f27b8 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -73,7 +73,7 @@ struct ispmdvec { void (*dv_reset0) (struct ispsoftc *); void (*dv_reset1) (struct ispsoftc *); void (*dv_dregs) (struct ispsoftc *, const char *); - const u_int16_t *dv_ispfw; /* ptr to f/w */ + u_int16_t *dv_ispfw; /* ptr to f/w */ u_int16_t dv_conf1; u_int16_t dv_clock; /* clock frequency */ }; @@ -396,6 +396,8 @@ typedef struct ispsoftc { volatile u_int16_t isp_reqodx; /* index of last ISP pickup */ volatile u_int16_t isp_reqidx; /* index of next request */ volatile u_int16_t isp_residx; /* index of next result */ + volatile u_int16_t isp_resodx; /* index of next result */ + volatile u_int16_t isp_rspbsy; volatile u_int16_t isp_lasthdls; /* last handle seed */ volatile u_int16_t isp_mboxtmp[MAX_MAILBOX]; volatile u_int16_t isp_lastmbxcmd; /* last mbox command sent */ |
