diff options
author | Renato Botelho <renato@netgate.com> | 2015-12-01 08:32:21 -0200 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2015-12-01 08:32:21 -0200 |
commit | 695ea8099809439ed40fe35451df301d75e2b39e (patch) | |
tree | f5d371838e7b09643ac854d4c84c96d401175010 /sys/dev/isp/isp_freebsd.c | |
parent | 2572e1a27934f3539d0356653fcac9aa6b03b80e (diff) | |
parent | ff68307fb48ebed764757b9f0ff301df2f3d8825 (diff) | |
download | FreeBSD-src-695ea8099809439ed40fe35451df301d75e2b39e.zip FreeBSD-src-695ea8099809439ed40fe35451df301d75e2b39e.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 1058 |
1 files changed, 194 insertions, 864 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 6d7033a..73741eb 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -50,13 +50,13 @@ __FBSDID("$FreeBSD$"); MODULE_VERSION(isp, 1); MODULE_DEPEND(isp, cam, 1, 1, 1); int isp_announced = 0; -int isp_fabric_hysteresis = 5; int isp_loop_down_limit = 60; /* default loop down limit */ int isp_quickboot_time = 7; /* don't wait more than N secs for loop up */ int isp_gone_device_time = 30; /* grace time before reporting device lost */ static const char prom3[] = "Chan %d [%u] PortID 0x%06x Departed because of %s"; -static void isp_freeze_loopdown(ispsoftc_t *, int, char *); +static void isp_freeze_loopdown(ispsoftc_t *, int); +static void isp_loop_changed(ispsoftc_t *isp, int chan); static d_ioctl_t ispioctl; static void isp_intr_enable(void *); static void isp_cam_async(void *, uint32_t, struct cam_path *, void *); @@ -64,8 +64,6 @@ static void isp_poll(struct cam_sim *); static timeout_t isp_watchdog; static timeout_t isp_gdt; static task_fn_t isp_gdt_task; -static timeout_t isp_ldt; -static task_fn_t isp_ldt_task; static void isp_kthread(void *); static void isp_action(struct cam_sim *, union ccb *); static int isp_timer_count; @@ -168,25 +166,13 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan) fc->isp = isp; fc->ready = 1; - callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0); callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0); - TASK_INIT(&fc->ltask, 1, isp_ldt_task, fc); TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc); - - /* - * We start by being "loop down" if we have an initiator role - */ - if (fcp->role & ISP_ROLE_INITIATOR) { - isp_freeze_loopdown(isp, chan, "isp_attach"); - callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc); - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_uptime); - } + isp_loop_changed(isp, chan); ISP_UNLOCK(isp); if (THREAD_CREATE(isp_kthread, fc, &fc->kproc, 0, 0, "%s: fc_thrd%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) { xpt_free_path(fc->path); ISP_LOCK(isp); - if (callout_active(&fc->ldt)) - callout_stop(&fc->ldt); xpt_bus_deregister(cam_sim_path(fc->sim)); ISP_UNLOCK(isp); cam_sim_free(fc->sim, FALSE); @@ -377,13 +363,13 @@ isp_detach(ispsoftc_t *isp) } static void -isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg) +isp_freeze_loopdown(ispsoftc_t *isp, int chan) { if (IS_FC(isp)) { struct isp_fc *fc = ISP_FC_PC(isp, chan); if (fc->simqfrozen == 0) { isp_prt(isp, ISP_LOGDEBUG0, - "Chan %d %s -- freeze simq (loopdown)", chan, msg); + "Chan %d Freeze simq (loopdown)", chan); fc->simqfrozen = SIMQFRZ_LOOPDOWN; #if __FreeBSD_version >= 1000039 xpt_hold_boot(); @@ -391,7 +377,7 @@ isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg) xpt_freeze_simq(fc->sim, 1); } else { isp_prt(isp, ISP_LOGDEBUG0, - "Chan %d %s -- mark frozen (loopdown)", chan, msg); + "Chan %d Mark simq frozen (loopdown)", chan); fc->simqfrozen |= SIMQFRZ_LOOPDOWN; } } @@ -405,7 +391,8 @@ isp_unfreeze_loopdown(ispsoftc_t *isp, int chan) int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN; fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN; if (wasfrozen && fc->simqfrozen == 0) { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan); + isp_prt(isp, ISP_LOGDEBUG0, + "Chan %d Release simq", chan); xpt_release_simq(fc->sim, 1); #if __FreeBSD_version >= 1000039 xpt_release_boot(); @@ -441,11 +428,13 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) if (IS_FC(isp)) { *(int *)addr = FCPARAM(isp, chan)->role; } else { - *(int *)addr = SDPARAM(isp, chan)->role; + *(int *)addr = ISP_ROLE_INITIATOR; } retval = 0; break; case ISP_SETROLE: + if (IS_SCSI(isp)) + break; nr = *(int *)addr; chan = nr >> 8; if (chan < 0 || chan >= isp->isp_nchan) { @@ -458,10 +447,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) break; } ISP_LOCK(isp); - if (IS_FC(isp)) - *(int *)addr = FCPARAM(isp, chan)->role; - else - *(int *)addr = SDPARAM(isp, chan)->role; + *(int *)addr = FCPARAM(isp, chan)->role; retval = isp_control(isp, ISPCTL_CHANGE_ROLE, chan, nr); ISP_UNLOCK(isp); retval = 0; @@ -482,7 +468,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) break; } ISP_LOCK(isp); - if (isp_fc_runstate(isp, chan, 5 * 1000000)) { + if (isp_fc_runstate(isp, chan, 5 * 1000000) != LOOP_READY) { retval = EIO; } else { retval = 0; @@ -604,7 +590,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) { int needmarker; struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr; - uint16_t loopid; + uint16_t nphdl; mbreg_t mbs; if (IS_SCSI(isp)) { @@ -618,7 +604,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) } needmarker = retval = 0; - loopid = fct->loopid; + nphdl = fct->loopid; ISP_LOCK(isp); if (IS_24XX(isp)) { uint8_t local[QENTRY_LEN]; @@ -630,7 +616,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) for (i = 0; i < MAX_FC_TARG; i++) { lp = &fcp->portdb[i]; - if (lp->handle == loopid) { + if (lp->handle == nphdl) { break; } } @@ -714,34 +700,34 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td) } else { MBSINIT(&mbs, 0, MBLOGALL, 0); if (ISP_CAP_2KLOGIN(isp) == 0) { - loopid <<= 8; + nphdl <<= 8; } switch (fct->action) { case IPT_CLEAR_ACA: mbs.param[0] = MBOX_CLEAR_ACA; - mbs.param[1] = loopid; + mbs.param[1] = nphdl; mbs.param[2] = fct->lun; break; case IPT_TARGET_RESET: mbs.param[0] = MBOX_TARGET_RESET; - mbs.param[1] = loopid; + mbs.param[1] = nphdl; needmarker = 1; break; case IPT_LUN_RESET: mbs.param[0] = MBOX_LUN_RESET; - mbs.param[1] = loopid; + mbs.param[1] = nphdl; mbs.param[2] = fct->lun; needmarker = 1; break; case IPT_CLEAR_TASK_SET: mbs.param[0] = MBOX_CLEAR_TASK_SET; - mbs.param[1] = loopid; + mbs.param[1] = nphdl; mbs.param[2] = fct->lun; needmarker = 1; break; case IPT_ABORT_TASK_SET: mbs.param[0] = MBOX_ABORT_TASK_SET; - mbs.param[1] = loopid; + mbs.param[1] = nphdl; mbs.param[2] = fct->lun; needmarker = 1; break; @@ -774,18 +760,15 @@ isp_intr_enable(void *arg) int chan; ispsoftc_t *isp = arg; ISP_LOCK(isp); - for (chan = 0; chan < isp->isp_nchan; chan++) { - if (IS_FC(isp)) { + if (IS_FC(isp)) { + for (chan = 0; chan < isp->isp_nchan; chan++) { if (FCPARAM(isp, chan)->role != ISP_ROLE_NONE) { ISP_ENABLE_INTS(isp); break; } - } else { - if (SDPARAM(isp, chan)->role != ISP_ROLE_NONE) { - ISP_ENABLE_INTS(isp); - break; - } } + } else { + ISP_ENABLE_INTS(isp); } isp->isp_osinfo.ehook_active = 0; ISP_UNLOCK(isp); @@ -831,9 +814,6 @@ isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb) * Put the target mode functions here, because some are inlines */ #ifdef ISP_TARGET_MODE -static ISP_INLINE void isp_tmlock(ispsoftc_t *, const char *); -static ISP_INLINE void isp_tmunlk(ispsoftc_t *); -static ISP_INLINE int is_any_lun_enabled(ispsoftc_t *, int); static ISP_INLINE int is_lun_enabled(ispsoftc_t *, int, lun_id_t); static ISP_INLINE tstate_t *get_lun_statep(ispsoftc_t *, int, lun_id_t); static ISP_INLINE tstate_t *get_lun_statep_from_tag(ispsoftc_t *, int, uint32_t); @@ -848,23 +828,16 @@ static ISP_INLINE void isp_put_ntpd(ispsoftc_t *, tstate_t *, inot_private_data_ static cam_status create_lun_state(ispsoftc_t *, int, struct cam_path *, tstate_t **); static void destroy_lun_state(ispsoftc_t *, tstate_t *); static void isp_enable_lun(ispsoftc_t *, union ccb *); -static cam_status isp_enable_deferred_luns(ispsoftc_t *, int); -static cam_status isp_enable_deferred(ispsoftc_t *, int, lun_id_t); static void isp_disable_lun(ispsoftc_t *, union ccb *); -static int isp_enable_target_mode(ispsoftc_t *, int); -static int isp_disable_target_mode(ispsoftc_t *, int); -static void isp_ledone(ispsoftc_t *, lun_entry_t *); static timeout_t isp_refire_putback_atio; static timeout_t isp_refire_notify_ack; static void isp_complete_ctio(union ccb *); static void isp_target_putback_atio(union ccb *); enum Start_Ctio_How { FROM_CAM, FROM_TIMER, FROM_SRR, FROM_CTIO_DONE }; static void isp_target_start_ctio(ispsoftc_t *, union ccb *, enum Start_Ctio_How); -static void isp_handle_platform_atio(ispsoftc_t *, at_entry_t *); static void isp_handle_platform_atio2(ispsoftc_t *, at2_entry_t *); static void isp_handle_platform_atio7(ispsoftc_t *, at7_entry_t *); static void isp_handle_platform_ctio(ispsoftc_t *, void *); -static void isp_handle_platform_notify_scsi(ispsoftc_t *, in_entry_t *); static void isp_handle_platform_notify_fc(ispsoftc_t *, in_fcentry_t *); static void isp_handle_platform_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *); static int isp_handle_platform_target_notify_ack(ispsoftc_t *, isp_notify_t *); @@ -872,40 +845,6 @@ static void isp_handle_platform_target_tmf(ispsoftc_t *, isp_notify_t *); static void isp_target_mark_aborted(ispsoftc_t *, union ccb *); static void isp_target_mark_aborted_early(ispsoftc_t *, tstate_t *, uint32_t); -static ISP_INLINE void -isp_tmlock(ispsoftc_t *isp, const char *msg) -{ - while (isp->isp_osinfo.tmbusy) { - isp->isp_osinfo.tmwanted = 1; - mtx_sleep(isp, &isp->isp_lock, PRIBIO, msg, 0); - } - isp->isp_osinfo.tmbusy = 1; -} - -static ISP_INLINE void -isp_tmunlk(ispsoftc_t *isp) -{ - isp->isp_osinfo.tmbusy = 0; - if (isp->isp_osinfo.tmwanted) { - isp->isp_osinfo.tmwanted = 0; - wakeup(isp); - } -} - -static ISP_INLINE int -is_any_lun_enabled(ispsoftc_t *isp, int bus) -{ - struct tslist *lhp; - int i; - - for (i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - if (SLIST_FIRST(lhp)) - return (1); - } - return (0); -} - static ISP_INLINE int is_lun_enabled(ispsoftc_t *isp, int bus, lun_id_t lun) { @@ -1107,7 +1046,7 @@ isp_dump_atpd(ispsoftc_t *isp, tstate_t *tptr) const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" }; for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) { - xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n", + xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %x nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n", atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]); } } @@ -1222,232 +1161,59 @@ destroy_lun_state(ispsoftc_t *isp, tstate_t *tptr) free(tptr, M_DEVBUF); } -/* - * Enable a lun. - */ static void isp_enable_lun(ispsoftc_t *isp, union ccb *ccb) { - tstate_t *tptr = NULL; - int bus, tm_enabled, target_role; + tstate_t *tptr; + int bus; target_id_t target; lun_id_t lun; + if (!IS_FC(isp) || !ISP_CAP_TMODE(isp) || !ISP_CAP_SCCFW(isp)) { + xpt_print(ccb->ccb_h.path, "Target mode is not supported\n"); + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + return; + } /* - * We only support either a wildcard target/lun or a target ID of zero and a non-wildcard lun + * We only support either target and lun both wildcard + * or target and lun both non-wildcard. */ bus = XS_CHANNEL(ccb); target = ccb->ccb_h.target_id; lun = ccb->ccb_h.target_lun; ISP_PATH_PRT(isp, ISP_LOGTDEBUG0|ISP_LOGCONFIG, ccb->ccb_h.path, "enabling lun %jx\n", (uintmax_t)lun); - if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) { - ccb->ccb_h.status = CAM_LUN_INVALID; - xpt_done(ccb); - return; - } - - if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) { + if ((target == CAM_TARGET_WILDCARD) != (lun == CAM_LUN_WILDCARD)) { ccb->ccb_h.status = CAM_LUN_INVALID; xpt_done(ccb); return; } - if (isp->isp_dblev & ISP_LOGTDEBUG0) { - xpt_print(ccb->ccb_h.path, - "enabling lun 0x%jx on channel %d\n", (uintmax_t)lun, bus); - } - - /* - * Wait until we're not busy with the lun enables subsystem - */ - isp_tmlock(isp, "isp_enable_lun"); - - /* - * This is as a good a place as any to check f/w capabilities. - */ - - if (IS_FC(isp)) { - if (ISP_CAP_TMODE(isp) == 0) { - xpt_print(ccb->ccb_h.path, "firmware does not support target mode\n"); - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - goto done; - } - /* - * We *could* handle non-SCCLUN f/w, but we'd have to - * dork with our already fragile enable/disable code. - */ - if (ISP_CAP_SCCFW(isp) == 0) { - xpt_print(ccb->ccb_h.path, "firmware not SCCLUN capable\n"); - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - goto done; - } - - target_role = (FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0; - } else { - target_role = (SDPARAM(isp, bus)->role & ISP_ROLE_TARGET) != 0; - } - - /* - * Create the state pointer. - * It should not already exist. - */ + /* Create the state pointer. It should not already exist. */ tptr = get_lun_statep(isp, bus, lun); if (tptr) { ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; - goto done; + xpt_done(ccb); + return; } ccb->ccb_h.status = create_lun_state(isp, bus, ccb->ccb_h.path, &tptr); if (ccb->ccb_h.status != CAM_REQ_CMP) { - goto done; - } - - /* - * We have a tricky maneuver to perform here. - * - * If target mode isn't already enabled here, - * *and* our current role includes target mode, - * we enable target mode here. - * - */ - ISP_GET_PC(isp, bus, tm_enabled, tm_enabled); - if (tm_enabled == 0 && target_role != 0) { - if (isp_enable_target_mode(isp, bus)) { - ccb->ccb_h.status = CAM_REQ_CMP_ERR; - destroy_lun_state(isp, tptr); - tptr = NULL; - goto done; - } - tm_enabled = 1; - } - - /* - * Now check to see whether this bus is in target mode already. - * - * If not, a later role change into target mode will finish the job. - */ - if (tm_enabled == 0) { - ISP_SET_PC(isp, bus, tm_enable_defer, 1); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_print(ccb->ccb_h.path, "Target Mode not enabled yet- lun enable deferred\n"); - goto done1; - } - - /* - * Enable the lun. - */ - ccb->ccb_h.status = isp_enable_deferred(isp, bus, lun); - -done: - if (ccb->ccb_h.status != CAM_REQ_CMP) { - if (tptr) { - destroy_lun_state(isp, tptr); - tptr = NULL; - } - } else { - tptr->enabled = 1; - } -done1: - if (tptr) { - rls_lun_statep(isp, tptr); + xpt_done(ccb); + return; } - /* - * And we're outta here.... - */ - isp_tmunlk(isp); + rls_lun_statep(isp, tptr); + ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } -static cam_status -isp_enable_deferred_luns(ispsoftc_t *isp, int bus) -{ - tstate_t *tptr = NULL; - struct tslist *lhp; - int i, n; - - - ISP_GET_PC(isp, bus, tm_enabled, i); - if (i == 1) { - return (CAM_REQ_CMP); - } - ISP_GET_PC(isp, bus, tm_enable_defer, i); - if (i == 0) { - return (CAM_REQ_CMP); - } - /* - * If this succeeds, it will set tm_enable - */ - if (isp_enable_target_mode(isp, bus)) { - return (CAM_REQ_CMP_ERR); - } - isp_tmlock(isp, "isp_enable_deferred_luns"); - for (n = i = 0; i < LUN_HASH_SIZE; i++) { - ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp); - SLIST_FOREACH(tptr, lhp, next) { - tptr->hold++; - if (tptr->enabled == 0) { - if (isp_enable_deferred(isp, bus, tptr->ts_lun) == CAM_REQ_CMP) { - tptr->enabled = 1; - n++; - } - } else { - n++; - } - tptr->hold--; - } - } - isp_tmunlk(isp); - if (n == 0) { - return (CAM_REQ_CMP_ERR); - } - ISP_SET_PC(isp, bus, tm_enable_defer, 0); - return (CAM_REQ_CMP); -} - -static cam_status -isp_enable_deferred(ispsoftc_t *isp, int bus, lun_id_t lun) -{ - cam_status status; - int luns_already_enabled; - - ISP_GET_PC(isp, bus, tm_luns_enabled, luns_already_enabled); - isp_prt(isp, ISP_LOGTINFO, "%s: bus %d lun %u luns_enabled %d", __func__, bus, lun, luns_already_enabled); - if (IS_24XX(isp) || (IS_FC(isp) && luns_already_enabled)) { - status = CAM_REQ_CMP; - } else { - int cmd_cnt, not_cnt; - - if (IS_23XX(isp)) { - cmd_cnt = DFLT_CMND_CNT; - not_cnt = DFLT_INOT_CNT; - } else { - cmd_cnt = 64; - not_cnt = 8; - } - status = CAM_REQ_INPROG; - isp->isp_osinfo.rptr = &status; - if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun == CAM_LUN_WILDCARD? 0 : lun, cmd_cnt, not_cnt)) { - status = CAM_RESRC_UNAVAIL; - } else { - mtx_sleep(&status, &isp->isp_lock, PRIBIO, "isp_enable_deferred", 0); - } - isp->isp_osinfo.rptr = NULL; - } - if (status == CAM_REQ_CMP) { - ISP_SET_PC(isp, bus, tm_luns_enabled, 1); - isp_prt(isp, ISP_LOGCONFIG|ISP_LOGTINFO, "bus %d lun %u now enabled for target mode", bus, lun); - } - return (status); -} - static void isp_disable_lun(ispsoftc_t *isp, union ccb *ccb) { tstate_t *tptr = NULL; int bus; - cam_status status; target_id_t target; lun_id_t lun; @@ -1456,143 +1222,24 @@ isp_disable_lun(ispsoftc_t *isp, union ccb *ccb) lun = ccb->ccb_h.target_lun; ISP_PATH_PRT(isp, ISP_LOGTDEBUG0|ISP_LOGCONFIG, ccb->ccb_h.path, "disabling lun %jx\n", (uintmax_t)lun); - if (target == CAM_TARGET_WILDCARD && lun != CAM_LUN_WILDCARD) { + if ((target == CAM_TARGET_WILDCARD) != (lun == CAM_LUN_WILDCARD)) { ccb->ccb_h.status = CAM_LUN_INVALID; xpt_done(ccb); return; } - if (target != CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) { - ccb->ccb_h.status = CAM_LUN_INVALID; + /* Find the state pointer. */ + if ((tptr = get_lun_statep(isp, bus, lun)) == NULL) { + ccb->ccb_h.status = CAM_PATH_INVALID; xpt_done(ccb); return; } - /* - * See if we're busy disabling a lun now. - */ - isp_tmlock(isp, "isp_disable_lun"); - status = CAM_REQ_INPROG; - - /* - * Find the state pointer. - */ - if ((tptr = get_lun_statep(isp, bus, lun)) == NULL) { - status = CAM_PATH_INVALID; - goto done; - } - - /* - * If we're a 24XX card, we're done. - */ - if (IS_24XX(isp)) { - status = CAM_REQ_CMP; - goto done; - } - - /* - * For SCC FW, we only deal with lun zero. - */ - if (IS_FC(isp) && lun > 0) { - status = CAM_REQ_CMP; - goto done; - } - isp->isp_osinfo.rptr = &status; - if (isp_lun_cmd(isp, RQSTYPE_ENABLE_LUN, bus, lun, 0, 0)) { - status = CAM_RESRC_UNAVAIL; - } else { - mtx_sleep(ccb, &isp->isp_lock, PRIBIO, "isp_disable_lun", 0); - } - isp->isp_osinfo.rptr = NULL; -done: - if (status == CAM_REQ_CMP) { - tptr->enabled = 0; - if (is_any_lun_enabled(isp, bus) == 0) { - if (isp_disable_target_mode(isp, bus)) { - status = CAM_REQ_CMP_ERR; - } - } - } - ccb->ccb_h.status = status; - if (status == CAM_REQ_CMP) { - destroy_lun_state(isp, tptr); - xpt_print(ccb->ccb_h.path, "lun now disabled for target mode\n"); - } else { - if (tptr) - rls_lun_statep(isp, tptr); - } - isp_tmunlk(isp); + destroy_lun_state(isp, tptr); + ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); } -static int -isp_enable_target_mode(ispsoftc_t *isp, int bus) -{ - int tm_enabled; - - ISP_GET_PC(isp, bus, tm_enabled, tm_enabled); - if (tm_enabled != 0) { - return (0); - } - if (IS_SCSI(isp)) { - mbreg_t mbs; - MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0); - mbs.param[0] = MBOX_ENABLE_TARGET_MODE; - mbs.param[1] = ENABLE_TARGET_FLAG|ENABLE_TQING_FLAG; - mbs.param[2] = bus << 7; - if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "Unable to enable Target Role on Bus %d", bus); - return (EIO); - } - } - ISP_SET_PC(isp, bus, tm_enabled, 1); - isp_prt(isp, ISP_LOGINFO, "Target Role enabled on Bus %d", bus); - return (0); -} - -static int -isp_disable_target_mode(ispsoftc_t *isp, int bus) -{ - int tm_enabled; - - ISP_GET_PC(isp, bus, tm_enabled, tm_enabled); - if (tm_enabled == 0) { - return (0); - } - if (IS_SCSI(isp)) { - mbreg_t mbs; - MBSINIT(&mbs, MBOX_ENABLE_TARGET_MODE, MBLOGALL, 0); - mbs.param[2] = bus << 7; - if (isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs) < 0 || mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "Unable to disable Target Role on Bus %d", bus); - return (EIO); - } - } - ISP_SET_PC(isp, bus, tm_enabled, 0); - isp_prt(isp, ISP_LOGINFO, "Target Role disabled on Bus %d", bus); - return (0); -} - -static void -isp_ledone(ispsoftc_t *isp, lun_entry_t *lep) -{ - uint32_t *rptr; - - rptr = isp->isp_osinfo.rptr; - if (lep->le_status != LUN_OK) { - isp_prt(isp, ISP_LOGERR, "ENABLE/MODIFY LUN returned 0x%x", lep->le_status); - if (rptr) { - *rptr = CAM_REQ_CMP_ERR; - wakeup_one(rptr); - } - } else { - if (rptr) { - *rptr = CAM_REQ_CMP; - wakeup_one(rptr); - } - } -} - static void isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) { @@ -1890,7 +1537,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO7[0x%x] seq %u nc %d CDB0=%x sstatus=0x%x flags=0x%x xfrlen=%u off=%u", __func__, cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cto->ct_scsi_status, cto->ct_flags, xfrlen, atp->bytes_xfered); } - } else if (IS_FC(isp)) { + } else { ct2_entry_t *cto = (ct2_entry_t *) local; if (isp->isp_osinfo.sixtyfourbit) @@ -2039,41 +1686,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) } isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO2[%x] seq %u nc %d CDB0=%x scsi status %x flags %x resid %d xfrlen %u offset %u", __func__, cto->ct_rxid, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), atp->cdb0, cso->scsi_status, cto->ct_flags, cto->ct_resid, cso->dxfer_len, atp->bytes_xfered); - } else { - ct_entry_t *cto = (ct_entry_t *) local; - - cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; - cto->ct_header.rqs_entry_count = 1; - cto->ct_header.rqs_seqno |= ATPD_SEQ_NOTIFY_CAM; - ATPD_SET_SEQNO(cto, atp); - cto->ct_iid = cso->init_id; - cto->ct_iid |= XS_CHANNEL(ccb) << 7; - cto->ct_tgt = ccb->ccb_h.target_id; - cto->ct_lun = ccb->ccb_h.target_lun; - cto->ct_fwhandle = cso->tag_id; - if (atp->rxid) { - cto->ct_tag_val = atp->rxid; - cto->ct_flags |= CT_TQAE; - } - if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { - cto->ct_flags |= CT_NODISC; - } - if (cso->dxfer_len == 0) { - cto->ct_flags |= CT_NO_DATA; - } else if ((cso->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - cto->ct_flags |= CT_DATA_IN; - } else { - cto->ct_flags |= CT_DATA_OUT; - } - if (ccb->ccb_h.flags & CAM_SEND_STATUS) { - cto->ct_flags |= CT_SENDSTATUS|CT_CCINCR; - cto->ct_scsi_status = cso->scsi_status; - cto->ct_resid = atp->orig_datalen - atp->bytes_xfered - atp->bytes_in_transit - xfrlen; - isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] seq %u nc %d scsi status %x resid %d tag_id %x", __func__, - cto->ct_fwhandle, ATPD_GET_SEQNO(cto), ATPD_GET_NCAM(cto), cso->scsi_status, cso->resid, cso->tag_id); - } - ccb->ccb_h.flags &= ~CAM_SEND_SENSE; - cto->ct_timeout = 10; } if (isp_get_pcmd(isp, ccb)) { @@ -2103,11 +1715,8 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) if (IS_24XX(isp)) { ct7_entry_t *cto = (ct7_entry_t *) local; cto->ct_syshandle = handle; - } else if (IS_FC(isp)) { - ct2_entry_t *cto = (ct2_entry_t *) local; - cto->ct_syshandle = handle; } else { - ct_entry_t *cto = (ct_entry_t *) local; + ct2_entry_t *cto = (ct2_entry_t *) local; cto->ct_syshandle = handle; } @@ -2166,6 +1775,7 @@ isp_target_putback_atio(union ccb *ccb) ispsoftc_t *isp; struct ccb_scsiio *cso; void *qe; + at2_entry_t local, *at = &local; isp = XS_ISP(ccb); @@ -2179,38 +1789,22 @@ isp_target_putback_atio(union ccb *ccb) } memset(qe, 0, QENTRY_LEN); cso = &ccb->csio; - if (IS_FC(isp)) { - at2_entry_t local, *at = &local; - ISP_MEMZERO(at, sizeof (at2_entry_t)); - at->at_header.rqs_entry_type = RQSTYPE_ATIO2; - at->at_header.rqs_entry_count = 1; - if (ISP_CAP_SCCFW(isp)) { - at->at_scclun = (uint16_t) ccb->ccb_h.target_lun; + ISP_MEMZERO(at, sizeof (at2_entry_t)); + at->at_header.rqs_entry_type = RQSTYPE_ATIO2; + at->at_header.rqs_entry_count = 1; + if (ISP_CAP_SCCFW(isp)) { + at->at_scclun = (uint16_t) ccb->ccb_h.target_lun; #if __FreeBSD_version < 1000700 - if (at->at_scclun >= 256) - at->at_scclun |= 0x4000; + if (at->at_scclun >= 256) + at->at_scclun |= 0x4000; #endif - } else { - at->at_lun = (uint8_t) ccb->ccb_h.target_lun; - } - 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; - ISP_MEMZERO(at, sizeof (at_entry_t)); - at->at_header.rqs_entry_type = RQSTYPE_ATIO; - at->at_header.rqs_entry_count = 1; - at->at_iid = cso->init_id; - at->at_iid |= XS_CHANNEL(ccb) << 7; - at->at_tgt = cso->ccb_h.target_id; - at->at_lun = cso->ccb_h.target_lun; - at->at_status = CT_OK; - at->at_tag_val = AT_GET_TAG(cso->tag_id); - at->at_handle = AT_GET_HANDLE(cso->tag_id); - isp_put_atio(isp, at, qe); + at->at_lun = (uint8_t) ccb->ccb_h.target_lun; } + 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); ISP_TDQE(isp, "isp_target_putback_atio", isp->isp_reqidx, qe); ISP_SYNC_REQUEST(isp); isp_complete_ctio(ccb); @@ -2225,134 +1819,10 @@ isp_complete_ctio(union ccb *ccb) } } -/* - * Handle ATIO stuff that the generic code can't. - * This means handling CDBs. - */ - -static void -isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep) -{ - tstate_t *tptr; - int status, bus; - struct ccb_accept_tio *atiop; - atio_private_data_t *atp; - - /* - * The firmware status (except for the QLTM_SVALID bit) - * indicates why this ATIO was sent to us. - * - * If QLTM_SVALID is set, the firmware has recommended Sense Data. - * - * If the DISCONNECTS DISABLED bit is set in the flags field, - * we're still connected on the SCSI bus. - */ - status = aep->at_status; - if ((status & ~QLTM_SVALID) == AT_PHASE_ERROR) { - /* - * Bus Phase Sequence error. We should have sense data - * suggested by the f/w. I'm not sure quite yet what - * to do about this for CAM. - */ - isp_prt(isp, ISP_LOGWARN, "PHASE ERROR"); - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); - return; - } - if ((status & ~QLTM_SVALID) != AT_CDB) { - isp_prt(isp, ISP_LOGWARN, "bad atio (0x%x) leaked to platform", status); - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); - return; - } - - bus = GET_BUS_VAL(aep->at_iid); - tptr = get_lun_statep(isp, bus, aep->at_lun); - if (tptr == NULL) { - tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD); - if (tptr == NULL) { - /* - * 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, SCSI_STATUS_BUSY, 0); - return; - } - } - - atp = isp_get_atpd(isp, tptr, aep->at_handle); - atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios); - if (atiop == NULL || atp == NULL) { - /* - * 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 QUEUE FULL status - * instead. This works out okay because the only time we - * should, in fact, get this, is in the case that we've - * run out of ATIOS. - */ - xpt_print(tptr->owner, "no %s for lun %d from initiator %d\n", (atp == NULL && atiop == NULL)? "ATIOs *or* ATPS" : - ((atp == NULL)? "ATPs" : "ATIOs"), aep->at_lun, aep->at_iid); - isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0); - if (atp) { - isp_put_atpd(isp, tptr, atp); - } - rls_lun_statep(isp, tptr); - return; - } - atp->rxid = aep->at_tag_val; - atp->state = ATPD_STATE_ATIO; - SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); - tptr->atio_count--; - ISP_PATH_PRT(isp, ISP_LOGTDEBUG2, atiop->ccb_h.path, "Take FREE ATIO count now %d\n", tptr->atio_count); - atiop->ccb_h.target_id = aep->at_tgt; - atiop->ccb_h.target_lun = aep->at_lun; - if (aep->at_flags & AT_NODISC) { - atiop->ccb_h.flags |= CAM_DIS_DISCONNECT; - } else { - atiop->ccb_h.flags &= ~CAM_DIS_DISCONNECT; - } - - if (status & QLTM_SVALID) { - size_t amt = ISP_MIN(QLTM_SENSELEN, sizeof (atiop->sense_data)); - atiop->sense_len = amt; - ISP_MEMCPY(&atiop->sense_data, aep->at_sense, amt); - } else { - atiop->sense_len = 0; - } - - atiop->init_id = GET_IID_VAL(aep->at_iid); - atiop->cdb_len = aep->at_cdblen; - ISP_MEMCPY(atiop->cdb_io.cdb_bytes, aep->at_cdb, aep->at_cdblen); - atiop->ccb_h.status = CAM_CDB_RECVD; - /* - * Construct a tag 'id' based upon tag value (which may be 0..255) - * and the handle (which we have to preserve). - */ - atiop->tag_id = atp->tag; - if (aep->at_flags & AT_TQAE) { - atiop->tag_action = aep->at_tag_type; - atiop->ccb_h.status |= CAM_TAG_ACTION_VALID; - } - atp->orig_datalen = 0; - atp->bytes_xfered = 0; - atp->lun = aep->at_lun; - atp->nphdl = aep->at_iid; - atp->portid = PORT_NONE; - atp->oxid = 0; - atp->cdb0 = atiop->cdb_io.cdb_bytes[0]; - atp->tattr = aep->at_tag_type; - atp->state = ATPD_STATE_CAM; - isp_prt(isp, ISP_LOGTDEBUG0, "ATIO[0x%x] CDB=0x%x lun %d", aep->at_tag_val, atp->cdb0, atp->lun); - rls_lun_statep(isp, tptr); -} - static void isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) { + fcparam *fcp; lun_id_t lun; fcportdb_t *lp; tstate_t *tptr; @@ -2373,6 +1843,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) return; } + fcp = FCPARAM(isp, 0); if (ISP_CAP_SCCFW(isp)) { lun = aep->at_scclun; #if __FreeBSD_version < 1000700 @@ -2443,7 +1914,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle); tptr->atio_count--; isp_prt(isp, ISP_LOGTDEBUG2, "Take FREE ATIO count now %d", tptr->atio_count); - atiop->ccb_h.target_id = FCPARAM(isp, 0)->isp_loopid; + atiop->ccb_h.target_id = fcp->isp_loopid; atiop->ccb_h.target_lun = lun; /* @@ -2466,6 +1937,10 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) (((uint64_t) aep->at_wwpn[3]) << 0); isp_add_wwn_entry(isp, 0, wwpn, INI_NONE, nphdl, PORT_ANY, 0); + if (fcp->isp_loopstate > LOOP_LTEST_DONE) + fcp->isp_loopstate = LOOP_LTEST_DONE; + isp_async(isp, ISPASYNC_CHANGE_NOTIFY, 0, + ISPASYNC_CHANGE_PDB, nphdl, 0x06, 0xff); isp_find_pdb_by_handle(isp, 0, nphdl, &lp); } atiop->init_id = FC_PORTDB_TGT(isp, 0, lp); @@ -2588,7 +2063,7 @@ isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep) /* * Find the PDB entry for this initiator */ - if (isp_find_pdb_by_sid(isp, chan, sid, &lp) == 0) { + if (isp_find_pdb_by_portid(isp, chan, sid, &lp) == 0) { /* * If we're not in the port database terminate the exchange. */ @@ -2903,16 +2378,7 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) int bus; uint32_t handle, moved_data = 0, data_requested; - /* - * CTIO handles are 16 bits. - * CTIO2 and CTIO7 are 32 bits. - */ - - if (IS_SCSI(isp)) { - handle = ((ct_entry_t *)arg)->ct_syshandle; - } else { - handle = ((ct2_entry_t *)arg)->ct_syshandle; - } + handle = ((ct2_entry_t *)arg)->ct_syshandle; ccb = isp_find_xs_tgt(isp, handle); if (ccb == NULL) { isp_print_bytes(isp, "null ccb in isp_handle_platform_ctio", QENTRY_LEN, arg); @@ -2937,10 +2403,8 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) if (IS_24XX(isp)) { atp = isp_find_atpd(isp, tptr, ((ct7_entry_t *)arg)->ct_rxid); - } else if (IS_FC(isp)) { - atp = isp_find_atpd(isp, tptr, ((ct2_entry_t *)arg)->ct_rxid); } else { - atp = isp_find_atpd(isp, tptr, ((ct_entry_t *)arg)->ct_fwhandle); + atp = isp_find_atpd(isp, tptr, ((ct2_entry_t *)arg)->ct_rxid); } if (atp == NULL) { /* @@ -2983,7 +2447,7 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) } isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO7[%x] seq %u nc %d sts 0x%x flg 0x%x sns %d resid %d %s", __func__, ct->ct_rxid, ATPD_GET_SEQNO(ct), notify_cam, ct->ct_nphdl, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID"); - } else if (IS_FC(isp)) { + } else { ct2_entry_t *ct = arg; if (ct->ct_status == CT_SRR) { atp->srr_ccb = ccb; @@ -3006,22 +2470,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) } isp_prt(isp, ok? ISP_LOGTDEBUG0 : ISP_LOGWARN, "%s: CTIO2[%x] seq %u nc %d sts 0x%x flg 0x%x sns %d resid %d %s", __func__, ct->ct_rxid, ATPD_GET_SEQNO(ct), notify_cam, ct->ct_status, ct->ct_flags, (ccb->ccb_h.status & CAM_SENT_SENSE) != 0, resid, sentstatus? "FIN" : "MID"); - } else { - ct_entry_t *ct = arg; - - if (ct->ct_status == (CT_HBA_RESET & 0xff)) { - failure = CAM_UNREC_HBA_ERROR; - } else { - sentstatus = ct->ct_flags & CT_SENDSTATUS; - ok = (ct->ct_status & ~QLTM_SVALID) == CT_OK; - notify_cam = (ct->ct_header.rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0; - } - if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { - resid = ct->ct_resid; - moved_data = data_requested - resid; - } - isp_prt(isp, ISP_LOGTDEBUG0, "%s: CTIO[%x] seq %u nc %d tag %x S_ID 0x%x lun %x sts %x flg %x resid %d %s", __func__, ct->ct_fwhandle, ATPD_GET_SEQNO(ct), - notify_cam, ct->ct_tag_val, ct->ct_iid, ct->ct_lun, ct->ct_status, ct->ct_flags, resid, sentstatus? "FIN" : "MID"); } if (ok) { if (moved_data) { @@ -3075,12 +2523,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) } static void -isp_handle_platform_notify_scsi(ispsoftc_t *isp, in_entry_t *inot) -{ - isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot); -} - -static void isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp) { int needack = 1; @@ -3102,8 +2544,8 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp) case IN_ABORT_TASK: { tstate_t *tptr; - uint16_t lun; - uint32_t loopid, sid; + uint16_t nphdl, lun; + uint32_t sid; uint64_t wwn; atio_private_data_t *atp; fcportdb_t *lp; @@ -3118,11 +2560,11 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp) lun = inp->in_lun; } if (ISP_CAP_2KLOGIN(isp)) { - loopid = ((in_fcentry_e_t *)inp)->in_iid; + nphdl = ((in_fcentry_e_t *)inp)->in_iid; } else { - loopid = inp->in_iid; + nphdl = inp->in_iid; } - if (isp_find_pdb_by_handle(isp, 0, loopid, &lp)) { + if (isp_find_pdb_by_handle(isp, 0, nphdl, &lp)) { wwn = lp->port_wwn; sid = lp->portid; } else { @@ -3133,7 +2575,7 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp) if (tptr == NULL) { tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD); if (tptr == NULL) { - isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %u- but no tstate", lun); + isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %x, but no tstate", lun); return; } } @@ -3158,7 +2600,7 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp) nt->nt_hba = isp; nt->nt_tgt = FCPARAM(isp, 0)->isp_wwpn; nt->nt_wwn = wwn; - nt->nt_nphdl = loopid; + nt->nt_nphdl = nphdl; nt->nt_sid = sid; nt->nt_did = PORT_ANY; nt->nt_lun = lun; @@ -3321,7 +2763,7 @@ isp_handle_platform_target_notify_ack(ispsoftc_t *isp, isp_notify_t *mp) uint16_t nphdl; sid = (aep->at_hdr.s_id[0] << 16) | (aep->at_hdr.s_id[1] << 8) | aep->at_hdr.s_id[2]; - if (isp_find_pdb_by_sid(isp, mp->nt_channel, sid, &lp)) { + if (isp_find_pdb_by_portid(isp, mp->nt_channel, sid, &lp)) { nphdl = lp->handle; } else { nphdl = NIL_HANDLE; @@ -3445,7 +2887,7 @@ isp_handle_platform_target_tmf(ispsoftc_t *isp, isp_notify_t *notify) goto bad; } - if (isp_find_pdb_by_sid(isp, notify->nt_channel, notify->nt_sid, &lp) == 0 && + if (isp_find_pdb_by_portid(isp, notify->nt_channel, notify->nt_sid, &lp) == 0 && isp_find_pdb_by_handle(isp, notify->nt_channel, notify->nt_nphdl, &lp) == 0) { inot->initiator_id = CAM_TARGET_WILDCARD; } else { @@ -3611,14 +3053,10 @@ isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg) if (tgt >= 0) { nflags = sdp->isp_devparam[tgt].nvrm_flags; -#ifndef ISP_TARGET_MODE nflags &= DPARM_SAFE_DFLT; if (isp->isp_loaded_fw) { nflags |= DPARM_NARROW | DPARM_ASYNC; } -#else - nflags = DPARM_DEFAULT; -#endif oflags = sdp->isp_devparam[tgt].goal_flags; sdp->isp_devparam[tgt].goal_flags = nflags; sdp->isp_devparam[tgt].dev_update = 1; @@ -3819,41 +3257,59 @@ isp_gdt_task(void *arg, int pending) } /* - * Loop Down Timer Function- when loop goes down, a timer is started and - * and after it expires we come here and take all probational devices that - * the OS knows about and the tell the OS that they've gone away. - * + * When loop goes down we remember the time and freeze CAM command queue. + * During some time period we are trying to reprobe the loop. But if we + * fail, we tell the OS that devices have gone away and drop the freeze. + * * We don't clear the devices out of our port database because, when loop * come back up, we have to do some actual cleanup with the chip at that * point (implicit PLOGO, e.g., to get the chip's port database state right). */ static void -isp_ldt(void *arg) +isp_loop_changed(ispsoftc_t *isp, int chan) { - struct isp_fc *fc = arg; - taskqueue_enqueue(taskqueue_thread, &fc->ltask); + fcparam *fcp = FCPARAM(isp, chan); + struct isp_fc *fc = ISP_FC_PC(isp, chan); + + if (fc->loop_down_time) + return; + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop changed", chan); + if (fcp->role & ISP_ROLE_INITIATOR) + isp_freeze_loopdown(isp, chan); + fc->loop_dead = 0; + fc->loop_down_time = time_uptime; + wakeup(fc); } static void -isp_ldt_task(void *arg, int pending) +isp_loop_up(ispsoftc_t *isp, int chan) { - struct isp_fc *fc = arg; - ispsoftc_t *isp = fc->isp; - int chan = fc - isp->isp_osinfo.pc.fc; + struct isp_fc *fc = ISP_FC_PC(isp, chan); + + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is up", chan); + fc->loop_seen_once = 1; + fc->loop_dead = 0; + fc->loop_down_time = 0; + isp_unfreeze_loopdown(isp, chan); +} + +static void +isp_loop_dead(ispsoftc_t *isp, int chan) +{ + fcparam *fcp = FCPARAM(isp, chan); + struct isp_fc *fc = ISP_FC_PC(isp, chan); fcportdb_t *lp; struct ac_contract ac; struct ac_device_changed *adc; int dbidx, i; - ISP_LOCK(isp); - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime); - callout_deactivate(&fc->ldt); + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is dead", chan); /* * Notify to the OS all targets who we now consider have departed. */ for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) { - lp = &FCPARAM(isp, chan)->portdb[dbidx]; + lp = &fcp->portdb[dbidx]; if (lp->state == FC_PORTDB_STATE_NIL) continue; @@ -3896,14 +3352,8 @@ isp_ldt_task(void *arg, int pending) } isp_unfreeze_loopdown(isp, chan); - /* - * The loop down timer has expired. Wake up the kthread - * to notice that fact (or make it false). - */ fc->loop_dead = 1; - fc->loop_down_time = fc->loop_down_limit+1; - wakeup(fc); - ISP_UNLOCK(isp); + fc->loop_down_time = 0; } static void @@ -3912,15 +3362,18 @@ isp_kthread(void *arg) struct isp_fc *fc = arg; ispsoftc_t *isp = fc->isp; int chan = fc - isp->isp_osinfo.pc.fc; - int slp = 0; + int slp = 0, d; + int lb, lim; mtx_lock(&isp->isp_osinfo.lock); while (isp->isp_osinfo.is_exiting == 0) { - int lb, lim; - - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan); + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, + "Chan %d Checking FC state", chan); lb = isp_fc_runstate(isp, chan, 250000); + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, + "Chan %d FC got to %s state", chan, + isp_fc_loop_statename(lb)); /* * Our action is different based upon whether we're supporting @@ -3930,87 +3383,44 @@ isp_kthread(void *arg) * * If not, we simply just wait for loop to come up. */ - if (lb && (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR)) { - /* - * Increment loop down time by the last sleep interval - */ - fc->loop_down_time += slp; - - if (lb < 0) { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC loop not up (down count %d)", __func__, chan, fc->loop_down_time); - } else { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC got to %d (down count %d)", __func__, chan, lb, fc->loop_down_time); - } - + if (lb == LOOP_READY || lb < 0) { + slp = 0; + } else { /* * If we've never seen loop up and we've waited longer * than quickboot time, or we've seen loop up but we've * waited longer than loop_down_limit, give up and go * to sleep until loop comes up. */ - if (FCPARAM(isp, chan)->loop_seen_once == 0) { + if (fc->loop_seen_once == 0) lim = isp_quickboot_time; - } else { + else lim = fc->loop_down_limit; - } - if (fc->loop_down_time >= lim) { - isp_freeze_loopdown(isp, chan, "loop limit hit"); + d = time_uptime - fc->loop_down_time; + if (d >= lim) slp = 0; - } else if (fc->loop_down_time < 10) { + else if (d < 10) slp = 1; - } else if (fc->loop_down_time < 30) { + else if (d < 30) slp = 5; - } else if (fc->loop_down_time < 60) { + else if (d < 60) slp = 10; - } else if (fc->loop_down_time < 120) { + else if (d < 120) slp = 20; - } else { - slp = 30; - } - - } else if (lb) { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC Loop Down", __func__, chan); - fc->loop_down_time += slp; - if (fc->loop_down_time > 300) - slp = 0; else - slp = 60; - } else { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan); - fc->loop_down_time = 0; - slp = 0; + slp = 30; } - - /* - * If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it - * now so that CAM can start sending us commands. - * - * If the FC state isn't okay yet, they'll hit that in isp_start which will freeze the queue again - * or kill the commands, as appropriate. - */ - - if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) { - isp_unfreeze_loopdown(isp, chan); + if (slp == 0) { + if (lb == LOOP_READY) + isp_loop_up(isp, chan); + else + isp_loop_dead(isp, chan); } - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp); - + isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, + "Chan %d sleep for %d seconds", chan, slp); msleep(fc, &isp->isp_osinfo.lock, PRIBIO, "ispf", slp * hz); - - /* - * If slp is zero, we're waking up for the first time after - * things have been okay. In this case, we set a deferral state - * for all commands and delay hysteresis seconds before starting - * the FC state evaluation. This gives the loop/fabric a chance - * to settle. - */ - if (slp == 0 && fc->hysteresis) { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep hysteresis ticks %d", __func__, chan, fc->hysteresis * hz); - mtx_unlock(&isp->isp_osinfo.lock); - pause("ispt", fc->hysteresis * hz); - mtx_lock(&isp->isp_osinfo.lock); - } } fc->num_threads -= 1; mtx_unlock(&isp->isp_osinfo.lock); @@ -4020,7 +3430,7 @@ isp_kthread(void *arg) static void isp_action(struct cam_sim *sim, union ccb *ccb) { - int bus, tgt, ts, error, lim; + int bus, tgt, ts, error; ispsoftc_t *isp; struct ccb_trans_settings *cts; @@ -4084,26 +3494,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb) break; case CMD_RQLATER: /* - * We get this result for FC devices if the loop state isn't ready yet - * or if the device in question has gone zombie on us. - * - * If we've never seen Loop UP at all, we requeue this request and wait - * for the initial loop up delay to expire. + * We get this result if the loop isn't ready + * or if the device in question has gone zombie. */ - lim = ISP_FC_PC(isp, bus)->loop_down_limit; - if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) { - if (FCPARAM(isp, bus)->loop_seen_once == 0) { - isp_prt(isp, ISP_LOGDEBUG0, - "%d.%jx loop not seen yet @ %lu", - XS_TGT(ccb), (uintmax_t)XS_LUN(ccb), - (unsigned long) time_uptime); - } else { - isp_prt(isp, ISP_LOGDEBUG0, - "%d.%jx downtime (%d) > lim (%d)", - XS_TGT(ccb), (uintmax_t)XS_LUN(ccb), - ISP_FC_PC(isp, bus)->loop_down_time, - lim); - } + if (ISP_FC_PC(isp, bus)->loop_dead) { + isp_prt(isp, ISP_LOGDEBUG0, + "%d.%jx loop is dead", + XS_TGT(ccb), (uintmax_t)XS_LUN(ccb)); ccb->ccb_h.status = CAM_SEL_TIMEOUT; isp_done((struct ccb_scsiio *) ccb); break; @@ -4248,16 +3645,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb) break; #endif case XPT_RESET_DEV: /* BDR the specified SCSI device */ - { - struct isp_fc *fc; - bus = cam_sim_bus(xpt_path_sim(ccb->ccb_h.path)); tgt = ccb->ccb_h.target_id; tgt |= (bus << 16); - if (IS_FC(isp)) - fc = ISP_FC_PC(isp, bus); - else - fc = NULL; error = isp_control(isp, ISPCTL_RESET_DEV, bus, tgt); if (error) { @@ -4268,14 +3658,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb) * Reference Number, because the target will expect * that we re-start the CRN at 1 after a reset. */ - if (fc != NULL) - isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); + if (IS_FC(isp)) + isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); ccb->ccb_h.status = CAM_REQ_CMP; } xpt_done(ccb); break; - } case XPT_ABORT: /* Abort the specified CCB */ { union ccb *accb = ccb->cab.abort_ccb; @@ -4542,25 +3931,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb) } if (rchange) { ISP_PATH_PRT(isp, ISP_LOGCONFIG, ccb->ccb_h.path, "changing role on from %d to %d\n", fcp->role, newrole); -#ifdef ISP_TARGET_MODE - ISP_SET_PC(isp, bus, tm_enabled, 0); - ISP_SET_PC(isp, bus, tm_luns_enabled, 0); -#endif if (isp_control(isp, ISPCTL_CHANGE_ROLE, bus, newrole) != 0) { ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); break; } -#ifdef ISP_TARGET_MODE - if (newrole == ISP_ROLE_TARGET || newrole == ISP_ROLE_BOTH) { - /* - * Give the new role a chance to complain and settle - */ - msleep(isp, &isp->isp_lock, PRIBIO, "taking a breather", 2); - ccb->ccb_h.status = isp_enable_deferred_luns(isp, bus); - } -#endif } } xpt_done(ccb); @@ -4606,10 +3982,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb) cpi->version_num = 1; #ifdef ISP_TARGET_MODE - cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; -#else - cpi->target_sprt = 0; + if (IS_FC(isp) && ISP_CAP_TMODE(isp) && ISP_CAP_SCCFW(isp)) + cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; + else #endif + cpi->target_sprt = 0; cpi->hba_eng_cnt = 0; cpi->max_target = ISP_MAX_TARGETS(isp) - 1; cpi->max_lun = ISP_MAX_LUNS(isp) == 0 ? @@ -4829,49 +4206,20 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) msg = "LOOP Reset"; /* FALLTHROUGH */ case ISPASYNC_LOOP_DOWN: - { if (msg == NULL) msg = "LOOP Down"; va_start(ap, cmd); bus = va_arg(ap, int); va_end(ap); - - FCPARAM(isp, bus)->isp_linkstate = 0; - - fc = ISP_FC_PC(isp, bus); - if (cmd == ISPASYNC_LOOP_DOWN && fc->ready) { - /* - * We don't do any simq freezing if we are only in target mode - */ - if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) { - if (fc->path) { - isp_freeze_loopdown(isp, bus, msg); - } - } - if (!callout_active(&fc->ldt)) { - callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc); - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Starting Loop Down Timer @ %lu", (unsigned long) time_uptime); - } - } - isp_fcp_reset_crn(fc, /*tgt*/0, /*tgt_set*/ 0); - - isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg); + isp_fcp_reset_crn(isp, bus, /*tgt*/0, /*tgt_set*/ 0); + isp_loop_changed(isp, bus); + isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); break; - } case ISPASYNC_LOOP_UP: va_start(ap, cmd); bus = va_arg(ap, int); va_end(ap); - fc = ISP_FC_PC(isp, bus); - /* - * Now we just note that Loop has come up. We don't - * actually do anything because we're waiting for a - * Change Notify before activating the FC cleanup - * thread to look at the state of the loop again. - */ - FCPARAM(isp, bus)->isp_linkstate = 1; - fc->loop_dead = 0; - fc->loop_down_time = 0; + isp_loop_changed(isp, bus); isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus); break; case ISPASYNC_DEV_ARRIVED: @@ -4886,7 +4234,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) if ((FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) && (lp->prli_word3 & PRLI_WD3_TARGET_FUNCTION)) { lp->is_target = 1; - isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); + isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); isp_make_here(isp, lp, bus, tgt); } if ((FCPARAM(isp, bus)->role & ISP_ROLE_TARGET) && @@ -4916,11 +4264,11 @@ changed: (lp->new_prli_word3 & PRLI_WD3_TARGET_FUNCTION))) { lp->is_target = !lp->is_target; if (lp->is_target) { - isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); + isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); isp_make_here(isp, lp, bus, tgt); } else { isp_make_gone(isp, lp, bus, tgt); - isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1); + isp_fcp_reset_crn(isp, bus, tgt, /*tgt_set*/ 1); } } if (lp->is_initiator != @@ -4973,15 +4321,17 @@ changed: case ISPASYNC_CHANGE_NOTIFY: { char *msg; - int evt, nphdl, nlstate, reason; + int evt, nphdl, nlstate, portid, reason; va_start(ap, cmd); bus = va_arg(ap, int); evt = va_arg(ap, int); - if (IS_24XX(isp) && evt == ISPASYNC_CHANGE_PDB) { + if (evt == ISPASYNC_CHANGE_PDB) { nphdl = va_arg(ap, int); nlstate = va_arg(ap, int); reason = va_arg(ap, int); + } else if (evt == ISPASYNC_CHANGE_SNS) { + portid = va_arg(ap, int); } else { nphdl = NIL_HANDLE; nlstate = reason = 0; @@ -4991,24 +4341,18 @@ changed: if (evt == ISPASYNC_CHANGE_PDB) { msg = "Port Database Changed"; + isp_prt(isp, ISP_LOGINFO, + "Chan %d %s (nphdl 0x%x state 0x%x reason 0x%x)", + bus, msg, nphdl, nlstate, reason); } else if (evt == ISPASYNC_CHANGE_SNS) { msg = "Name Server Database Changed"; + isp_prt(isp, ISP_LOGINFO, "Chan %d %s (PortID 0x%06x)", + bus, msg, portid); } else { msg = "Other Change Notify"; + isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); } - - /* - * If the loop down timer is running, cancel it. - */ - if (fc->ready && callout_active(&fc->ldt)) { - isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_uptime); - callout_stop(&fc->ldt); - } - isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg); - if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) { - isp_freeze_loopdown(isp, bus, msg); - } - wakeup(fc); + isp_loop_changed(isp, bus); break; } #ifdef ISP_TARGET_MODE @@ -5092,20 +4436,14 @@ changed: isp_prt(isp, ISP_LOGWARN, "%s: unhandled target action 0x%x", __func__, hp->rqs_entry_type); break; case RQSTYPE_NOTIFY: - if (IS_SCSI(isp)) { - isp_handle_platform_notify_scsi(isp, (in_entry_t *) hp); - } else if (IS_24XX(isp)) { + if (IS_24XX(isp)) { isp_handle_platform_notify_24xx(isp, (in_fcentry_24xx_t *) hp); } else { isp_handle_platform_notify_fc(isp, (in_fcentry_t *) hp); } break; case RQSTYPE_ATIO: - if (IS_24XX(isp)) { - isp_handle_platform_atio7(isp, (at7_entry_t *) hp); - } else { - isp_handle_platform_atio(isp, (at_entry_t *) hp); - } + isp_handle_platform_atio7(isp, (at7_entry_t *) hp); break; case RQSTYPE_ATIO2: isp_handle_platform_atio2(isp, (at2_entry_t *) hp); @@ -5170,10 +4508,6 @@ changed: isp_handle_platform_target_tmf(isp, nt); break; } - case RQSTYPE_ENABLE_LUN: - case RQSTYPE_MODIFY_LUN: - isp_ledone(isp, (lun_entry_t *) hp); - break; } break; } @@ -5489,23 +4823,23 @@ isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl) * (needed for events like a LIP). */ void -isp_fcp_reset_crn(struct isp_fc *fc, uint32_t tgt, int tgt_set) +isp_fcp_reset_crn(ispsoftc_t *isp, int chan, uint32_t tgt, int tgt_set) { - int i; + struct isp_fc *fc = ISP_FC_PC(isp, chan); struct isp_nexus *nxp; + int i; if (tgt_set == 0) - isp_prt(fc->isp, ISP_LOG_SANCFG, "resetting CRN on all targets"); + isp_prt(isp, ISP_LOGDEBUG0, + "Chan %d resetting CRN on all targets", chan); else - isp_prt(fc->isp, ISP_LOG_SANCFG, "resetting CRN target %u", tgt); + isp_prt(isp, ISP_LOGDEBUG0, + "Chan %d resetting CRN on target %u", chan, tgt); for (i = 0; i < NEXUS_HASH_WIDTH; i++) { - nxp = fc->nexus_hash[i]; - while (nxp) { - if ((tgt_set != 0) && (tgt == nxp->tgt)) + for (nxp = fc->nexus_hash[i]; nxp != NULL; nxp = nxp->next) { + if (tgt_set == 0 || tgt == nxp->tgt) nxp->crnseed = 0; - - nxp = nxp->next; } } } @@ -5519,7 +4853,7 @@ isp_fcp_next_crn(ispsoftc_t *isp, uint8_t *crnp, XS_T *cmd) struct isp_nexus *nxp; int idx; - if (isp->isp_type < ISP_HA_FC_2300) + if (IS_2100(isp)) return (0); chan = XS_CHANNEL(cmd); @@ -5549,15 +4883,11 @@ isp_fcp_next_crn(ispsoftc_t *isp, uint8_t *crnp, XS_T *cmd) nxp->next = fc->nexus_hash[idx]; fc->nexus_hash[idx] = nxp; } - if (nxp) { - if (nxp->crnseed == 0) - nxp->crnseed = 1; - if (cmd) - PISP_PCMD(cmd)->crn = nxp->crnseed; - *crnp = nxp->crnseed++; - return (0); - } - return (-1); + if (nxp->crnseed == 0) + nxp->crnseed = 1; + PISP_PCMD(cmd)->crn = nxp->crnseed; + *crnp = nxp->crnseed++; + return (0); } /* |