summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2009-12-04 03:34:12 +0000
committermjacob <mjacob@FreeBSD.org>2009-12-04 03:34:12 +0000
commit131d3745385aefd75c98f334be75366694ccbd9c (patch)
tree69ca594dc7af6d5e7423015418427516190b8ab0 /sys/dev/isp
parent901b0b81fe3969528db13d192d74c87c04ac6bf4 (diff)
downloadFreeBSD-src-131d3745385aefd75c98f334be75366694ccbd9c.zip
FreeBSD-src-131d3745385aefd75c98f334be75366694ccbd9c.tar.gz
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
Diffstat (limited to 'sys/dev/isp')
-rw-r--r--sys/dev/isp/isp_freebsd.c91
-rw-r--r--sys/dev/isp/isp_freebsd.h4
2 files changed, 52 insertions, 43 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index ca85d64..2861d7b 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -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
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 2988e30..2942594 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -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
OpenPOWER on IntegriCloud