summaryrefslogtreecommitdiff
path: root/sys/dev/isp
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2002-07-29 04:18:09 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2002-07-29 04:18:09 +0000
commit67198a155e144d0b9b2cbe317d4c757f5a3f9268 (patch)
tree6da1a79a0202b2f358777656c95a9a0b2ea138ce /sys/dev/isp
parentf24de6a5ed9ed1c2286c3f2d549e8b8c33274fea (diff)
Notes
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp_freebsd.c447
1 files changed, 295 insertions, 152 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index cedfaa8cfa4d..7523df7b69d6 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -197,7 +197,6 @@ isp_attach(struct ispsoftc *isp)
isp->isp_sim2 = sim;
isp->isp_path2 = path;
}
-
/*
* Create device nodes
*/
@@ -219,6 +218,21 @@ isp_attach(struct ispsoftc *isp)
}
+static __inline void
+isp_freeze_loopdown(struct ispsoftc *isp, char *msg)
+{
+ if (isp->isp_osinfo.simqfrozen == 0) {
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
+ isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ ISPLOCK_2_CAMLOCK(isp);
+ xpt_freeze_simq(isp->isp_sim, 1);
+ CAMLOCK_2_ISPLOCK(isp);
+ } else {
+ isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
+ isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ }
+}
+
static int
ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
{
@@ -264,12 +278,7 @@ ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
case ISP_FORCE_CRASH_DUMP:
ISP_LOCK(isp);
- if ((isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN) == 0) {
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
- ISPLOCK_2_CAMLOCK(isp);
- xpt_freeze_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
- }
+ isp_freeze_loopdown(isp, "ispioctl(ISP_FORCE_CRASH_DUMP)");
isp_fw_dump(isp);
isp_reinit(isp);
ISP_UNLOCK(isp);
@@ -369,7 +378,109 @@ ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
ISP_UNLOCK(isp);
retval = 0;
break;
+ case ISP_FC_GETHINFO:
+ {
+ struct isp_hba_device *hba = (struct isp_hba_device *) addr;
+ MEMZERO(hba, sizeof (*hba));
+ ISP_LOCK(isp);
+ hba->fc_speed = FCPARAM(isp)->isp_gbspeed;
+ hba->fc_scsi_supported = 1;
+ hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
+ hba->fc_loopid = FCPARAM(isp)->isp_loopid;
+ hba->active_node_wwn = FCPARAM(isp)->isp_nodewwn;
+ hba->active_port_wwn = FCPARAM(isp)->isp_portwwn;
+ ISP_UNLOCK(isp);
+ retval = 0;
+ break;
+ }
+ case ISP_GET_FC_PARAM:
+ {
+ struct isp_fc_param *f = (struct isp_fc_param *) addr;
+
+ if (!IS_FC(isp)) {
+ retval = EINVAL;
+ break;
+ }
+ f->parameter = 0;
+ if (strcmp(f->param_name, "framelength") == 0) {
+ f->parameter = FCPARAM(isp)->isp_maxfrmlen;
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "exec_throttle") == 0) {
+ f->parameter = FCPARAM(isp)->isp_execthrottle;
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "fullduplex") == 0) {
+ if (FCPARAM(isp)->isp_fwoptions & ICBOPT_FULL_DUPLEX)
+ f->parameter = 1;
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "loopid") == 0) {
+ f->parameter = FCPARAM(isp)->isp_loopid;
+ retval = 0;
+ break;
+ }
+ retval = EINVAL;
+ break;
+ }
+ case ISP_SET_FC_PARAM:
+ {
+ struct isp_fc_param *f = (struct isp_fc_param *) addr;
+ u_int32_t param = f->parameter;
+ if (!IS_FC(isp)) {
+ retval = EINVAL;
+ break;
+ }
+ f->parameter = 0;
+ if (strcmp(f->param_name, "framelength") == 0) {
+ if (param != 512 && param != 1024 && param != 1024) {
+ retval = EINVAL;
+ break;
+ }
+ FCPARAM(isp)->isp_maxfrmlen = param;
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "exec_throttle") == 0) {
+ if (param < 16 || param > 255) {
+ retval = EINVAL;
+ break;
+ }
+ FCPARAM(isp)->isp_execthrottle = param;
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "fullduplex") == 0) {
+ if (param != 0 && param != 1) {
+ retval = EINVAL;
+ break;
+ }
+ if (param) {
+ FCPARAM(isp)->isp_fwoptions |=
+ ICBOPT_FULL_DUPLEX;
+ } else {
+ FCPARAM(isp)->isp_fwoptions &=
+ ~ICBOPT_FULL_DUPLEX;
+ }
+ retval = 0;
+ break;
+ }
+ if (strcmp(f->param_name, "loopid") == 0) {
+ if (param < 0 || param > 125) {
+ retval = EINVAL;
+ break;
+ }
+ FCPARAM(isp)->isp_loopid = param;
+ retval = 0;
+ break;
+ }
+ retval = EINVAL;
+ break;
+ }
default:
break;
}
@@ -414,6 +525,8 @@ static cam_status isp_target_start_ctio(struct ispsoftc *, union ccb *);
static int isp_handle_platform_atio(struct ispsoftc *, at_entry_t *);
static int isp_handle_platform_atio2(struct ispsoftc *, at2_entry_t *);
static int isp_handle_platform_ctio(struct ispsoftc *, void *);
+static int isp_handle_platform_notify_scsi(struct ispsoftc *, in_entry_t *);
+static int isp_handle_platform_notify_fc(struct ispsoftc *, in_fcentry_t *);
static __inline int
is_lun_enabled(struct ispsoftc *isp, int bus, lun_id_t lun)
@@ -1019,8 +1132,10 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
atp = isp_get_atpd(isp, cso->tag_id);
if (atp == NULL) {
- panic("cannot find private data adjunct for tag %x",
+ isp_prt(isp, ISP_LOGERR,
+ "cannot find private data adjunct for tag %x",
cso->tag_id);
+ return (-1);
}
cto->ct_rxid = cso->tag_id;
@@ -1031,6 +1146,13 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
cto->rsp.m1.ct_scsi_status = cso->scsi_status;
cto->ct_resid =
atp->orig_datalen - atp->bytes_xfered;
+ if (cto->ct_resid < 0) {
+ cto->rsp.m1.ct_scsi_status |=
+ CT2_DATA_OVER;
+ } else if (cto->ct_resid > 0) {
+ cto->rsp.m1.ct_scsi_status |=
+ CT2_DATA_UNDER;
+ }
}
if ((ccb->ccb_h.flags & CAM_SEND_SENSE) != 0) {
int m = min(cso->sense_len, MAXRESPLEN);
@@ -1045,12 +1167,20 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
} else {
cto->ct_flags |= CT2_DATA_OUT;
}
+ cto->ct_reloff = atp->bytes_xfered;
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
cto->ct_flags |= CT2_SENDSTATUS;
cto->rsp.m0.ct_scsi_status = cso->scsi_status;
cto->ct_resid =
atp->orig_datalen -
(atp->bytes_xfered + cso->dxfer_len);
+ if (cto->ct_resid < 0) {
+ cto->rsp.m0.ct_scsi_status |=
+ CT2_DATA_OVER;
+ } else if (cto->ct_resid > 0) {
+ cto->rsp.m0.ct_scsi_status |=
+ CT2_DATA_UNDER;
+ }
} else {
atp->last_xframt = cso->dxfer_len;
}
@@ -1067,7 +1197,9 @@ isp_target_start_ctio(struct ispsoftc *isp, union ccb *ccb)
cto->ct_rxid, cso->scsi_status, atp->orig_datalen,
cso->dxfer_len, cto->ct_resid);
cto->ct_flags |= CT2_CCINCR;
- }
+ atp->state = ATPD_STATE_LAST_CTIO;
+ } else
+ atp->state = ATPD_STATE_CTIO;
cto->ct_timeout = 10;
hp = &cto->ct_syshandle;
} else {
@@ -1180,6 +1312,7 @@ isp_target_putback_atio(union ccb *ccb)
}
at->at_status = CT_OK;
at->at_rxid = cso->tag_id;
+ at->at_iid = cso->ccb_h.target_id;
isp_put_atio2(isp, at, qe);
} else {
at_entry_t local, *at = &local;
@@ -1208,20 +1341,6 @@ isp_complete_ctio(union ccb *ccb)
ccb->ccb_h.status |= CAM_REQ_CMP;
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
- if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
- isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
- if (isp->isp_osinfo.simqfrozen == 0) {
- if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
- isp_prt(isp, ISP_LOGDEBUG2, "ctio->relsimq");
- ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- } else {
- isp_prt(isp, ISP_LOGWARN, "ctio->devqfrozen");
- }
- } else {
- isp_prt(isp, ISP_LOGWARN,
- "ctio->simqfrozen(%x)", isp->isp_osinfo.simqfrozen);
- }
- }
xpt_done(ccb);
}
@@ -1379,6 +1498,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
}
tptr = get_lun_statep(isp, 0, lun);
if (tptr == NULL) {
+ isp_prt(isp, ISP_LOGWARN, "no state pointer for lun %d", lun);
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
}
@@ -1407,18 +1527,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
* at this time.
*
*/
- u_int32_t ccode = SCSI_STATUS_BUSY;
-
- /*
- * Because we can't autofeed sense data back with
- * a command for parallel SCSI, we can't give back
- * a CHECK CONDITION. We'll give back a BUSY status
- * instead. This works out okay because the only
- * time we should, in fact, get this, is in the
- * case that somebody configured us without the
- * blackhole driver, so they get what they deserve.
- */
- isp_endcmd(isp, aep, ccode, 0);
+ isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
return (0);
}
@@ -1435,19 +1544,22 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
*/
xpt_print_path(tptr->owner);
isp_prt(isp, ISP_LOGWARN,
- "no ATIOS for lun %d from initiator %d", lun, aep->at_iid);
+ "no %s for lun %d from initiator %d",
+ (atp == NULL && atiop == NULL)? "ATIO2s *or* ATPS" :
+ ((atp == NULL)? "ATPs" : "ATIO2s"), lun, aep->at_iid);
rls_lun_statep(isp, tptr);
- if (aep->at_flags & AT_TQAE)
- isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
- else
- isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
+ isp_endcmd(isp, aep, SCSI_STATUS_QUEUE_FULL, 0);
return (0);
}
+ atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
+ tptr->atio_count--;
+ isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO2 lun %d, count now %d",
+ lun, tptr->atio_count);
if (tptr == &isp->isp_osinfo.tsdflt[0]) {
atiop->ccb_h.target_id =
- ((fcparam *)isp->isp_param)->isp_loopid;
+ ((fcparam *)isp->isp_param)->isp_loopid;
atiop->ccb_h.target_lun = lun;
}
/*
@@ -1476,16 +1588,16 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
atiop->tag_action = 0;
break;
}
- if (atiop->tag_action != 0) {
- atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;
- }
+ atiop->ccb_h.flags = CAM_TAG_ACTION_VALID;
atp->tag = atiop->tag_id;
+ atp->lun = lun;
atp->orig_datalen = aep->at_datalen;
atp->last_xframt = 0;
atp->bytes_xfered = 0;
-
+ atp->state = ATPD_STATE_CAM;
xpt_done((union ccb*)atiop);
+
isp_prt(isp, ISP_LOGTDEBUG0,
"ATIO2[%x] CDB=0x%x iid%d->lun%d tattr 0x%x datalen %u",
aep->at_rxid, aep->at_cdb[0] & 0xff, aep->at_iid,
@@ -1511,6 +1623,13 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
if (IS_FC(isp)) {
ct2_entry_t *ct = arg;
+ atio_private_data_t *atp = isp_get_atpd(isp, ct->ct_rxid);
+ if (atp == NULL) {
+ isp_prt(isp, ISP_LOGERR,
+ "cannot find adjunct for %x after I/O",
+ ct->ct_rxid);
+ return (0);
+ }
sentstatus = ct->ct_flags & CT2_SENDSTATUS;
ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK;
if (ok && sentstatus && (ccb->ccb_h.flags & CAM_SEND_SENSE)) {
@@ -1518,24 +1637,22 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
}
notify_cam = ct->ct_header.rqs_seqno & 0x1;
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
- atio_private_data_t *atp =
- isp_get_atpd(isp, ct->ct_rxid);
- if (atp == NULL) {
- panic("cannot find adjunct after I/O");
- }
resid = ct->ct_resid;
atp->bytes_xfered += (atp->last_xframt - resid);
atp->last_xframt = 0;
- if (sentstatus) {
- atp->tag = 0;
- }
}
- isp_prt(isp, ISP_LOGTDEBUG0,
+ if (sentstatus || !ok) {
+ atp->tag = 0;
+ }
+ isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN,
"CTIO2[%x] sts 0x%x flg 0x%x sns %d resid %d %s",
ct->ct_rxid, ct->ct_status, ct->ct_flags,
(ccb->ccb_h.status & CAM_SENT_SENSE) != 0,
resid, sentstatus? "FIN" : "MID");
tval = ct->ct_rxid;
+
+ /* XXX: should really come after isp_complete_ctio */
+ atp->state = ATPD_STATE_PDON;
} else {
ct_entry_t *ct = arg;
sentstatus = ct->ct_flags & CT_SENDSTATUS;
@@ -1596,6 +1713,68 @@ isp_handle_platform_ctio(struct ispsoftc *isp, void *arg)
}
return (0);
}
+
+static int
+isp_handle_platform_notify_scsi(struct ispsoftc *isp, in_entry_t *inp)
+{
+ return (0); /* XXXX */
+}
+
+static int
+isp_handle_platform_notify_fc(struct ispsoftc *isp, in_fcentry_t *inp)
+{
+
+ switch (inp->in_status) {
+ case IN_PORT_LOGOUT:
+ isp_prt(isp, ISP_LOGWARN, "port logout of iid %d",
+ inp->in_iid);
+ break;
+ case IN_PORT_CHANGED:
+ isp_prt(isp, ISP_LOGWARN, "port changed for iid %d",
+ inp->in_iid);
+ break;
+ case IN_GLOBAL_LOGO:
+ isp_prt(isp, ISP_LOGINFO, "all ports logged out");
+ break;
+ case IN_ABORT_TASK:
+ {
+ atio_private_data_t *atp = isp_get_atpd(isp, inp->in_seqid);
+ struct ccb_immed_notify *inot = NULL;
+
+ if (atp) {
+ tstate_t *tptr = get_lun_statep(isp, 0, atp->lun);
+ if (tptr) {
+ inot = (struct ccb_immed_notify *)
+ SLIST_FIRST(&tptr->inots);
+ if (inot) {
+ SLIST_REMOVE_HEAD(&tptr->inots,
+ sim_links.sle);
+ }
+ }
+ isp_prt(isp, ISP_LOGWARN,
+ "abort task RX_ID %x IID %d state %d",
+ inp->in_seqid, inp->in_iid, atp->state);
+ } else {
+ isp_prt(isp, ISP_LOGWARN,
+ "abort task RX_ID %x from iid %d, state unknown",
+ inp->in_seqid, inp->in_iid);
+ }
+ if (inot) {
+ inot->initiator_id = inp->in_iid;
+ inot->sense_len = 0;
+ inot->message_args[0] = MSG_ABORT_TAG;
+ inot->message_args[1] = inp->in_seqid & 0xff;
+ inot->message_args[2] = (inp->in_seqid >> 8) & 0xff;
+ inot->ccb_h.status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
+ xpt_done((union ccb *)inot);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return (0);
+}
#endif
static void
@@ -1653,12 +1832,14 @@ isp_poll(struct cam_sim *sim)
ISP_UNLOCK(isp);
}
+
static void
isp_watchdog(void *arg)
{
XS_T *xs = arg;
struct ispsoftc *isp = XS_ISP(xs);
u_int32_t handle;
+ int iok;
/*
* We've decided this command is dead. Make sure we're not trying
@@ -1666,6 +1847,8 @@ isp_watchdog(void *arg)
* and seeing whether it's still alive.
*/
ISP_LOCK(isp);
+ iok = isp->isp_osinfo.intsok;
+ isp->isp_osinfo.intsok = 0;
handle = isp_find_handle(isp, xs);
if (handle) {
u_int16_t isr, sema, mbox;
@@ -1686,10 +1869,7 @@ isp_watchdog(void *arg)
XS_CMD_S_WDOG(xs);
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
- int iok = isp->isp_osinfo.intsok;
- isp->isp_osinfo.intsok = 0;
isp_intr(isp, isr, sema, mbox);
- isp->isp_osinfo.intsok = iok;
}
if (XS_CMD_DONE_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG2,
@@ -1737,54 +1917,56 @@ isp_watchdog(void *arg)
} else {
isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
}
+ isp->isp_osinfo.intsok = iok;
ISP_UNLOCK(isp);
}
-static int isp_ktmature = 0;
-
static void
isp_kthread(void *arg)
{
struct ispsoftc *isp = arg;
- int wasfrozen, s, iok;
+ int s;
s = splcam();
+ isp->isp_osinfo.intsok = 1;
+
/*
- * We can't really do generic intsok because we can't, in RELENG_4,
- * know whether we're on an interrupt stack or not.
+ * The first loop is for our usage where we have yet to have
+ * gotten good fibre channel state.
*/
for (;;) {
- isp_prt(isp, ISP_LOGDEBUG0, "kthread checking FC state");
- iok = isp->isp_osinfo.intsok;
- isp->isp_osinfo.intsok = 1;
+ int wasfrozen;
+
+ isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
while (isp_fc_runstate(isp, 2 * 1000000) != 0) {
+ isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood");
if (FCPARAM(isp)->isp_fwstate != FW_READY ||
FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) {
if (FCPARAM(isp)->loop_seen_once == 0 ||
- isp_ktmature == 0) {
+ isp->isp_osinfo.ktmature == 0) {
break;
}
}
- isp->isp_osinfo.intsok = iok;
tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz);
- isp->isp_osinfo.intsok = iok;
+
}
+
/*
* Even if we didn't get good loop state we may be
* unfreezing the SIMQ so that we can kill off
- * commands (if we've never seen loop before, e.g.)
+ * commands (if we've never seen loop before, for example).
*/
- isp_ktmature = 1;
- isp->isp_osinfo.intsok = iok;
+ isp->isp_osinfo.ktmature = 1;
wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0, "kthread up release simq");
+ isp_prt(isp, ISP_LOGDEBUG0, "kthread: releasing simq");
ISPLOCK_2_CAMLOCK(isp);
xpt_release_simq(isp->isp_sim, 1);
CAMLOCK_2_ISPLOCK(isp);
}
tsleep(&isp->isp_osinfo.kproc, PRIBIO, "isp_fc_worker", 0);
+ isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called");
}
}
@@ -1862,7 +2044,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
if (ticks >= 0x80000000) {
isp_prt(isp, ISP_LOGERR,
"timeout overflow");
- ticks = 0x80000000;
+ ticks = 0x7fffffff;
}
ccb->ccb_h.timeout_ch = timeout(isp_watchdog,
(caddr_t)ccb, (int)ticks);
@@ -1876,32 +2058,21 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
* This can only happen for Fibre Channel
*/
KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
- if (FCPARAM(isp)->loop_seen_once == 0 && isp_ktmature) {
+ if (FCPARAM(isp)->loop_seen_once == 0 &&
+ isp->isp_osinfo.ktmature) {
ISPLOCK_2_CAMLOCK(isp);
XS_SETERR(ccb, CAM_SEL_TIMEOUT);
xpt_done(ccb);
break;
}
wakeup(&isp->isp_osinfo.kproc);
- if (isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG2,
- "RQLATER freeze simq");
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
- ISPLOCK_2_CAMLOCK(isp);
- xpt_freeze_simq(sim, 1);
- } else {
- ISPLOCK_2_CAMLOCK(isp);
- }
+ isp_freeze_loopdown(isp, "isp_action(RQLATER)");
+ isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
break;
case CMD_EAGAIN:
- if (isp->isp_osinfo.simqfrozen == 0) {
- xpt_freeze_simq(sim, 1);
- isp_prt(isp, ISP_LOGDEBUG2,
- "EAGAIN freeze simq");
- }
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
XS_SETERR(ccb, CAM_REQUEUE_REQ);
ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
@@ -1946,13 +2117,25 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
ccb->ccb_h.sim_priv.entries[0].field = 0;
ccb->ccb_h.sim_priv.entries[1].ptr = isp;
+ ccb->ccb_h.flags = 0;
+
CAMLOCK_2_ISPLOCK(isp);
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
- SLIST_INSERT_HEAD(&tptr->atios,
- &ccb->ccb_h, sim_links.sle);
- } else {
+ /*
+ * Note that the command itself may not be done-
+ * it may not even have had the first CTIO sent.
+ */
+ tptr->atio_count++;
+ isp_prt(isp, ISP_LOGTDEBUG0,
+ "Put FREE ATIO2, lun %d, count now %d",
+ ccb->ccb_h.target_lun, tptr->atio_count);
+ SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
+ sim_links.sle);
+ } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
sim_links.sle);
+ } else {
+ ;
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -1964,13 +2147,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
CAMLOCK_2_ISPLOCK(isp);
ccb->ccb_h.status = isp_target_start_ctio(isp, ccb);
if (ccb->ccb_h.status != CAM_REQ_INPROG) {
- if (isp->isp_osinfo.simqfrozen == 0) {
- xpt_freeze_simq(sim, 1);
- xpt_print_path(ccb->ccb_h.path);
- isp_prt(isp, ISP_LOGINFO,
- "XPT_CONT_TARGET_IO freeze simq");
- }
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_RESOURCE;
+ isp_prt(isp, ISP_LOGWARN,
+ "XPT_CONT_TARGET_IO: status 0x%x",
+ ccb->ccb_h.status);
XS_SETERR(ccb, CAM_REQUEUE_REQ);
ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
@@ -2313,38 +2492,13 @@ isp_done(struct ccb_scsiio *sccb)
if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
sccb->ccb_h.status |= CAM_DEV_QFRZN;
xpt_freeze_devq(sccb->ccb_h.path, 1);
- if (sccb->scsi_status != SCSI_STATUS_OK)
- isp_prt(isp, ISP_LOGDEBUG2,
- "freeze devq %d.%d %x %x",
- sccb->ccb_h.target_id,
- sccb->ccb_h.target_lun, sccb->ccb_h.status,
- sccb->scsi_status);
+ isp_prt(isp, ISP_LOGDEBUG0,
+ "freeze devq %d.%d cam sts %x scsi sts %x",
+ sccb->ccb_h.target_id, sccb->ccb_h.target_lun,
+ sccb->ccb_h.status, sccb->scsi_status);
}
}
- /*
- * If we were frozen waiting resources, clear that we were frozen
- * waiting for resources. If we are no longer frozen, and the devq
- * isn't frozen, mark the completing CCB to have the XPT layer
- * release the simq.
- */
- if (isp->isp_osinfo.simqfrozen & SIMQFRZ_RESOURCE) {
- isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_RESOURCE;
- if (isp->isp_osinfo.simqfrozen == 0) {
- if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
- isp_prt(isp, ISP_LOGDEBUG2,
- "isp_done->relsimq");
- sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
- } else {
- isp_prt(isp, ISP_LOGDEBUG2,
- "isp_done->devq frozen");
- }
- } else {
- isp_prt(isp, ISP_LOGDEBUG2,
- "isp_done -> simqfrozen = %x",
- isp->isp_osinfo.simqfrozen);
- }
- }
if ((CAM_DEBUGGED(sccb->ccb_h.path, ISPDDB)) &&
(sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
xpt_print_path(sccb->ccb_h.path);
@@ -2442,39 +2596,19 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
break;
case ISPASYNC_LIP:
if (isp->isp_path) {
- if (isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0, "LIP freeze simq");
- ISPLOCK_2_CAMLOCK(isp);
- xpt_freeze_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
- }
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ isp_freeze_loopdown(isp, "ISPASYNC_LIP");
}
isp_prt(isp, ISP_LOGINFO, "LIP Received");
break;
case ISPASYNC_LOOP_RESET:
if (isp->isp_path) {
- if (isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0,
- "Loop Reset freeze simq");
- ISPLOCK_2_CAMLOCK(isp);
- xpt_freeze_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
- }
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ isp_freeze_loopdown(isp, "ISPASYNC_LOOP_RESET");
}
isp_prt(isp, ISP_LOGINFO, "Loop Reset Received");
break;
case ISPASYNC_LOOP_DOWN:
if (isp->isp_path) {
- if (isp->isp_osinfo.simqfrozen == 0) {
- isp_prt(isp, ISP_LOGDEBUG0,
- "loop down freeze simq");
- ISPLOCK_2_CAMLOCK(isp);
- xpt_freeze_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
- }
- isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
+ isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN");
}
isp_prt(isp, ISP_LOGINFO, "Loop DOWN");
break;
@@ -2655,6 +2789,15 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
"event 0x%x for unhandled target action",
((isphdr_t *)arg)->rqs_entry_type);
break;
+ case RQSTYPE_NOTIFY:
+ if (IS_SCSI(isp)) {
+ rv = isp_handle_platform_notify_scsi(isp,
+ (in_entry_t *) arg);
+ } else {
+ rv = isp_handle_platform_notify_fc(isp,
+ (in_fcentry_t *) arg);
+ }
+ break;
case RQSTYPE_ATIO:
rv = isp_handle_platform_atio(isp, (at_entry_t *) arg);
break;
@@ -2689,7 +2832,7 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
mbox6 = 0;
}
isp_prt(isp, ISP_LOGERR,
- "Internal Firmware on bus %d Error @ RISC Address 0x%x",
+ "Internal Firmware Error on bus %d @ RISC Address 0x%x",
mbox6, mbox1);
isp_reinit(isp);
break;