One more round of port scanner rewrite.
- Make scan aborted by event restart immediately and infinitely. - Improve handling of some loop events from firmware. - Remove loop down timer, adding its functionality to scanner thread. - Some more unification and simplification.
This commit is contained in:
parent
a693a7b851
commit
155e1e1885
@ -2810,6 +2810,8 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
|
|||||||
|
|
||||||
fcp = FCPARAM(isp, chan);
|
fcp = FCPARAM(isp, chan);
|
||||||
|
|
||||||
|
if (fcp->isp_loopstate < LOOP_HAVE_LINK)
|
||||||
|
return (-1);
|
||||||
if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
|
if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
@ -2825,15 +2827,13 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
|
|||||||
if (fcp->isp_fwstate == FW_READY) {
|
if (fcp->isp_fwstate == FW_READY) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (fcp->isp_loopstate < LOOP_TESTING_LINK)
|
||||||
|
goto abort;
|
||||||
GET_NANOTIME(&hrb);
|
GET_NANOTIME(&hrb);
|
||||||
if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
|
if ((NANOTIME_SUB(&hrb, &hra) / 1000 + 1000 >= usdelay))
|
||||||
break;
|
break;
|
||||||
ISP_SLEEP(isp, 1000);
|
ISP_SLEEP(isp, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If we haven't gone to 'ready' state, return.
|
|
||||||
*/
|
|
||||||
if (fcp->isp_fwstate != FW_READY) {
|
if (fcp->isp_fwstate != FW_READY) {
|
||||||
isp_prt(isp, ISP_LOG_SANCFG,
|
isp_prt(isp, ISP_LOG_SANCFG,
|
||||||
"Chan %d Firmware is not ready (%s)",
|
"Chan %d Firmware is not ready (%s)",
|
||||||
@ -2938,6 +2938,12 @@ not_on_fabric:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fcp->isp_loopstate < LOOP_TESTING_LINK) {
|
||||||
|
abort:
|
||||||
|
isp_prt(isp, ISP_LOG_SANCFG,
|
||||||
|
"Chan %d FC link test aborted", chan);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
||||||
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
|
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG,
|
||||||
"Chan %d WWPN %016jx WWNN %016jx",
|
"Chan %d WWPN %016jx WWNN %016jx",
|
||||||
@ -2968,12 +2974,10 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
|
|||||||
fcportdb_t *lp;
|
fcportdb_t *lp;
|
||||||
uint16_t dbidx;
|
uint16_t dbidx;
|
||||||
|
|
||||||
if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
|
if (fcp->isp_loopstate < LOOP_FSCAN_DONE)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
if (fcp->isp_loopstate >= LOOP_READY)
|
||||||
if (fcp->isp_loopstate > LOOP_SYNCING_PDB) {
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
|
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
|
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
|
||||||
|
|
||||||
@ -3025,12 +3029,12 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (fcp->isp_loopstate < LOOP_SYNCING_PDB) {
|
||||||
* If we get here, we've for sure seen not only a valid loop
|
isp_prt(isp, ISP_LOG_SANCFG,
|
||||||
* but know what is or isn't on it, so mark this for usage
|
"Chan %d FC PDB sync aborted", chan);
|
||||||
* in isp_start.
|
return (1);
|
||||||
*/
|
}
|
||||||
fcp->loop_seen_once = 1;
|
|
||||||
fcp->isp_loopstate = LOOP_READY;
|
fcp->isp_loopstate = LOOP_READY;
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
|
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
|
||||||
return (0);
|
return (0);
|
||||||
@ -3154,12 +3158,11 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
|
|||||||
uint16_t handles[LOCAL_LOOP_LIM];
|
uint16_t handles[LOCAL_LOOP_LIM];
|
||||||
uint16_t handle;
|
uint16_t handle;
|
||||||
|
|
||||||
if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
|
if (fcp->isp_loopstate < LOOP_LTEST_DONE)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
if (fcp->isp_loopstate >= LOOP_LSCAN_DONE)
|
||||||
if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
|
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
|
||||||
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
|
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
|
||||||
if (TOPO_IS_FABRIC(fcp->isp_topo)) {
|
if (TOPO_IS_FABRIC(fcp->isp_topo)) {
|
||||||
@ -3214,8 +3217,8 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
|
|||||||
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
|
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
|
||||||
abort:
|
abort:
|
||||||
isp_prt(isp, ISP_LOG_SANCFG,
|
isp_prt(isp, ISP_LOG_SANCFG,
|
||||||
"Chan %d FC loop scan done (abort)", chan);
|
"Chan %d FC loop scan aborted", chan);
|
||||||
return (-1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (node_wwn == INI_NONE) {
|
if (node_wwn == INI_NONE) {
|
||||||
continue;
|
continue;
|
||||||
@ -3424,12 +3427,11 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
|
|||||||
int portidx, portlim, r;
|
int portidx, portlim, r;
|
||||||
sns_gid_ft_rsp_t *rs0, *rs1;
|
sns_gid_ft_rsp_t *rs0, *rs1;
|
||||||
|
|
||||||
if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
|
if (fcp->isp_loopstate < LOOP_LSCAN_DONE)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
if (fcp->isp_loopstate >= LOOP_FSCAN_DONE)
|
||||||
if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
|
isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
|
||||||
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
|
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
|
||||||
if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
|
if (!TOPO_IS_FABRIC(fcp->isp_topo)) {
|
||||||
@ -3450,8 +3452,8 @@ fail:
|
|||||||
abort:
|
abort:
|
||||||
FC_SCRATCH_RELEASE(isp, chan);
|
FC_SCRATCH_RELEASE(isp, chan);
|
||||||
isp_prt(isp, ISP_LOG_SANCFG,
|
isp_prt(isp, ISP_LOG_SANCFG,
|
||||||
"Chan %d FC fabric scan done (abort)", chan);
|
"Chan %d FC fabric scan aborted", chan);
|
||||||
return (-1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3478,11 +3480,11 @@ abort:
|
|||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
fcp->isp_loopstate = LOOP_FSCAN_DONE;
|
fcp->isp_loopstate = LOOP_FSCAN_DONE;
|
||||||
FC_SCRATCH_RELEASE(isp, chan);
|
FC_SCRATCH_RELEASE(isp, chan);
|
||||||
return (0);
|
return (-1);
|
||||||
} else if (r < 0) {
|
} else if (r < 0) {
|
||||||
fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
|
fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
|
||||||
FC_SCRATCH_RELEASE(isp, chan);
|
FC_SCRATCH_RELEASE(isp, chan);
|
||||||
return (0);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan);
|
MEMORYBARRIER(isp, SYNC_SFORCPU, IGPOFF, GIDLEN, chan);
|
||||||
@ -3504,7 +3506,7 @@ abort:
|
|||||||
rs1->snscb_cthdr.ct_explanation);
|
rs1->snscb_cthdr.ct_explanation);
|
||||||
FC_SCRATCH_RELEASE(isp, chan);
|
FC_SCRATCH_RELEASE(isp, chan);
|
||||||
fcp->isp_loopstate = LOOP_FSCAN_DONE;
|
fcp->isp_loopstate = LOOP_FSCAN_DONE;
|
||||||
return (0);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check our buffer was big enough to get the full list. */
|
/* Check our buffer was big enough to get the full list. */
|
||||||
@ -5657,11 +5659,10 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
fcp = FCPARAM(isp, chan);
|
fcp = FCPARAM(isp, chan);
|
||||||
int topo = fcp->isp_topo;
|
int topo = fcp->isp_topo;
|
||||||
|
|
||||||
if (fcp->role == ISP_ROLE_NONE) {
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
continue;
|
continue;
|
||||||
}
|
if (fcp->isp_loopstate > LOOP_HAVE_LINK)
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
fcp->isp_loopstate = LOOP_NIL;
|
|
||||||
ISP_SET_SENDMARKER(isp, chan, 1);
|
ISP_SET_SENDMARKER(isp, chan, 1);
|
||||||
isp_async(isp, ISPASYNC_LIP, chan);
|
isp_async(isp, ISPASYNC_LIP, chan);
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
@ -5714,6 +5715,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
fcp = FCPARAM(isp, chan);
|
fcp = FCPARAM(isp, chan);
|
||||||
if (fcp->role == ISP_ROLE_NONE)
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
continue;
|
continue;
|
||||||
|
fcp->isp_linkstate = 1;
|
||||||
|
if (fcp->isp_loopstate < LOOP_HAVE_LINK)
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
ISP_SET_SENDMARKER(isp, chan, 1);
|
ISP_SET_SENDMARKER(isp, chan, 1);
|
||||||
isp_async(isp, ISPASYNC_LOOP_UP, chan);
|
isp_async(isp, ISPASYNC_LOOP_UP, chan);
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
@ -5734,6 +5738,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
if (fcp->role == ISP_ROLE_NONE)
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
continue;
|
continue;
|
||||||
ISP_SET_SENDMARKER(isp, chan, 1);
|
ISP_SET_SENDMARKER(isp, chan, 1);
|
||||||
|
fcp->isp_linkstate = 0;
|
||||||
fcp->isp_loopstate = LOOP_NIL;
|
fcp->isp_loopstate = LOOP_NIL;
|
||||||
isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
|
isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
@ -5754,7 +5759,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
if (fcp->role == ISP_ROLE_NONE)
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
continue;
|
continue;
|
||||||
ISP_SET_SENDMARKER(isp, chan, 1);
|
ISP_SET_SENDMARKER(isp, chan, 1);
|
||||||
fcp->isp_loopstate = LOOP_NIL;
|
if (fcp->isp_loopstate > LOOP_HAVE_LINK)
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
isp_async(isp, ISPASYNC_LOOP_RESET, chan);
|
isp_async(isp, ISPASYNC_LOOP_RESET, chan);
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
if (isp_target_async(isp, chan, mbox)) {
|
if (isp_target_async(isp, chan, mbox)) {
|
||||||
@ -5797,6 +5803,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
continue;
|
continue;
|
||||||
if (fcp->isp_loopstate > LOOP_LTEST_DONE)
|
if (fcp->isp_loopstate > LOOP_LTEST_DONE)
|
||||||
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
||||||
|
else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
|
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
|
||||||
ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
|
ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
|
||||||
}
|
}
|
||||||
@ -5820,6 +5828,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
break;
|
break;
|
||||||
if (fcp->isp_loopstate > LOOP_LTEST_DONE)
|
if (fcp->isp_loopstate > LOOP_LTEST_DONE)
|
||||||
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
fcp->isp_loopstate = LOOP_LTEST_DONE;
|
||||||
|
else if (fcp->isp_loopstate < LOOP_HAVE_LINK)
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
|
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan,
|
||||||
ISPASYNC_CHANGE_SNS, portid);
|
ISPASYNC_CHANGE_SNS, portid);
|
||||||
break;
|
break;
|
||||||
@ -5867,7 +5877,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ISP_SET_SENDMARKER(isp, chan, 1);
|
ISP_SET_SENDMARKER(isp, chan, 1);
|
||||||
FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
|
FCPARAM(isp, chan)->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER);
|
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER);
|
||||||
break;
|
break;
|
||||||
case ASYNC_P2P_INIT_ERR:
|
case ASYNC_P2P_INIT_ERR:
|
||||||
@ -5939,16 +5949,29 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt
|
|||||||
if (fcp->role == ISP_ROLE_NONE)
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
continue;
|
continue;
|
||||||
c = (chan == 0) ? 127 : (chan - 1);
|
c = (chan == 0) ? 127 : (chan - 1);
|
||||||
if (rid.ridacq_map[c / 16] & (1 << (c % 16))) {
|
if (rid.ridacq_map[c / 16] & (1 << (c % 16)) ||
|
||||||
fcp->isp_loopstate = LOOP_NIL;
|
chan == 0) {
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
|
isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
|
||||||
chan, ISPASYNC_CHANGE_OTHER);
|
chan, ISPASYNC_CHANGE_OTHER);
|
||||||
|
} else {
|
||||||
|
fcp->isp_loopstate = LOOP_NIL;
|
||||||
|
isp_async(isp, ISPASYNC_LOOP_DOWN,
|
||||||
|
chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FCPARAM(isp, rid.ridacq_vp_index)->isp_loopstate = LOOP_NIL;
|
fcparam *fcp = FCPARAM(isp, rid.ridacq_vp_index);
|
||||||
isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
|
if (rid.ridacq_vp_status == RIDACQ_STS_COMPLETE ||
|
||||||
rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
|
rid.ridacq_vp_status == RIDACQ_STS_CHANGED) {
|
||||||
|
fcp->isp_loopstate = LOOP_HAVE_LINK;
|
||||||
|
isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
|
||||||
|
rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
|
||||||
|
} else {
|
||||||
|
fcp->isp_loopstate = LOOP_NIL;
|
||||||
|
isp_async(isp, ISPASYNC_LOOP_DOWN,
|
||||||
|
rid.ridacq_vp_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (1);
|
return (1);
|
||||||
case RQSTYPE_ATIO:
|
case RQSTYPE_ATIO:
|
||||||
|
@ -50,13 +50,13 @@ __FBSDID("$FreeBSD$");
|
|||||||
MODULE_VERSION(isp, 1);
|
MODULE_VERSION(isp, 1);
|
||||||
MODULE_DEPEND(isp, cam, 1, 1, 1);
|
MODULE_DEPEND(isp, cam, 1, 1, 1);
|
||||||
int isp_announced = 0;
|
int isp_announced = 0;
|
||||||
int isp_fabric_hysteresis = 5;
|
|
||||||
int isp_loop_down_limit = 60; /* default loop down limit */
|
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_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 */
|
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 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 d_ioctl_t ispioctl;
|
||||||
static void isp_intr_enable(void *);
|
static void isp_intr_enable(void *);
|
||||||
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
|
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
|
||||||
@ -168,25 +168,13 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
|
|||||||
fc->isp = isp;
|
fc->isp = isp;
|
||||||
fc->ready = 1;
|
fc->ready = 1;
|
||||||
|
|
||||||
callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0);
|
|
||||||
callout_init_mtx(&fc->gdt, &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);
|
TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc);
|
||||||
|
isp_loop_changed(isp, chan);
|
||||||
/*
|
|
||||||
* 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_UNLOCK(isp);
|
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)) {
|
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);
|
xpt_free_path(fc->path);
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if (callout_active(&fc->ldt))
|
|
||||||
callout_stop(&fc->ldt);
|
|
||||||
xpt_bus_deregister(cam_sim_path(fc->sim));
|
xpt_bus_deregister(cam_sim_path(fc->sim));
|
||||||
ISP_UNLOCK(isp);
|
ISP_UNLOCK(isp);
|
||||||
cam_sim_free(fc->sim, FALSE);
|
cam_sim_free(fc->sim, FALSE);
|
||||||
@ -377,13 +365,13 @@ isp_detach(ispsoftc_t *isp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
|
isp_freeze_loopdown(ispsoftc_t *isp, int chan)
|
||||||
{
|
{
|
||||||
if (IS_FC(isp)) {
|
if (IS_FC(isp)) {
|
||||||
struct isp_fc *fc = ISP_FC_PC(isp, chan);
|
struct isp_fc *fc = ISP_FC_PC(isp, chan);
|
||||||
if (fc->simqfrozen == 0) {
|
if (fc->simqfrozen == 0) {
|
||||||
isp_prt(isp, ISP_LOGDEBUG0,
|
isp_prt(isp, ISP_LOGDEBUG0,
|
||||||
"Chan %d %s -- freeze simq (loopdown)", chan, msg);
|
"Chan %d Freeze simq (loopdown)", chan);
|
||||||
fc->simqfrozen = SIMQFRZ_LOOPDOWN;
|
fc->simqfrozen = SIMQFRZ_LOOPDOWN;
|
||||||
#if __FreeBSD_version >= 1000039
|
#if __FreeBSD_version >= 1000039
|
||||||
xpt_hold_boot();
|
xpt_hold_boot();
|
||||||
@ -391,7 +379,7 @@ isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
|
|||||||
xpt_freeze_simq(fc->sim, 1);
|
xpt_freeze_simq(fc->sim, 1);
|
||||||
} else {
|
} else {
|
||||||
isp_prt(isp, ISP_LOGDEBUG0,
|
isp_prt(isp, ISP_LOGDEBUG0,
|
||||||
"Chan %d %s -- mark frozen (loopdown)", chan, msg);
|
"Chan %d Mark simq frozen (loopdown)", chan);
|
||||||
fc->simqfrozen |= SIMQFRZ_LOOPDOWN;
|
fc->simqfrozen |= SIMQFRZ_LOOPDOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +393,8 @@ isp_unfreeze_loopdown(ispsoftc_t *isp, int chan)
|
|||||||
int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
|
int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
|
||||||
fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
|
fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
|
||||||
if (wasfrozen && fc->simqfrozen == 0) {
|
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);
|
xpt_release_simq(fc->sim, 1);
|
||||||
#if __FreeBSD_version >= 1000039
|
#if __FreeBSD_version >= 1000039
|
||||||
xpt_release_boot();
|
xpt_release_boot();
|
||||||
@ -481,7 +470,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ISP_LOCK(isp);
|
ISP_LOCK(isp);
|
||||||
if (isp_fc_runstate(isp, chan, 5 * 1000000)) {
|
if (isp_fc_runstate(isp, chan, 5 * 1000000) != LOOP_READY) {
|
||||||
retval = EIO;
|
retval = EIO;
|
||||||
} else {
|
} else {
|
||||||
retval = 0;
|
retval = 0;
|
||||||
@ -3270,41 +3259,59 @@ isp_gdt_task(void *arg, int pending)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop Down Timer Function- when loop goes down, a timer is started and
|
* When loop goes down we remember the time and freeze CAM command queue.
|
||||||
* and after it expires we come here and take all probational devices that
|
* During some time period we are trying to reprobe the loop. But if we
|
||||||
* the OS knows about and the tell the OS that they've gone away.
|
* 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
|
* 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
|
* 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).
|
* point (implicit PLOGO, e.g., to get the chip's port database state right).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
isp_ldt(void *arg)
|
isp_loop_changed(ispsoftc_t *isp, int chan)
|
||||||
{
|
{
|
||||||
struct isp_fc *fc = arg;
|
fcparam *fcp = FCPARAM(isp, chan);
|
||||||
taskqueue_enqueue(taskqueue_thread, &fc->ltask);
|
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
|
static void
|
||||||
isp_ldt_task(void *arg, int pending)
|
isp_loop_up(ispsoftc_t *isp, int chan)
|
||||||
{
|
{
|
||||||
struct isp_fc *fc = arg;
|
struct isp_fc *fc = ISP_FC_PC(isp, chan);
|
||||||
ispsoftc_t *isp = fc->isp;
|
|
||||||
int chan = fc - isp->isp_osinfo.pc.fc;
|
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;
|
fcportdb_t *lp;
|
||||||
struct ac_contract ac;
|
struct ac_contract ac;
|
||||||
struct ac_device_changed *adc;
|
struct ac_device_changed *adc;
|
||||||
int dbidx, i;
|
int dbidx, i;
|
||||||
|
|
||||||
ISP_LOCK(isp);
|
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop is dead", chan);
|
||||||
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime);
|
|
||||||
callout_deactivate(&fc->ldt);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify to the OS all targets who we now consider have departed.
|
* Notify to the OS all targets who we now consider have departed.
|
||||||
*/
|
*/
|
||||||
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
|
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)
|
if (lp->state == FC_PORTDB_STATE_NIL)
|
||||||
continue;
|
continue;
|
||||||
@ -3347,14 +3354,8 @@ isp_ldt_task(void *arg, int pending)
|
|||||||
}
|
}
|
||||||
|
|
||||||
isp_unfreeze_loopdown(isp, chan);
|
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_dead = 1;
|
||||||
fc->loop_down_time = fc->loop_down_limit+1;
|
fc->loop_down_time = 0;
|
||||||
wakeup(fc);
|
|
||||||
ISP_UNLOCK(isp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3363,15 +3364,18 @@ isp_kthread(void *arg)
|
|||||||
struct isp_fc *fc = arg;
|
struct isp_fc *fc = arg;
|
||||||
ispsoftc_t *isp = fc->isp;
|
ispsoftc_t *isp = fc->isp;
|
||||||
int chan = fc - isp->isp_osinfo.pc.fc;
|
int chan = fc - isp->isp_osinfo.pc.fc;
|
||||||
int slp = 0;
|
int slp = 0, d;
|
||||||
|
int lb, lim;
|
||||||
|
|
||||||
mtx_lock(&isp->isp_osinfo.lock);
|
mtx_lock(&isp->isp_osinfo.lock);
|
||||||
|
|
||||||
while (isp->isp_osinfo.is_exiting == 0) {
|
while (isp->isp_osinfo.is_exiting == 0) {
|
||||||
int lb, lim;
|
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0,
|
||||||
|
"Chan %d Checking FC state", chan);
|
||||||
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan);
|
|
||||||
lb = isp_fc_runstate(isp, chan, 250000);
|
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
|
* Our action is different based upon whether we're supporting
|
||||||
@ -3381,87 +3385,44 @@ isp_kthread(void *arg)
|
|||||||
*
|
*
|
||||||
* If not, we simply just wait for loop to come up.
|
* If not, we simply just wait for loop to come up.
|
||||||
*/
|
*/
|
||||||
if (lb && (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR)) {
|
if (lb == LOOP_READY || lb < 0) {
|
||||||
/*
|
slp = 0;
|
||||||
* Increment loop down time by the last sleep interval
|
} else {
|
||||||
*/
|
|
||||||
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 we've never seen loop up and we've waited longer
|
* If we've never seen loop up and we've waited longer
|
||||||
* than quickboot time, or we've seen loop up but we've
|
* than quickboot time, or we've seen loop up but we've
|
||||||
* waited longer than loop_down_limit, give up and go
|
* waited longer than loop_down_limit, give up and go
|
||||||
* to sleep until loop comes up.
|
* to sleep until loop comes up.
|
||||||
*/
|
*/
|
||||||
if (FCPARAM(isp, chan)->loop_seen_once == 0) {
|
if (fc->loop_seen_once == 0)
|
||||||
lim = isp_quickboot_time;
|
lim = isp_quickboot_time;
|
||||||
} else {
|
|
||||||
lim = fc->loop_down_limit;
|
|
||||||
}
|
|
||||||
if (fc->loop_down_time >= lim) {
|
|
||||||
isp_freeze_loopdown(isp, chan, "loop limit hit");
|
|
||||||
slp = 0;
|
|
||||||
} else if (fc->loop_down_time < 10) {
|
|
||||||
slp = 1;
|
|
||||||
} else if (fc->loop_down_time < 30) {
|
|
||||||
slp = 5;
|
|
||||||
} else if (fc->loop_down_time < 60) {
|
|
||||||
slp = 10;
|
|
||||||
} else if (fc->loop_down_time < 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
|
else
|
||||||
slp = 60;
|
lim = fc->loop_down_limit;
|
||||||
} else {
|
d = time_uptime - fc->loop_down_time;
|
||||||
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGDEBUG0, "%s: Chan %d FC state OK", __func__, chan);
|
if (d >= lim)
|
||||||
fc->loop_down_time = 0;
|
slp = 0;
|
||||||
slp = 0;
|
else if (d < 10)
|
||||||
|
slp = 1;
|
||||||
|
else if (d < 30)
|
||||||
|
slp = 5;
|
||||||
|
else if (d < 60)
|
||||||
|
slp = 10;
|
||||||
|
else if (d < 120)
|
||||||
|
slp = 20;
|
||||||
|
else
|
||||||
|
slp = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (slp == 0) {
|
||||||
/*
|
if (lb == LOOP_READY)
|
||||||
* If this is past the first loop up or the loop is dead and if we'd frozen the simq, unfreeze it
|
isp_loop_up(isp, chan);
|
||||||
* now so that CAM can start sending us commands.
|
else
|
||||||
*
|
isp_loop_dead(isp, chan);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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;
|
fc->num_threads -= 1;
|
||||||
mtx_unlock(&isp->isp_osinfo.lock);
|
mtx_unlock(&isp->isp_osinfo.lock);
|
||||||
@ -3471,7 +3432,7 @@ isp_kthread(void *arg)
|
|||||||
static void
|
static void
|
||||||
isp_action(struct cam_sim *sim, union ccb *ccb)
|
isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||||
{
|
{
|
||||||
int bus, tgt, ts, error, lim;
|
int bus, tgt, ts, error;
|
||||||
ispsoftc_t *isp;
|
ispsoftc_t *isp;
|
||||||
struct ccb_trans_settings *cts;
|
struct ccb_trans_settings *cts;
|
||||||
|
|
||||||
@ -3535,26 +3496,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
|||||||
break;
|
break;
|
||||||
case CMD_RQLATER:
|
case CMD_RQLATER:
|
||||||
/*
|
/*
|
||||||
* We get this result for FC devices if the loop state isn't ready yet
|
* We get this result if the loop isn't ready
|
||||||
* or if the device in question has gone zombie on us.
|
* or if the device in question has gone zombie.
|
||||||
*
|
|
||||||
* If we've never seen Loop UP at all, we requeue this request and wait
|
|
||||||
* for the initial loop up delay to expire.
|
|
||||||
*/
|
*/
|
||||||
lim = ISP_FC_PC(isp, bus)->loop_down_limit;
|
if (ISP_FC_PC(isp, bus)->loop_dead) {
|
||||||
if (FCPARAM(isp, bus)->loop_seen_once == 0 || ISP_FC_PC(isp, bus)->loop_down_time >= lim) {
|
isp_prt(isp, ISP_LOGDEBUG0,
|
||||||
if (FCPARAM(isp, bus)->loop_seen_once == 0) {
|
"%d.%jx loop is dead",
|
||||||
isp_prt(isp, ISP_LOGDEBUG0,
|
XS_TGT(ccb), (uintmax_t)XS_LUN(ccb));
|
||||||
"%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);
|
|
||||||
}
|
|
||||||
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
|
ccb->ccb_h.status = CAM_SEL_TIMEOUT;
|
||||||
isp_done((struct ccb_scsiio *) ccb);
|
isp_done((struct ccb_scsiio *) ccb);
|
||||||
break;
|
break;
|
||||||
@ -4260,49 +4208,20 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
|||||||
msg = "LOOP Reset";
|
msg = "LOOP Reset";
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case ISPASYNC_LOOP_DOWN:
|
case ISPASYNC_LOOP_DOWN:
|
||||||
{
|
|
||||||
if (msg == NULL)
|
if (msg == NULL)
|
||||||
msg = "LOOP Down";
|
msg = "LOOP Down";
|
||||||
va_start(ap, cmd);
|
va_start(ap, cmd);
|
||||||
bus = va_arg(ap, int);
|
bus = va_arg(ap, int);
|
||||||
va_end(ap);
|
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(isp, bus, /*tgt*/0, /*tgt_set*/ 0);
|
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);
|
isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case ISPASYNC_LOOP_UP:
|
case ISPASYNC_LOOP_UP:
|
||||||
va_start(ap, cmd);
|
va_start(ap, cmd);
|
||||||
bus = va_arg(ap, int);
|
bus = va_arg(ap, int);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
fc = ISP_FC_PC(isp, bus);
|
isp_loop_changed(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_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
|
isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
|
||||||
break;
|
break;
|
||||||
case ISPASYNC_DEV_ARRIVED:
|
case ISPASYNC_DEV_ARRIVED:
|
||||||
@ -4435,18 +4354,7 @@ changed:
|
|||||||
msg = "Other Change Notify";
|
msg = "Other Change Notify";
|
||||||
isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg);
|
isp_prt(isp, ISP_LOGINFO, "Chan %d %s", bus, msg);
|
||||||
}
|
}
|
||||||
|
isp_loop_changed(isp, bus);
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
if (FCPARAM(isp, bus)->role & ISP_ROLE_INITIATOR) {
|
|
||||||
isp_freeze_loopdown(isp, bus, msg);
|
|
||||||
}
|
|
||||||
wakeup(fc);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
|
@ -228,9 +228,9 @@ struct isp_fc {
|
|||||||
bus_dmamap_t tdmap;
|
bus_dmamap_t tdmap;
|
||||||
uint64_t def_wwpn;
|
uint64_t def_wwpn;
|
||||||
uint64_t def_wwnn;
|
uint64_t def_wwnn;
|
||||||
uint32_t loop_down_time;
|
time_t loop_down_time;
|
||||||
uint32_t loop_down_limit;
|
int loop_down_limit;
|
||||||
uint32_t gone_device_time;
|
int gone_device_time;
|
||||||
/*
|
/*
|
||||||
* Per target/lun info- just to keep a per-ITL nexus crn count
|
* Per target/lun info- just to keep a per-ITL nexus crn count
|
||||||
*/
|
*/
|
||||||
@ -239,15 +239,13 @@ struct isp_fc {
|
|||||||
uint32_t
|
uint32_t
|
||||||
simqfrozen : 3,
|
simqfrozen : 3,
|
||||||
default_id : 8,
|
default_id : 8,
|
||||||
hysteresis : 8,
|
|
||||||
def_role : 2, /* default role */
|
def_role : 2, /* default role */
|
||||||
gdt_running : 1,
|
gdt_running : 1,
|
||||||
loop_dead : 1,
|
loop_dead : 1,
|
||||||
|
loop_seen_once : 1,
|
||||||
fcbsy : 1,
|
fcbsy : 1,
|
||||||
ready : 1;
|
ready : 1;
|
||||||
struct callout ldt; /* loop down timer */
|
|
||||||
struct callout gdt; /* gone device timer */
|
struct callout gdt; /* gone device timer */
|
||||||
struct task ltask;
|
|
||||||
struct task gtask;
|
struct task gtask;
|
||||||
#ifdef ISP_TARGET_MODE
|
#ifdef ISP_TARGET_MODE
|
||||||
struct tslist lun_hash[LUN_HASH_SIZE];
|
struct tslist lun_hash[LUN_HASH_SIZE];
|
||||||
@ -698,7 +696,6 @@ extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
|
|||||||
* driver global data
|
* driver global data
|
||||||
*/
|
*/
|
||||||
extern int isp_announced;
|
extern int isp_announced;
|
||||||
extern int isp_fabric_hysteresis;
|
|
||||||
extern int isp_loop_down_limit;
|
extern int isp_loop_down_limit;
|
||||||
extern int isp_gone_device_time;
|
extern int isp_gone_device_time;
|
||||||
extern int isp_quickboot_time;
|
extern int isp_quickboot_time;
|
||||||
|
@ -394,33 +394,31 @@ isp_print_bytes(ispsoftc_t *isp, const char *msg, int amt, void *arg)
|
|||||||
int
|
int
|
||||||
isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
|
isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
|
||||||
{
|
{
|
||||||
fcparam *fcp;
|
fcparam *fcp = FCPARAM(isp, chan);
|
||||||
|
int res;
|
||||||
|
|
||||||
fcp = FCPARAM(isp, chan);
|
again:
|
||||||
if (fcp->role == ISP_ROLE_NONE) {
|
if (fcp->role == ISP_ROLE_NONE)
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
|
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
res = isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval);
|
||||||
if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) {
|
if (res > 0)
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop failed on channel %d", chan);
|
goto again;
|
||||||
return (LOOP_LTEST_DONE);
|
if (res < 0)
|
||||||
}
|
return (fcp->isp_loopstate);
|
||||||
if (isp_control(isp, ISPCTL_SCAN_FABRIC, chan) != 0) {
|
res = isp_control(isp, ISPCTL_SCAN_LOOP, chan);
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric failed on channel %d", chan);
|
if (res > 0)
|
||||||
return (LOOP_LSCAN_DONE);
|
goto again;
|
||||||
}
|
if (res < 0)
|
||||||
if (isp_control(isp, ISPCTL_PDB_SYNC, chan) != 0) {
|
return (fcp->isp_loopstate);
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync failed on channel %d", chan);
|
res = isp_control(isp, ISPCTL_SCAN_FABRIC, chan);
|
||||||
return (LOOP_FSCAN_DONE);
|
if (res > 0)
|
||||||
}
|
goto again;
|
||||||
if (fcp->isp_loopstate != LOOP_READY) {
|
if (res < 0)
|
||||||
isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: not ready again on channel %d", chan);
|
return (fcp->isp_loopstate);
|
||||||
return (-1);
|
res = isp_control(isp, ISPCTL_PDB_SYNC, chan);
|
||||||
}
|
if (res > 0)
|
||||||
return (0);
|
goto again;
|
||||||
|
return (fcp->isp_loopstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -545,6 +543,7 @@ isp_fc_loop_statename(int state)
|
|||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case LOOP_NIL: return "NIL";
|
case LOOP_NIL: return "NIL";
|
||||||
|
case LOOP_HAVE_LINK: return "Have Link";
|
||||||
case LOOP_TESTING_LINK: return "Testing Link";
|
case LOOP_TESTING_LINK: return "Testing Link";
|
||||||
case LOOP_LTEST_DONE: return "Link Test Done";
|
case LOOP_LTEST_DONE: return "Link Test Done";
|
||||||
case LOOP_SCANNING_LOOP: return "Scanning Loop";
|
case LOOP_SCANNING_LOOP: return "Scanning Loop";
|
||||||
|
@ -638,16 +638,6 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tval = 0;
|
|
||||||
snprintf(name, sizeof(name), "%shysteresis", prefix);
|
|
||||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
|
||||||
"name", &tval);
|
|
||||||
if (tval >= 0 && tval < 256) {
|
|
||||||
ISP_FC_PC(isp, chan)->hysteresis = tval;
|
|
||||||
} else {
|
|
||||||
ISP_FC_PC(isp, chan)->hysteresis = isp_fabric_hysteresis;
|
|
||||||
}
|
|
||||||
|
|
||||||
tval = -1;
|
tval = -1;
|
||||||
snprintf(name, sizeof(name), "%sloop_down_limit", prefix);
|
snprintf(name, sizeof(name), "%sloop_down_limit", prefix);
|
||||||
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
|
||||||
|
@ -438,10 +438,9 @@ typedef struct {
|
|||||||
int isp_loopstate; /* Loop State */
|
int isp_loopstate; /* Loop State */
|
||||||
int isp_topo; /* Connection Type */
|
int isp_topo; /* Connection Type */
|
||||||
|
|
||||||
uint32_t : 3,
|
uint32_t : 4,
|
||||||
fctape_enabled : 1,
|
fctape_enabled : 1,
|
||||||
sendmarker : 1,
|
sendmarker : 1,
|
||||||
loop_seen_once : 1,
|
|
||||||
role : 2,
|
role : 2,
|
||||||
isp_portid : 24; /* S_ID */
|
isp_portid : 24; /* S_ID */
|
||||||
|
|
||||||
@ -490,14 +489,15 @@ typedef struct {
|
|||||||
#define FW_NON_PART 7
|
#define FW_NON_PART 7
|
||||||
|
|
||||||
#define LOOP_NIL 0
|
#define LOOP_NIL 0
|
||||||
#define LOOP_TESTING_LINK 1
|
#define LOOP_HAVE_LINK 1
|
||||||
#define LOOP_LTEST_DONE 2
|
#define LOOP_TESTING_LINK 2
|
||||||
#define LOOP_SCANNING_LOOP 3
|
#define LOOP_LTEST_DONE 3
|
||||||
#define LOOP_LSCAN_DONE 4
|
#define LOOP_SCANNING_LOOP 4
|
||||||
#define LOOP_SCANNING_FABRIC 5
|
#define LOOP_LSCAN_DONE 5
|
||||||
#define LOOP_FSCAN_DONE 6
|
#define LOOP_SCANNING_FABRIC 6
|
||||||
#define LOOP_SYNCING_PDB 7
|
#define LOOP_FSCAN_DONE 7
|
||||||
#define LOOP_READY 8
|
#define LOOP_SYNCING_PDB 8
|
||||||
|
#define LOOP_READY 9
|
||||||
|
|
||||||
#define TOPO_NL_PORT 0
|
#define TOPO_NL_PORT 0
|
||||||
#define TOPO_FL_PORT 1
|
#define TOPO_FL_PORT 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user