summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_freebsd.c
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2007-05-05 20:17:23 +0000
committermjacob <mjacob@FreeBSD.org>2007-05-05 20:17:23 +0000
commitace2524e6248fd7ca96bda126cb5bded62451a13 (patch)
treec5e127befa8e1d977a5d0f932bdbef74b370fa64 /sys/dev/isp/isp_freebsd.c
parentb34f6f7ab1b2b31d561cfbfbc0b43a23c6d93a3e (diff)
downloadFreeBSD-src-ace2524e6248fd7ca96bda126cb5bded62451a13.zip
FreeBSD-src-ace2524e6248fd7ca96bda126cb5bded62451a13.tar.gz
Make this an MP safe driver but also still be multi-release.
Seems to work on RELENG_4 through -current and also on sparc64 now. There may still be some issues with the auto attach/detach code to sort out. MFC after: 3 days
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r--sys/dev/isp/isp_freebsd.c409
1 files changed, 185 insertions, 224 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 85b292f..8e5642f 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -99,7 +99,9 @@ static struct cdevsw isp_cdevsw = {
#else
static struct cdevsw isp_cdevsw = {
.d_version = D_VERSION,
+#if __FreeBSD_version < 700037
.d_flags = D_NEEDGIANT,
+#endif
.d_ioctl = ispioctl,
.d_name = "isp",
};
@@ -135,22 +137,17 @@ isp_attach(ispsoftc_t *isp)
/*
* Construct our SIM entry.
*/
- ISPLOCK_2_CAMLOCK(isp);
- sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), &Giant, 1, isp->isp_maxcmds, devq);
+ sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
+ device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
if (sim == NULL) {
cam_simq_free(devq);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
- CAMLOCK_2_ISPLOCK(isp);
isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
isp->isp_osinfo.ehook.ich_arg = isp;
- ISPLOCK_2_CAMLOCK(isp);
if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
cam_sim_free(sim, TRUE);
- CAMLOCK_2_ISPLOCK(isp);
isp_prt(isp, ISP_LOGERR,
"could not establish interrupt enable hook");
return;
@@ -158,7 +155,6 @@ isp_attach(ispsoftc_t *isp)
if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
cam_sim_free(sim, TRUE);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
@@ -167,7 +163,6 @@ isp_attach(ispsoftc_t *isp)
xpt_bus_deregister(cam_sim_path(sim));
cam_sim_free(sim, TRUE);
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
@@ -177,55 +172,15 @@ isp_attach(ispsoftc_t *isp)
csa.callback = isp_cam_async;
csa.callback_arg = sim;
xpt_action((union ccb *)&csa);
- CAMLOCK_2_ISPLOCK(isp);
isp->isp_sim = sim;
isp->isp_path = path;
- /*
- * Create a kernel thread for fibre channel instances. We
- * don't have dual channel FC cards.
- */
- if (IS_FC(isp)) {
- ISPLOCK_2_CAMLOCK(isp);
-#if __FreeBSD_version >= 500000
- cv_init(&isp->isp_osinfo.kthread_cv, "isp_kthread_cv");
- if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
- RFHIGHPID, 0, "%s: fc_thrd",
- device_get_nameunit(isp->isp_dev)))
-#else
- if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
- "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
-#endif
- {
- xpt_bus_deregister(cam_sim_path(sim));
- cam_sim_free(sim, TRUE);
- config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- CAMLOCK_2_ISPLOCK(isp);
- isp_prt(isp, ISP_LOGERR, "could not create kthread");
- return;
- }
- CAMLOCK_2_ISPLOCK(isp);
- /*
- * We start by being "loop down" if we have an initiator role
- */
- if (isp->isp_role & ISP_ROLE_INITIATOR) {
- isp_freeze_loopdown(isp, "isp_attach");
- isp->isp_osinfo.ldt =
- timeout(isp_ldt, isp, isp_quickboot_time * hz);
- isp->isp_osinfo.ldt_running = 1;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
- "Starting Initial Loop Down Timer");
- }
- }
-
/*
* If we have a second channel, construct SIM entry for that.
*/
if (IS_DUALBUS(isp)) {
- ISPLOCK_2_CAMLOCK(isp);
- sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
- device_get_unit(isp->isp_dev), &Giant, 1,
- isp->isp_maxcmds, devq);
+ sim = isp_sim_alloc(isp_action, isp_poll, "isp", isp,
+ device_get_unit(isp->isp_dev), 1, isp->isp_maxcmds, devq);
if (sim == NULL) {
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
xpt_free_path(isp->isp_path);
@@ -238,7 +193,6 @@ isp_attach(ispsoftc_t *isp)
xpt_free_path(isp->isp_path);
cam_sim_free(sim, TRUE);
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
@@ -249,7 +203,6 @@ isp_attach(ispsoftc_t *isp)
xpt_bus_deregister(cam_sim_path(sim));
cam_sim_free(sim, TRUE);
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
@@ -259,7 +212,6 @@ isp_attach(ispsoftc_t *isp)
csa.callback = isp_cam_async;
csa.callback_arg = sim;
xpt_action((union ccb *)&csa);
- CAMLOCK_2_ISPLOCK(isp);
isp->isp_sim2 = sim;
isp->isp_path2 = path;
}
@@ -267,8 +219,11 @@ isp_attach(ispsoftc_t *isp)
/*
* Create device nodes
*/
+ ISP_UNLOCK(isp);
(void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT,
GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev));
+ isp_sysctl_update(isp);
+ ISP_LOCK(isp);
if (isp->isp_role != ISP_ROLE_NONE) {
isp->isp_state = ISP_RUNSTATE;
@@ -283,7 +238,43 @@ isp_attach(ispsoftc_t *isp)
}
tmp->isp_osinfo.next = isp;
}
- isp_sysctl_update(isp);
+
+ /*
+ * Create a kernel thread for fibre channel instances.
+ */
+ if (IS_FC(isp)) {
+ isp_callout_init(&isp->isp_osinfo.ldt);
+ isp_callout_init(&isp->isp_osinfo.gdt);
+ ISP_UNLOCK(isp);
+#if __FreeBSD_version >= 500000
+ if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
+ RFHIGHPID, 0, "%s: fc_thrd",
+ device_get_nameunit(isp->isp_dev)))
+#else
+ if (kthread_create(isp_kthread, isp, &isp->isp_osinfo.kproc,
+ "%s: fc_thrd", device_get_nameunit(isp->isp_dev)))
+#endif
+ {
+ ISP_LOCK(isp);
+ xpt_bus_deregister(cam_sim_path(sim));
+ cam_sim_free(sim, TRUE);
+ config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+ isp_prt(isp, ISP_LOGERR, "could not create kthread");
+ return;
+ }
+ ISP_LOCK(isp);
+ /*
+ * We start by being "loop down" if we have an initiator role
+ */
+ if (isp->isp_role & ISP_ROLE_INITIATOR) {
+ isp_freeze_loopdown(isp, "isp_attach");
+ isp->isp_osinfo.ldt_running = 1;
+ callout_reset(&isp->isp_osinfo.ldt,
+ isp_quickboot_time * hz, isp_ldt, isp);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
+ "Starting Initial Loop Down Timer");
+ }
+ }
}
static void
@@ -292,9 +283,7 @@ isp_freeze_loopdown(ispsoftc_t *isp, char *msg)
if (isp->isp_osinfo.simqfrozen == 0) {
isp_prt(isp, ISP_LOGDEBUG0, "%s: freeze simq (loopdown)", msg);
isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
- ISPLOCK_2_CAMLOCK(isp);
xpt_freeze_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
} else {
isp_prt(isp, ISP_LOGDEBUG0, "%s: mark frozen (loopdown)", msg);
isp->isp_osinfo.simqfrozen |= SIMQFRZ_LOOPDOWN;
@@ -315,6 +304,11 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
{
ispsoftc_t *isp;
int nr, retval = ENOTTY;
+#if __FreeBSD_version < 500000
+ int s = splcam();
+#else
+ GIANT_REQUIRED;
+#endif
isp = isplist;
while (isp) {
@@ -323,8 +317,12 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
}
isp = isp->isp_osinfo.next;
}
- if (isp == NULL)
+ if (isp == NULL) {
+#if __FreeBSD_version < 500000
+ splx(s);
+#endif
return (ENXIO);
+ }
switch (c) {
#ifdef ISP_FW_CRASH_DUMP
@@ -339,7 +337,6 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
} else {
sz = QLA2300_RISC_IMAGE_DUMP_SIZE;
}
- ISP_LOCK(isp);
if (ptr && *ptr) {
void *uaddr = *((void **) addr);
if (copyout(ptr, uaddr, sz)) {
@@ -350,17 +347,14 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
} else {
retval = ENXIO;
}
- ISP_UNLOCK(isp);
}
break;
case ISP_FORCE_CRASH_DUMP:
if (IS_FC(isp)) {
- ISP_LOCK(isp);
isp_freeze_loopdown(isp,
"ispioctl(ISP_FORCE_CRASH_DUMP)");
isp_fw_dump(isp);
isp_reinit(isp);
- ISP_UNLOCK(isp);
retval = 0;
}
break;
@@ -395,31 +389,25 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
isp->isp_role = nr;
/* FALLTHROUGH */
case ISP_RESETHBA:
- ISP_LOCK(isp);
isp_reinit(isp);
- ISP_UNLOCK(isp);
retval = 0;
break;
case ISP_RESCAN:
if (IS_FC(isp)) {
- ISP_LOCK(isp);
if (isp_fc_runstate(isp, 5 * 1000000)) {
retval = EIO;
} else {
retval = 0;
}
- ISP_UNLOCK(isp);
}
break;
case ISP_FC_LIP:
if (IS_FC(isp)) {
- ISP_LOCK(isp);
if (isp_control(isp, ISPCTL_SEND_LIP, 0)) {
retval = EIO;
} else {
retval = 0;
}
- ISP_UNLOCK(isp);
}
break;
case ISP_FC_GETDINFO:
@@ -434,7 +422,6 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
retval = EINVAL;
break;
}
- ISP_LOCK(isp);
lp = &FCPARAM(isp)->portdb[ifc->loopid];
if (lp->state == FC_PORTDB_STATE_VALID) {
ifc->role = lp->roles;
@@ -446,7 +433,6 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
} else {
retval = ENODEV;
}
- ISP_UNLOCK(isp);
break;
}
case ISP_GET_STATS:
@@ -457,7 +443,6 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
sp->isp_stat_version = ISP_STATS_VERSION;
sp->isp_type = isp->isp_type;
sp->isp_revision = isp->isp_revision;
- ISP_LOCK(isp);
sp->isp_stats[ISP_INTCNT] = isp->isp_intcnt;
sp->isp_stats[ISP_INTBOGUS] = isp->isp_intbogus;
sp->isp_stats[ISP_INTMBOXC] = isp->isp_intmboxc;
@@ -466,12 +451,10 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
sp->isp_stats[ISP_FPHCCMCPLT] = isp->isp_fphccmplt;
sp->isp_stats[ISP_RSCCHIWAT] = isp->isp_rscchiwater;
sp->isp_stats[ISP_FPCCHIWAT] = isp->isp_fpcchiwater;
- ISP_UNLOCK(isp);
retval = 0;
break;
}
case ISP_CLR_STATS:
- ISP_LOCK(isp);
isp->isp_intcnt = 0;
isp->isp_intbogus = 0;
isp->isp_intmboxc = 0;
@@ -480,7 +463,6 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
isp->isp_fphccmplt = 0;
isp->isp_rscchiwater = 0;
isp->isp_fpcchiwater = 0;
- ISP_UNLOCK(isp);
retval = 0;
break;
case ISP_FC_GETHINFO:
@@ -641,12 +623,10 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
break;
}
if (retval == 0) {
- ISP_LOCK(isp);
if (needmarker) {
isp->isp_sendmarker |= 1;
}
retval = isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs);
- ISP_UNLOCK(isp);
if (retval)
retval = EIO;
}
@@ -655,6 +635,9 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
default:
break;
}
+#if __FreeBSD_version < 500000
+ splx(s);
+#endif
return (retval);
}
@@ -702,9 +685,11 @@ static void
isp_intr_enable(void *arg)
{
ispsoftc_t *isp = arg;
+ ISP_LOCK(isp);
if (isp->isp_role != ISP_ROLE_NONE) {
ISP_ENABLE_INTS(isp);
}
+ ISP_UNLOCK(isp);
/* Release our hook so that the boot can continue. */
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
}
@@ -1176,9 +1161,7 @@ err:
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
rls_lun_statep(isp, tptr);
isp->isp_osinfo.leact[seq] = 0;
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
- CAMLOCK_2_ISPLOCK(isp);
return;
} else {
isp_prt(isp, ISP_LOGTDEBUG0,
@@ -1191,9 +1174,7 @@ err:
xpt_print(ccb->ccb_h.path, lfmt, "en");
rls_lun_statep(isp, tptr);
isp->isp_osinfo.leact[seq] = 0;
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
- CAMLOCK_2_ISPLOCK(isp);
return;
}
@@ -1213,9 +1194,7 @@ err:
destroy_lun_state(isp, tptr);
ccb->ccb_h.status = CAM_REQ_CMP;
isp->isp_osinfo.leact[seq] = 0;
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
- CAMLOCK_2_ISPLOCK(isp);
if (are_any_luns_enabled(isp, XS_CHANNEL(ccb)) == 0) {
int bus = XS_CHANNEL(ccb);
av = bus << 31;
@@ -1494,9 +1473,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
isp_destroy_tgt_handle(isp, handle);
out:
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
- CAMLOCK_2_ISPLOCK(isp);
}
static void
@@ -1561,13 +1538,11 @@ isp_target_putback_atio(union ccb *ccb)
static void
isp_complete_ctio(union ccb *ccb)
{
- ISPLOCK_2_CAMLOCK(isp);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
ccb->ccb_h.status |= CAM_REQ_CMP;
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
- CAMLOCK_2_ISPLOCK(isp);
}
/*
@@ -1800,7 +1775,6 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
atp->last_xframt = 0;
atp->bytes_xfered = 0;
atp->state = ATPD_STATE_CAM;
- ISPLOCK_2_CAMLOCK(siP);
xpt_done((union ccb*)atiop);
isp_prt(isp, ISP_LOGTDEBUG0,
@@ -2004,7 +1978,6 @@ isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
tgt = xpt_path_target_id(path);
if (tgt >= 0) {
sdp += cam_sim_bus(sim);
- ISP_LOCK(isp);
nflags = sdp->isp_devparam[tgt].nvrm_flags;
#ifndef ISP_TARGET_MODE
nflags &= DPARM_SAFE_DFLT;
@@ -2021,7 +1994,6 @@ isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
(void) isp_control(isp,
ISPCTL_UPDATE_PARAMS, NULL);
sdp->isp_devparam[tgt].goal_flags = oflags;
- ISP_UNLOCK(isp);
}
}
break;
@@ -2038,11 +2010,9 @@ isp_poll(struct cam_sim *sim)
uint32_t isr;
uint16_t sema, mbox;
- ISP_LOCK(isp);
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
isp_intr(isp, isr, sema, mbox);
}
- ISP_UNLOCK(isp);
}
@@ -2058,7 +2028,6 @@ isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
* to kill a command that's already dead by getting it's handle and
* and seeing whether it's still alive.
*/
- ISP_LOCK(isp);
handle = isp_find_handle(isp, xs);
if (handle) {
uint32_t isr;
@@ -2067,14 +2036,12 @@ isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
if (XS_CMD_DONE_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG1,
"watchdog found done cmd (handle 0x%x)", handle);
- ISP_UNLOCK(isp);
return (1);;
}
if (XS_CMD_WDOG_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG2,
"recursive watchdog (handle 0x%x)", handle);
- ISP_UNLOCK(isp);
return (1);
}
@@ -2085,9 +2052,8 @@ isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
if (XS_CMD_DONE_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG2,
"watchdog cleanup for handle 0x%x", handle);
- ISPLOCK_2_CAMLOCK(isp);
+ isp_free_pcmd(isp, (union ccb *)xs);
xpt_done((union ccb *) xs);
- CAMLOCK_2_ISPLOCK(isp);
} else if (XS_CMD_GRACE_P(xs)) {
/*
* Make sure the command is *really* dead before we
@@ -2106,19 +2072,15 @@ isp_watchdog_work(ispsoftc_t *isp, XS_T *xs)
"watchdog timeout for handle 0x%x\n", handle);
XS_SETERR(xs, CAM_CMD_TIMEOUT);
XS_CMD_C_WDOG(xs);
- ISPLOCK_2_CAMLOCK(isp);
isp_done(xs);
- CAMLOCK_2_ISPLOCK(isp);
} else {
XS_CMD_C_WDOG(xs);
xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
XS_CMD_S_GRACE(xs);
isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
}
- ISP_UNLOCK(isp);
return (1);
}
- ISP_UNLOCK(isp);
return (0);
}
@@ -2127,10 +2089,12 @@ isp_watchdog(void *arg)
{
ispsoftc_t *isp;
XS_T *xs = arg;
- for (isp = isplist; isp != NULL; isp = isp->isp_osinfo.next) {
- if (isp_watchdog_work(isp, xs)) {
- break;
- }
+ int r;
+
+ for (r = 0, isp = isplist; r && isp; isp = isp->isp_osinfo.next) {
+ ISP_LOCK(isp);
+ r = isp_watchdog_work(isp, xs);
+ ISP_UNLOCK(isp);
}
if (isp == NULL) {
printf("isp_watchdog: nobody had %p active\n", arg);
@@ -2143,7 +2107,6 @@ static void
isp_make_here(ispsoftc_t *isp, int tgt)
{
union ccb *ccb;
- ISPLOCK_2_CAMLOCK(mpt);
/*
* Allocate a CCB, create a wildcard path for this bus,
* and schedule a rescan.
@@ -2151,31 +2114,26 @@ isp_make_here(ispsoftc_t *isp, int tgt)
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
isp_prt(isp, ISP_LOGWARN, "unable to alloc CCB for rescan");
- CAMLOCK_2_ISPLOCK(mpt);
return;
}
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
cam_sim_path(isp->isp_sim), tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- CAMLOCK_2_ISPLOCK(mpt);
isp_prt(isp, ISP_LOGWARN, "unable to create path for rescan");
xpt_free_ccb(ccb);
return;
}
xpt_rescan(ccb);
- CAMLOCK_2_ISPLOCK(mpt);
}
static void
isp_make_gone(ispsoftc_t *isp, int tgt)
{
struct cam_path *tp;
- ISPLOCK_2_CAMLOCK(isp);
if (xpt_create_path(&tp, NULL, cam_sim_path(isp->isp_sim), tgt,
CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
xpt_async(AC_LOST_DEVICE, tp, NULL);
xpt_free_path(tp);
}
- CAMLOCK_2_ISPLOCK(isp);
}
#else
#define isp_make_here(isp, tgt) do { ; } while (0)
@@ -2200,8 +2158,8 @@ isp_gdt(void *arg)
fcportdb_t *lp;
int dbidx, tgt, more_to_do = 0;
- isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGDEBUG0, "GDT timer expired");
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
lp = &FCPARAM(isp)->portdb[dbidx];
@@ -2228,7 +2186,8 @@ isp_gdt(void *arg)
isp_make_gone(isp, tgt);
}
if (more_to_do) {
- isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
+ isp->isp_osinfo.gdt_running = 1;
+ callout_reset(&isp->isp_osinfo.gdt, hz, isp_gdt, isp);
} else {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"stopping Gone Device Timer");
@@ -2253,9 +2212,10 @@ isp_ldt(void *arg)
fcportdb_t *lp;
int dbidx, tgt;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Loop Down Timer expired");
+
/*
* Notify to the OS all targets who we now consider have departed.
*/
@@ -2298,15 +2258,7 @@ isp_ldt(void *arg)
* to notice that fact (or make it false).
*/
isp->isp_osinfo.loop_down_time = isp->isp_osinfo.loop_down_limit+1;
-#if __FreeBSD_version < 500000
- wakeup(&isp->isp_osinfo.kproc);
-#else
-#ifdef ISP_SMPLOCK
- cv_signal(&isp->isp_osinfo.kthread_cv);
-#else
- wakeup(&isp->isp_osinfo.kthread_cv);
-#endif
-#endif
+ wakeup(ISP_KT_WCHAN(isp));
ISP_UNLOCK(isp);
}
@@ -2316,15 +2268,11 @@ isp_kthread(void *arg)
ispsoftc_t *isp = arg;
int slp = 0;
#if __FreeBSD_version < 500000
- int s;
-
- s = splcam();
-#else
-#ifdef ISP_SMPLOCK
- mtx_lock(&isp->isp_lock);
-#else
+ int s = splcam();
+#elif __FreeBSD_version < 700037
mtx_lock(&Giant);
-#endif
+#else
+ mtx_lock(&isp->isp_osinfo.lock);
#endif
/*
* The first loop is for our usage where we have yet to have
@@ -2399,23 +2347,15 @@ isp_kthread(void *arg)
if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"isp_kthread: releasing simq");
- ISPLOCK_2_CAMLOCK(isp);
xpt_release_simq(isp->isp_sim, 1);
- CAMLOCK_2_ISPLOCK(isp);
}
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"isp_kthread: sleep time %d", slp);
-#if __FreeBSD_version < 500000
- tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf",
- slp * hz);
+#if __FreeBSD_version < 700037
+ tsleep(ISP_KT_WCHAN(isp), PRIBIO, "ispf", slp * hz);
#else
-#ifdef ISP_SMPLOCK
- cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock,
- slp * hz);
-#else
- (void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf",
- slp * hz);
-#endif
+ msleep(ISP_KT_WCHAN(isp), &isp->isp_osinfo.lock,
+ PRIBIO, "ispf", slp * hz);
#endif
/*
* If slp is zero, we're waking up for the first time after
@@ -2428,30 +2368,52 @@ isp_kthread(void *arg)
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"isp_kthread: sleep hysteresis tick time %d",
isp->isp_osinfo.hysteresis * hz);
+#if __FreeBSD_version < 700037
(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
(isp->isp_osinfo.hysteresis * hz));
+#else
+ (void) msleep(&isp_fabric_hysteresis,
+ &isp->isp_osinfo.lock, PRIBIO, "ispT",
+ (isp->isp_osinfo.hysteresis * hz));
+#endif
}
}
+#if __FreeBSD_version < 500000
+ splx(s);
+#elif __FreeBSD_version < 700037
+ mtx_unlock(&Giant);
+#else
+ mtx_unlock(&isp->isp_osinfo.lock);
+#endif
}
+#if __FreeBSD_version < 500000
+static void isp_action_wrk(struct cam_sim *, union ccb *);
static void
isp_action(struct cam_sim *sim, union ccb *ccb)
{
- int bus, tgt, error, lim;
+ ispsoftc_t *isp = (ispsoftc_t *)cam_sim_softc(sim);
+ ISP_LOCK(isp);
+ isp_action_wrk(sim, ccb);
+ ISP_UNLOCK(isp);
+}
+#define isp_action isp_action_wrk
+#endif
+
+static void
+isp_action(struct cam_sim *sim, union ccb *ccb)
+{
+ int bus, tgt, ts, error, lim;
ispsoftc_t *isp;
struct ccb_trans_settings *cts;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("isp_action\n"));
isp = (ispsoftc_t *)cam_sim_softc(sim);
- ccb->ccb_h.sim_priv.entries[0].field = 0;
- ccb->ccb_h.sim_priv.entries[1].ptr = isp;
if (isp->isp_state != ISP_RUNSTATE &&
ccb->ccb_h.func_code == XPT_SCSI_IO) {
- CAMLOCK_2_ISPLOCK(isp);
isp_init(isp);
if (isp->isp_state != ISP_INITSTATE) {
- ISP_UNLOCK(isp);
/*
* Lie. Say it was a selection timeout.
*/
@@ -2461,10 +2423,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
return;
}
isp->isp_state = ISP_RUNSTATE;
- ISPLOCK_2_CAMLOCK(isp);
}
isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
-
+ ISP_PCMD(ccb) = NULL;
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO: /* Execute the requested I/O operation */
@@ -2491,32 +2452,33 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
}
#endif
- ((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
- CAMLOCK_2_ISPLOCK(isp);
+ ccb->csio.scsi_status = SCSI_STATUS_OK;
+ if (isp_get_pcmd(isp, ccb)) {
+ isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
+ cam_freeze_devq(ccb->ccb_h.path);
+ cam_release_devq(ccb->ccb_h.path,
+ RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ xpt_done(ccb);
+ break;
+ }
error = isp_start((XS_T *) ccb);
switch (error) {
case CMD_QUEUED:
XS_CMD_S_CLEAR(ccb);
- ISPLOCK_2_CAMLOCK(isp);
ccb->ccb_h.status |= CAM_SIM_QUEUED;
- if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
- int ms = ccb->ccb_h.timeout;
- if (ms == CAM_TIME_DEFAULT) {
- ms = 60*1000;
- }
- ccb->ccb_h.timeout_ch =
- timeout(isp_watchdog, ccb, isp_mstohz(ms));
- } else {
- callout_handle_init(&ccb->ccb_h.timeout_ch);
+ if (ccb->ccb_h.timeout == CAM_TIME_INFINITY) {
+ break;
+ }
+ ts = ccb->ccb_h.timeout;
+ if (ts == CAM_TIME_DEFAULT) {
+ ts = 60*1000;
}
+ ts = isp_mstohz(ts);
+ callout_reset(&PISP_PCMD(ccb)->wdog, ts,
+ isp_watchdog, ccb);
break;
case CMD_RQLATER:
/*
- * This can only happen for Fibre Channel
- */
- KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
-
- /*
* Handle initial and subsequent loop down cases
*/
if (FCPARAM(isp)->loop_seen_once == 0) {
@@ -2532,7 +2494,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status =
CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
xpt_freeze_devq(ccb->ccb_h.path, 1);
- ISPLOCK_2_CAMLOCK(isp);
+ isp_free_pcmd(isp, ccb);
xpt_done(ccb);
break;
}
@@ -2541,30 +2503,27 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
/*
* Otherwise, retry in a while.
*/
- ISPLOCK_2_CAMLOCK(isp);
cam_freeze_devq(ccb->ccb_h.path);
cam_release_devq(ccb->ccb_h.path,
RELSIM_RELEASE_AFTER_TIMEOUT, 0, 1000, 0);
XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ isp_free_pcmd(isp, ccb);
xpt_done(ccb);
break;
case CMD_EAGAIN:
- ISPLOCK_2_CAMLOCK(isp);
- cam_freeze_devq(ccb->ccb_h.path);
- cam_release_devq(ccb->ccb_h.path,
- RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ XS_SETERR(ccb, CAM_REQUEUE_REQ);
+ isp_free_pcmd(isp, ccb);
xpt_done(ccb);
break;
case CMD_COMPLETE:
isp_done((struct ccb_scsiio *) ccb);
- ISPLOCK_2_CAMLOCK(isp);
break;
default:
- ISPLOCK_2_CAMLOCK(isp);
isp_prt(isp, ISP_LOGERR,
"What's this? 0x%x at %d in file %s",
error, __LINE__, __FILE__);
XS_SETERR(ccb, CAM_REQ_CMP_ERR);
+ isp_free_pcmd(isp, ccb);
xpt_done(ccb);
}
break;
@@ -2573,10 +2532,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
case XPT_EN_LUN: /* Enable LUN as a target */
{
int seq, i;
- CAMLOCK_2_ISPLOCK(isp);
seq = isp_en_lun(isp, ccb);
if (seq < 0) {
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
break;
}
@@ -2588,7 +2545,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
DELAY(1000);
}
- ISPLOCK_2_CAMLOCK(isp);
break;
}
case XPT_NOTIFY_ACK: /* recycle notify ack */
@@ -2606,7 +2562,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.sim_priv.entries[1].ptr = isp;
ccb->ccb_h.flags = 0;
- CAMLOCK_2_ISPLOCK(isp);
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
/*
* Note that the command itself may not be done-
@@ -2630,14 +2585,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
- ISPLOCK_2_CAMLOCK(isp);
break;
}
case XPT_CONT_TARGET_IO:
{
- CAMLOCK_2_ISPLOCK(isp);
isp_target_start_ctio(isp, ccb);
- ISPLOCK_2_CAMLOCK(isp);
break;
}
#endif
@@ -2647,9 +2599,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
tgt = ccb->ccb_h.target_id;
tgt |= (bus << 16);
- CAMLOCK_2_ISPLOCK(isp);
error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
- ISPLOCK_2_CAMLOCK(isp);
if (error) {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
} else {
@@ -2660,7 +2610,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
case XPT_ABORT: /* Abort the specified CCB */
{
union ccb *accb = ccb->cab.abort_ccb;
- CAMLOCK_2_ISPLOCK(isp);
switch (accb->ccb_h.func_code) {
#ifdef ISP_TARGET_MODE
case XPT_ACCEPT_TARGET_IO:
@@ -2684,7 +2633,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_INVALID;
break;
}
- ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
break;
}
@@ -2701,7 +2649,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
}
tgt = cts->ccb_h.target_id;
- CAMLOCK_2_ISPLOCK(isp);
if (IS_SCSI(isp)) {
#ifndef CAM_NEW_TRAN_CODE
sdparam *sdp = isp->isp_param;
@@ -2771,7 +2718,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
uint16_t *dptr;
if (spi->valid == 0 && scsi->valid == 0) {
- ISPLOCK_2_CAMLOCK(isp);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -2834,14 +2780,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
sdp->isp_devparam[tgt].dev_update = 1;
isp->isp_update |= (1 << bus);
}
- ISPLOCK_2_CAMLOCK(isp);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
case XPT_GET_TRAN_SETTINGS:
cts = &ccb->cts;
tgt = cts->ccb_h.target_id;
- CAMLOCK_2_ISPLOCK(isp);
if (IS_FC(isp)) {
#ifndef CAM_NEW_TRAN_CODE
/*
@@ -2978,7 +2922,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM",
bus, tgt, cts->ccb_h.target_lun, dval, oval, pval);
}
- ISPLOCK_2_CAMLOCK(isp);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -3019,12 +2962,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
#endif
case XPT_RESET_BUS: /* Reset the specified bus */
bus = cam_sim_bus(sim);
- CAMLOCK_2_ISPLOCK(isp);
error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
- ISPLOCK_2_CAMLOCK(isp);
if (error)
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
else {
+ if (bootverbose) {
+ xpt_print(ccb->ccb_h.path, "reset bus\n");
+ }
if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
else if (isp->isp_path != NULL)
@@ -3154,9 +3098,8 @@ isp_done(struct ccb_scsiio *sccb)
"finished command on borrowed time");
}
XS_CMD_S_CLEAR(sccb);
- ISPLOCK_2_CAMLOCK(isp);
+ isp_free_pcmd(isp, (union ccb *) sccb);
xpt_done((union ccb *) sccb);
- CAMLOCK_2_ISPLOCK(isp);
}
}
@@ -3192,18 +3135,15 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
bus = (tgt >> 16) & 0xffff;
tgt &= 0xffff;
sdp += bus;
- ISPLOCK_2_CAMLOCK(isp);
if (xpt_create_path(&tmppath, NULL,
cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- CAMLOCK_2_ISPLOCK(isp);
isp_prt(isp, ISP_LOGWARN,
"isp_async cannot make temp path for %d.%d",
tgt, bus);
rv = -1;
break;
}
- CAMLOCK_2_ISPLOCK(isp);
flags = sdp->isp_devparam[tgt].actv_flags;
#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_CURRENT_SETTINGS;
@@ -3259,10 +3199,8 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
bus, tgt, sdp->isp_devparam[tgt].actv_period,
sdp->isp_devparam[tgt].actv_offset, flags);
xpt_setup_ccb(&cts.ccb_h, tmppath, 1);
- ISPLOCK_2_CAMLOCK(isp);
xpt_async(AC_TRANSFER_NEG, tmppath, &cts);
xpt_free_path(tmppath);
- CAMLOCK_2_ISPLOCK(isp);
break;
}
case ISPASYNC_BUS_RESET:
@@ -3270,13 +3208,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
isp_prt(isp, ISP_LOGINFO, "SCSI bus reset on bus %d detected",
bus);
if (bus > 0 && isp->isp_path2) {
- ISPLOCK_2_CAMLOCK(isp);
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
- CAMLOCK_2_ISPLOCK(isp);
} else if (isp->isp_path) {
- ISPLOCK_2_CAMLOCK(isp);
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
- CAMLOCK_2_ISPLOCK(isp);
}
break;
case ISPASYNC_LIP:
@@ -3297,9 +3231,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
isp_freeze_loopdown(isp, msg);
}
if (isp->isp_osinfo.ldt_running == 0) {
- isp->isp_osinfo.ldt = timeout(isp_ldt, isp,
- isp->isp_osinfo.loop_down_limit * hz);
isp->isp_osinfo.ldt_running = 1;
+ callout_reset(&isp->isp_osinfo.ldt,
+ isp->isp_osinfo.loop_down_limit * hz, isp_ldt, isp);
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"starting Loop Down Timer");
}
@@ -3443,8 +3377,9 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
if (isp->isp_osinfo.gdt_running == 0) {
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"starting Gone Device Timer");
- isp->isp_osinfo.gdt = timeout(isp_gdt, isp, hz);
isp->isp_osinfo.gdt_running = 1;
+ callout_reset(&isp->isp_osinfo.gdt, hz,
+ isp_gdt, isp);
}
tgt = lp->ini_map_idx - 1;
isp_prt(isp, ISP_LOGCONFIG, prom2,
@@ -3481,20 +3416,11 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0,
"Stopping Loop Down Timer");
isp->isp_osinfo.ldt_running = 0;
- untimeout(isp_ldt, isp, isp->isp_osinfo.ldt);
- callout_handle_init(&isp->isp_osinfo.ldt);
+ callout_stop(&isp->isp_osinfo.ldt);
}
isp_prt(isp, ISP_LOGINFO, msg);
isp_freeze_loopdown(isp, msg);
-#if __FreeBSD_version < 500000
- wakeup(&isp->isp_osinfo.kproc);
-#else
-#ifdef ISP_SMPLOCK
- cv_signal(&isp->isp_osinfo.kthread_cv);
-#else
- wakeup(&isp->isp_osinfo.kthread_cv);
-#endif
-#endif
+ wakeup(ISP_KT_WCHAN(isp));
break;
}
#ifdef ISP_TARGET_MODE
@@ -3552,9 +3478,8 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
"Internal Firmware Error on bus %d @ RISC Address 0x%x",
mbox6, mbox1);
#ifdef ISP_FW_CRASH_DUMP
- /*
- * XXX: really need a thread to do this right.
- */
+ mbox1 = isp->isp_osinfo.mbox_sleep_ok;
+ isp->isp_osinfo.mbox_sleep_ok = 0;
if (IS_FC(isp)) {
FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT;
FCPARAM(isp)->isp_loopstate = LOOP_NIL;
@@ -3562,8 +3487,14 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
isp_fw_dump(isp);
}
isp_reinit(isp);
- isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
+ isp->isp_osinfo.mbox_sleep_ok = mbox1;
+#else
+ mbox1 = isp->isp_osinfo.mbox_sleep_ok;
+ isp->isp_osinfo.mbox_sleep_ok = 0;
+ isp_reinit(isp);
+ isp->isp_osinfo.mbox_sleep_ok = mbox1;
#endif
+ isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
break;
}
case ISPASYNC_UNHANDLED_RESPONSE:
@@ -3645,12 +3576,12 @@ isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
isp->isp_osinfo.mbox_sleep_ok = 0;
isp->isp_osinfo.mbox_sleeping = 1;
for (olim = 0; olim < max; olim++) {
-#if __FreeBSD_version < 500000 || !defined(ISP_SMPLOCK)
+#if __FreeBSD_version < 700037
tsleep(&isp->isp_mbxworkp, PRIBIO, "ispmbx_sleep",
isp_mstohz(ms));
#else
- msleep(&isp->isp_mbxworkp, &isp->isp_mtx, PRIBIO,
- "ispmbx_sleep", isp_mstohz(ms));
+ msleep(&isp->isp_mbxworkp, &isp->isp_osinfo.lock,
+ PRIBIO, "ispmbx_sleep", isp_mstohz(ms));
#endif
if (isp->isp_osinfo.mboxcmd_done) {
break;
@@ -3720,3 +3651,33 @@ isp_mstohz(int ms)
}
return (hz);
}
+
+void
+isp_platform_intr(void *arg)
+{
+ ispsoftc_t *isp = arg;
+ uint32_t isr;
+ uint16_t sema, mbox;
+
+ ISP_LOCK(isp);
+ isp->isp_intcnt++;
+ if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
+ isp->isp_intbogus++;
+ } else {
+ isp_intr(isp, isr, sema, mbox);
+ }
+ ISP_UNLOCK(isp);
+}
+
+void
+isp_common_dmateardown(ispsoftc_t *isp, struct ccb_scsiio *csio, uint32_t hdl)
+{
+ if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTREAD);
+ } else {
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_POSTWRITE);
+ }
+ bus_dmamap_unload(isp->isp_osinfo.dmat, PISP_PCMD(csio)->dmap);
+}
OpenPOWER on IntegriCloud