Fix cases where we've managed to get a Loop UP event prior to initializing
the loop down counter, as well as other things. This was brought to my attention with a different fix, more for RELENG_7- this one covers the multiple channel case. PR: 140438 MFC after: 1 month
This commit is contained in:
parent
d94f2b8506
commit
a01f5aeb09
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=200089
@ -133,33 +133,37 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
fcparam *fcp = FCPARAM(isp, chan);
|
||||
struct isp_fc *fc = ISP_FC_PC(isp, chan);
|
||||
|
||||
ISP_LOCK(isp);
|
||||
fc->sim = sim;
|
||||
fc->path = path;
|
||||
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);
|
||||
|
||||
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);
|
||||
xpt_bus_deregister(cam_sim_path(fc->sim));
|
||||
ISP_UNLOCK(isp);
|
||||
cam_sim_free(fc->sim, FALSE);
|
||||
}
|
||||
/*
|
||||
* We start by being "loop down" if we have an initiator role
|
||||
*/
|
||||
ISP_LOCK(isp);
|
||||
if ((FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) && fc->ldt_running == 0) {
|
||||
if (fcp->role & ISP_ROLE_INITIATOR) {
|
||||
isp_freeze_loopdown(isp, chan, "isp_attach");
|
||||
fc->ldt_running = 1;
|
||||
callout_reset(&fc->ldt, isp_quickboot_time * hz, isp_ldt, fc);
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Starting Initial Loop Down Timer @ %lu", (unsigned long) time_uptime);
|
||||
}
|
||||
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);
|
||||
return (ENOMEM);
|
||||
}
|
||||
#ifdef ISP_INTERNAL_TARGET
|
||||
ISP_SET_PC(isp, chan, proc_active, 1);
|
||||
if (THREAD_CREATE(isp_target_thread_fc, fc, &fc->target_proc, 0, 0, "%s: isp_test_tgt%d", device_get_nameunit(isp->isp_osinfo.dev), chan)) {
|
||||
@ -3935,12 +3939,12 @@ isp_gdt(void *arg)
|
||||
isp_prt(isp, ISP_LOGCONFIG, prom3, chan, lp->portid, tgt, "Gone Device Timeout");
|
||||
isp_make_gone(isp, chan, tgt);
|
||||
}
|
||||
if (more_to_do) {
|
||||
fc->gdt_running = 1;
|
||||
callout_reset(&fc->gdt, hz, isp_gdt, fc);
|
||||
} else {
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d stopping Gone Device Timer", chan);
|
||||
fc->gdt_running = 0;
|
||||
if (fc->ready) {
|
||||
if (more_to_do) {
|
||||
callout_reset(&fc->gdt, hz, isp_gdt, fc);
|
||||
} else {
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d stopping Gone Device Timer", chan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4017,6 +4021,7 @@ isp_kthread(void *arg)
|
||||
ispsoftc_t *isp = fc->isp;
|
||||
int chan = fc - isp->isp_osinfo.pc.fc;
|
||||
int slp = 0;
|
||||
|
||||
mtx_lock(&isp->isp_osinfo.lock);
|
||||
|
||||
for (;;) {
|
||||
@ -4802,6 +4807,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
char *msg = NULL;
|
||||
target_id_t tgt;
|
||||
fcportdb_t *lp;
|
||||
struct isp_fc *fc;
|
||||
struct cam_path *tmppath;
|
||||
va_list ap;
|
||||
|
||||
@ -4886,7 +4892,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
/* FALLTHROUGH */
|
||||
case ISPASYNC_LOOP_DOWN:
|
||||
{
|
||||
struct isp_fc *fc;
|
||||
if (msg == NULL) {
|
||||
msg = "LOOP Down";
|
||||
}
|
||||
@ -4894,20 +4899,21 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
bus = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
|
||||
FCPARAM(isp, bus)->link_active = 1;
|
||||
FCPARAM(isp, bus)->link_active = 0;
|
||||
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
/*
|
||||
* We don't do any simq freezing if we are only in target mode
|
||||
*/
|
||||
if (fc->role & ISP_ROLE_INITIATOR) {
|
||||
if (fc->path) {
|
||||
isp_freeze_loopdown(isp, bus, msg);
|
||||
}
|
||||
if (fc->ldt_running == 0) {
|
||||
fc->ldt_running = 1;
|
||||
callout_reset(&fc->ldt, fc->loop_down_limit * hz, isp_ldt, fc);
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "starting Loop Down Timer @ %lu", (unsigned long) time_uptime);
|
||||
if (cmd == ISPASYNC_LOOP_DOWN && fc->ready) {
|
||||
/*
|
||||
* We don't do any simq freezing if we are only in target mode
|
||||
*/
|
||||
if (fc->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_LOGSANCFG|ISP_LOGDEBUG0, "starting Loop Down Timer @ %lu", (unsigned long) time_uptime);
|
||||
}
|
||||
}
|
||||
}
|
||||
isp_prt(isp, ISP_LOGINFO, "Chan %d: %s", bus, msg);
|
||||
@ -4917,6 +4923,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
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
|
||||
@ -4924,8 +4931,8 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
* thread to look at the state of the loop again.
|
||||
*/
|
||||
FCPARAM(isp, bus)->link_active = 1;
|
||||
ISP_FC_PC(isp, bus)->loop_dead = 0;
|
||||
ISP_FC_PC(isp, bus)->loop_down_time = 0;
|
||||
fc->loop_dead = 0;
|
||||
fc->loop_down_time = 0;
|
||||
isp_prt(isp, ISP_LOGINFO, "Chan %d Loop UP", bus);
|
||||
break;
|
||||
case ISPASYNC_DEV_ARRIVED:
|
||||
@ -4933,8 +4940,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
bus = va_arg(ap, int);
|
||||
lp = va_arg(ap, fcportdb_t *);
|
||||
va_end(ap);
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
lp->reserved = 0;
|
||||
if ((ISP_FC_PC(isp, bus)->role & ISP_ROLE_INITIATOR) && (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
|
||||
if ((fc->role & ISP_ROLE_INITIATOR) && (lp->roles & (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT))) {
|
||||
int dbidx = lp - FCPARAM(isp, bus)->portdb;
|
||||
int i;
|
||||
|
||||
@ -4967,6 +4975,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
bus = va_arg(ap, int);
|
||||
lp = va_arg(ap, fcportdb_t *);
|
||||
va_end(ap);
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
lp->reserved = 0;
|
||||
if (isp_change_is_bad) {
|
||||
lp->state = FC_PORTDB_STATE_NIL;
|
||||
@ -5013,6 +5022,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
bus = va_arg(ap, int);
|
||||
lp = va_arg(ap, fcportdb_t *);
|
||||
va_end(ap);
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
/*
|
||||
* If this has a virtual target and we haven't marked it
|
||||
* that we're going to have isp_gdt tell the OS it's gone,
|
||||
@ -5025,10 +5035,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
lp->reserved = 1;
|
||||
lp->new_reserved = ISP_FC_PC(isp, bus)->gone_device_time;
|
||||
lp->state = FC_PORTDB_STATE_ZOMBIE;
|
||||
if (ISP_FC_PC(isp, bus)->gdt_running == 0) {
|
||||
if (fc->ready && !callout_active(&fc->gdt)) {
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d starting Gone Device Timer", bus);
|
||||
ISP_FC_PC(isp, bus)->gdt_running = 1;
|
||||
callout_reset(&ISP_FC_PC(isp, bus)->gdt, hz, isp_gdt, ISP_FC_PC(isp, bus));
|
||||
callout_reset(&fc->gdt, hz, isp_gdt, fc);
|
||||
}
|
||||
tgt = lp->dev_map_idx - 1;
|
||||
isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, roles[lp->roles], "gone zombie at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
|
||||
@ -5053,6 +5062,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
nlstate = reason = 0;
|
||||
}
|
||||
va_end(ap);
|
||||
fc = ISP_FC_PC(isp, bus);
|
||||
|
||||
if (evt == ISPASYNC_CHANGE_PDB) {
|
||||
msg = "Chan %d Port Database Changed";
|
||||
@ -5065,16 +5075,15 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
|
||||
/*
|
||||
* If the loop down timer is running, cancel it.
|
||||
*/
|
||||
if (ISP_FC_PC(isp, bus)->ldt_running) {
|
||||
if (fc->ready && callout_active(&fc->ldt)) {
|
||||
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Stopping Loop Down Timer @ %lu", (unsigned long) time_uptime);
|
||||
ISP_FC_PC(isp, bus)->ldt_running = 0;
|
||||
callout_stop(&ISP_FC_PC(isp, bus)->ldt);
|
||||
callout_stop(&fc->ldt);
|
||||
}
|
||||
isp_prt(isp, ISP_LOGINFO, msg, bus);
|
||||
if (ISP_FC_PC(isp, bus)->role & ISP_ROLE_INITIATOR) {
|
||||
if (fc->role & ISP_ROLE_INITIATOR) {
|
||||
isp_freeze_loopdown(isp, bus, msg);
|
||||
}
|
||||
wakeup(ISP_FC_PC(isp, bus));
|
||||
wakeup(fc);
|
||||
break;
|
||||
}
|
||||
#ifdef ISP_TARGET_MODE
|
||||
|
@ -177,9 +177,9 @@ struct isp_fc {
|
||||
hysteresis : 8,
|
||||
role : 2,
|
||||
gdt_running : 1,
|
||||
ldt_running : 1,
|
||||
loop_dead : 1,
|
||||
fcbsy : 1;
|
||||
fcbsy : 1,
|
||||
ready : 1;
|
||||
struct callout ldt; /* loop down timer */
|
||||
struct callout gdt; /* gone device timer */
|
||||
#ifdef ISP_TARGET_MODE
|
||||
|
Loading…
Reference in New Issue
Block a user