diff options
| author | Matt Jacob <mjacob@FreeBSD.org> | 2002-07-29 04:18:09 +0000 |
|---|---|---|
| committer | Matt Jacob <mjacob@FreeBSD.org> | 2002-07-29 04:18:09 +0000 |
| commit | 67198a155e144d0b9b2cbe317d4c757f5a3f9268 (patch) | |
| tree | 6da1a79a0202b2f358777656c95a9a0b2ea138ce /sys/dev/isp | |
| parent | f24de6a5ed9ed1c2286c3f2d549e8b8c33274fea (diff) | |
Notes
Diffstat (limited to 'sys/dev/isp')
| -rw-r--r-- | sys/dev/isp/isp_freebsd.c | 447 |
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; |
