aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMatt Jacob <mjacob@FreeBSD.org>2007-05-08 17:47:08 +0000
committerMatt Jacob <mjacob@FreeBSD.org>2007-05-08 17:47:08 +0000
commit24c2342e6b25815d1c0d28d9813d3a5ef898d775 (patch)
tree59f4edbda64df0ab94ceb8724bce9690cae1350d /sys
parentfcc1ae4eef1004500dd9518ae7e3854be1b8ae57 (diff)
downloadsrc-24c2342e6b25815d1c0d28d9813d3a5ef898d775.tar.gz
src-24c2342e6b25815d1c0d28d9813d3a5ef898d775.zip
MFC to synchronize with -current. The bugs fixed are relatively few and
hopefully the bugs introduved are even fewer.
Notes
Notes: svn path=/stable/4/; revision=169383
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/isp/isp.c19
-rw-r--r--sys/dev/isp/isp_freebsd.c414
-rw-r--r--sys/dev/isp/isp_freebsd.h122
-rw-r--r--sys/dev/isp/isp_library.c14
-rw-r--r--sys/dev/isp/isp_library.h2
-rw-r--r--sys/dev/isp/isp_pci.c232
-rw-r--r--sys/dev/isp/isp_tpublic.h24
7 files changed, 410 insertions, 417 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index a6d04b7985d6..25b6e8f5b248 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -5121,20 +5121,11 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
isp->isp_mboxtmp[0] = MBOX_HOST_INTERFACE_ERROR;
MBOX_NOTIFY_COMPLETE(isp);
}
-#ifdef ISP_FW_CRASH_DUMP
/*
- * If we have crash dumps enabled, it's up to the handler
- * for isp_async to reinit stuff and restart the firmware
- * after performing the crash dump. The reason we do things
- * this way is that we may need to activate a kernel thread
- * to do all the crash dump goop.
+ * It's up to the handler for isp_async to reinit stuff and
+ * restart the firmware
*/
isp_async(isp, ISPASYNC_FW_CRASH, NULL);
-#else
- isp_async(isp, ISPASYNC_FW_CRASH, NULL);
- isp_reinit(isp);
- isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
-#endif
rval = -1;
break;
@@ -5401,13 +5392,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
break;
case ISP_CONN_FATAL:
isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
-#ifdef ISP_FW_CRASH_DUMP
- isp_async(isp, ISPASYNC_FW_CRASH, NULL);
-#else
isp_async(isp, ISPASYNC_FW_CRASH, NULL);
- isp_reinit(isp);
- isp_async(isp, ISPASYNC_FW_RESTARTED, NULL);
-#endif
return (-1);
case ISP_CONN_LOOPBACK:
isp_prt(isp, ISP_LOGWARN,
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 8ec82e28f9e4..8e5642f16373 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,
+ 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,53 +172,14 @@ 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,
+ 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));
@@ -237,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;
}
@@ -248,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;
}
@@ -258,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;
}
@@ -266,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;
@@ -282,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
@@ -291,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;
@@ -314,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) {
@@ -322,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
@@ -338,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)) {
@@ -349,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;
@@ -382,35 +377,37 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
retval = EINVAL;
break;
}
+ /*
+ * XXX: Current
+ */
+ if (nr == ISP_ROLE_BOTH) {
+ isp_prt(isp, ISP_LOGERR, "dual roles not supported");
+ retval = EINVAL;
+ break;
+ }
*(int *)addr = isp->isp_role;
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:
@@ -425,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;
@@ -437,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:
@@ -448,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;
@@ -457,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;
@@ -471,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:
@@ -632,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;
}
@@ -646,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);
}
@@ -693,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);
}
@@ -1133,7 +1127,7 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
static void
isp_ledone(ispsoftc_t *isp, lun_entry_t *lep)
{
- const char lfmt[] = "now %sabled for target mode";
+ const char lfmt[] = "now %sabled for target mode\n";
union ccb *ccb;
uint32_t seq;
tstate_t *tptr;
@@ -1167,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,
@@ -1182,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;
}
@@ -1204,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;
@@ -1485,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
@@ -1552,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);
}
/*
@@ -1791,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,
@@ -1995,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;
@@ -2012,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;
@@ -2029,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);
}
@@ -2049,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;
@@ -2058,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);
}
@@ -2076,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
@@ -2097,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);
}
@@ -2118,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);
@@ -2134,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.
@@ -2142,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)
@@ -2191,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];
@@ -2219,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");
@@ -2244,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.
*/
@@ -2289,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);
}
@@ -2307,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
@@ -2390,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
@@ -2419,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)
+{
+ 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, error, lim;
+ 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.
*/
@@ -2452,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 */
@@ -2482,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) {
@@ -2523,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;
}
@@ -2532,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;
@@ -2564,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;
}
@@ -2579,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 */
@@ -2597,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-
@@ -2621,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
@@ -2638,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 {
@@ -2651,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:
@@ -2675,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;
}
@@ -2692,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;
@@ -2762,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;
@@ -2825,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
/*
@@ -2969,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;
@@ -3010,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)
@@ -3145,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);
}
}
@@ -3183,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;
@@ -3250,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:
@@ -3261,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:
@@ -3288,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");
}
@@ -3434,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,
@@ -3472,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
@@ -3543,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;
@@ -3553,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:
@@ -3636,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;
@@ -3711,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);
+}
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index a3f70249aae9..c493ecd36b21 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -84,17 +84,13 @@
#define ISP_SBUS_SUPPORTED 0
#endif
-#define HANDLE_LOOPSTATE_IN_OUTER_LAYERS 1
-/* #define ISP_SMPLOCK 1 */
#if __FreeBSD_version < 500000
#define ISP_IFLAGS INTR_TYPE_CAM
+#elif __FreeBSD_version < 700037
+#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY
#else
-#ifdef ISP_SMPLOCK
#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
-#else
-#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY
-#endif
#endif
#if __FreeBSD_version < 700000
@@ -138,10 +134,23 @@ typedef struct tstate {
((lun) & (LUN_HASH_SIZE - 1)))
#endif
+/*
+ * Per command info.
+ */
+struct isp_pcmd {
+ struct isp_pcmd * next;
+ bus_dmamap_t dmap; /* dma map for this command */
+ struct ispsoftc * isp; /* containing isp */
+ struct callout wdog; /* watchdog timer */
+};
+#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1
+#define PISP_PCMD(ccb) ((struct isp_pcmd *)ISP_PCMD(ccb))
+
struct isposinfo {
struct ispsoftc * next;
bus_space_tag_t bus_tag;
bus_space_handle_t bus_handle;
+ bus_dma_tag_t dmat;
uint64_t default_port_wwn;
uint64_t default_node_wwn;
uint32_t default_id;
@@ -165,12 +174,14 @@ struct isposinfo {
mbox_sleep_ok : 1,
mboxcmd_done : 1,
mboxbsy : 1;
- struct callout_handle ldt; /* loop down timer */
- struct callout_handle gdt; /* gone device timer */
-#if __FreeBSD_version >= 500000
- const struct firmware * fw;
+ struct callout ldt; /* loop down timer */
+ struct callout gdt; /* gone device timer */
+#if __FreeBSD_version < 500000
+ uint32_t splcount;
+ uint32_t splsaved;
+#else
struct mtx lock;
- struct cv kthread_cv;
+ const struct firmware * fw;
union {
struct {
char wwnn[17];
@@ -183,6 +194,12 @@ struct isposinfo {
bus_dmamap_t cdmap;
#define isp_cdmat isp_osinfo.cdmat
#define isp_cdmap isp_osinfo.cdmap
+ /*
+ * Per command information.
+ */
+ struct isp_pcmd * pcmd_pool;
+ struct isp_pcmd * pcmd_free;
+
#ifdef ISP_TARGET_MODE
#define TM_WILDCARD_ENABLED 0x02
#define TM_TMODE_ENABLED 0x01
@@ -194,6 +211,7 @@ struct isposinfo {
atio_private_data_t atpdp[ATPDPSIZE];
#endif
};
+#define ISP_KT_WCHAN(isp) (&(isp)->isp_osinfo.kproc)
#define isp_lock isp_osinfo.lock
#define isp_bus_tag isp_osinfo.bus_tag
@@ -202,26 +220,24 @@ struct isposinfo {
/*
* Locking macros...
*/
-
-#ifdef ISP_SMPLOCK
-#define ISP_LOCK(x) mtx_lock(&(x)->isp_lock)
-#define ISP_UNLOCK(x) mtx_unlock(&(x)->isp_lock)
-#define ISPLOCK_2_CAMLOCK(isp) \
- mtx_unlock(&(isp)->isp_lock); mtx_lock(&Giant)
-#define CAMLOCK_2_ISPLOCK(isp) \
- mtx_unlock(&Giant); mtx_lock(&(isp)->isp_lock)
-#else
#if __FreeBSD_version < 500000
-#define ISP_LOCK(x) do { } while (0)
-#define ISP_UNLOCK(x) do { } while (0)
-#define ISPLOCK_2_CAMLOCK(isp) do { } while (0)
-#define CAMLOCK_2_ISPLOCK(isp) do { } while (0)
+#define ISP_LOCK(isp) \
+ if (isp->isp_osinfo.splcount++ == 0) { \
+ isp->isp_osinfo.splsaved = splcam(); \
+ }
+#define ISP_UNLOCK(isp) \
+ if (isp->isp_osinfo.splcount > 1) { \
+ isp->isp_osinfo.splcount--; \
+ } else { \
+ isp->isp_osinfo.splcount = 0; \
+ splx(isp->isp_osinfo.splsaved); \
+ }
+#elif __FreeBSD_version < 700037
+#define ISP_LOCK(isp) do {} while (0)
+#define ISP_UNLOCK(isp) do {} while (0)
#else
-#define ISP_LOCK(x) GIANT_REQUIRED
-#define ISP_UNLOCK(x) do { } while (0)
-#define ISPLOCK_2_CAMLOCK(isp) do { } while (0)
-#define CAMLOCK_2_ISPLOCK(isp) GIANT_REQUIRED
-#endif
+#define ISP_LOCK(isp) mtx_lock(&isp->isp_osinfo.lock)
+#define ISP_UNLOCK(isp) mtx_unlock(&isp->isp_osinfo.lock)
#endif
/*
@@ -292,7 +308,7 @@ default: \
#define XS_T struct ccb_scsiio
#define XS_DMA_ADDR_T bus_addr_t
-#define XS_ISP(ccb) ((ispsoftc_t *) (ccb)->ccb_h.spriv_ptr1)
+#define XS_ISP(ccb) cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path))
#define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
#define XS_TGT(ccb) (ccb)->ccb_h.target_id
#define XS_LUN(ccb) (ccb)->ccb_h.target_lun
@@ -493,9 +509,11 @@ void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
void isp_mbox_notify_done(ispsoftc_t *);
void isp_mbox_release(ispsoftc_t *);
int isp_mstohz(int);
+void isp_platform_intr(void *);
+void isp_common_dmateardown(ispsoftc_t *, struct ccb_scsiio *, uint32_t);
/*
- * Platform specific defines
+ * Platform Version specific defines
*/
#if __FreeBSD_version < 500000
#define BUS_DMA_ROOTARG(x) NULL
@@ -506,12 +524,18 @@ int isp_mstohz(int);
#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
busdma_lock_mutex, &Giant, z)
-#else
+#elif __FreeBSD_version < 700037
#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
busdma_lock_mutex, &Giant, z)
+#else
+#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
+#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
+ bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
+ busdma_lock_mutex, &isp->isp_osinfo.lock, z)
#endif
+
#if __FreeBSD_version < 700031
#define isp_setup_intr(d, i, f, U, if, ifa, hp) \
bus_setup_intr(d, i, f, if, ifa, hp)
@@ -519,12 +543,46 @@ int isp_mstohz(int);
#define isp_setup_intr bus_setup_intr
#endif
+#if __FreeBSD_version < 500000
+#define isp_sim_alloc cam_sim_alloc
+#define isp_callout_init(x) callout_init(x)
+#elif __FreeBSD_version < 700037
+#define isp_callout_init(x) callout_init(x, 0)
+#define isp_sim_alloc cam_sim_alloc
+#else
+#define isp_callout_init(x) callout_init(x, 1)
+#define isp_sim_alloc(a, b, c, d, e, f, g, h) \
+ cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h)
+#endif
+
/* Should be BUS_SPACE_MAXSIZE, but MAXPHYS is larger than BUS_SPACE_MAXSIZE */
#define ISP_NSEGS ((MAXPHYS / PAGE_SIZE) + 1)
/*
* Platform specific inline functions
*/
+static __inline int isp_get_pcmd(ispsoftc_t *, union ccb *);
+static __inline void isp_free_pcmd(ispsoftc_t *, union ccb *);
+
+static __inline int
+isp_get_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+ ISP_PCMD(ccb) = isp->isp_osinfo.pcmd_free;
+ if (ISP_PCMD(ccb) == NULL) {
+ return (-1);
+ }
+ isp->isp_osinfo.pcmd_free = ((struct isp_pcmd *)ISP_PCMD(ccb))->next;
+ return (0);
+}
+
+static __inline void
+isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
+{
+ ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
+ isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
+ ISP_PCMD(ccb) = NULL;
+}
+
/*
* ISP General Library functions
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index 98ec5d5f8021..2f628bf0287d 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -1499,12 +1499,12 @@ isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
void *
isp_find_xs_tgt(ispsoftc_t *isp, uint32_t handle)
{
- if (handle == 0 || (handle & 0x8000) == 0 ||
- (handle & 0x7fff) > isp->isp_maxcmds) {
+ if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 ||
+ (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
isp_prt(isp, ISP_LOGERR, "bad handle in isp_find_xs_tgt");
return (NULL);
} else {
- return (isp->isp_tgtlist[(handle & 0x7fff) - 1]);
+ return (isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1]);
}
}
@@ -1515,7 +1515,7 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
if (xs != NULL) {
for (i = 0; i < isp->isp_maxcmds; i++) {
if (isp->isp_tgtlist[i] == xs) {
- return ((i+1) & 0x7fff);
+ return ((i+1) & ISP_HANDLE_MASK);
}
}
}
@@ -1525,12 +1525,12 @@ isp_find_tgt_handle(ispsoftc_t *isp, void *xs)
void
isp_destroy_tgt_handle(ispsoftc_t *isp, uint32_t handle)
{
- if (handle == 0 || (handle & 0x8000) == 0 ||
- (handle & 0x7fff) > isp->isp_maxcmds) {
+ if (handle == 0 || IS_TARGET_HANDLE(handle) == 0 ||
+ (handle & ISP_HANDLE_MASK) > isp->isp_maxcmds) {
isp_prt(isp, ISP_LOGERR,
"bad handle in isp_destroy_tgt_handle");
} else {
- isp->isp_tgtlist[(handle & 0x7fff) - 1] = NULL;
+ isp->isp_tgtlist[(handle & ISP_HANDLE_MASK) - 1] = NULL;
}
}
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index 13b077c6170b..a614bb658fe8 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -128,6 +128,8 @@ extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
+#define ISP_HANDLE_MASK 0x7fff
+
#ifdef ISP_TARGET_MODE
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <dev/ic/isp_target.h>
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 7b5a32619f6b..b8caf8f68c02 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -75,8 +75,6 @@ isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int isp_pci_mbxdma(ispsoftc_t *);
static int
isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
-static void
-isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint32_t);
static void isp_pci_reset0(ispsoftc_t *);
@@ -89,7 +87,7 @@ static struct ispmdvec mdvec = {
isp_pci_wr_reg,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs,
@@ -103,7 +101,7 @@ static struct ispmdvec mdvec_1080 = {
isp_pci_wr_reg_1080,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs,
@@ -117,7 +115,7 @@ static struct ispmdvec mdvec_12160 = {
isp_pci_wr_reg_1080,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs,
@@ -131,7 +129,7 @@ static struct ispmdvec mdvec_2100 = {
isp_pci_wr_reg,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs
@@ -143,7 +141,7 @@ static struct ispmdvec mdvec_2200 = {
isp_pci_wr_reg,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs
@@ -155,7 +153,7 @@ static struct ispmdvec mdvec_2300 = {
isp_pci_wr_reg,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
isp_pci_dumpregs
@@ -167,7 +165,7 @@ static struct ispmdvec mdvec_2400 = {
isp_pci_wr_reg_2400,
isp_pci_mbxdma,
isp_pci_dmasetup,
- isp_pci_dmateardown,
+ isp_common_dmateardown,
isp_pci_reset0,
isp_pci_reset1,
NULL
@@ -338,7 +336,9 @@ struct isp_pcisoftc {
void * ih;
int16_t pci_poff[_NREG_BLKS];
bus_dma_tag_t dmat;
- bus_dmamap_t *dmaps;
+#if __FreeBSD_version > 700025
+ int msicount;
+#endif
};
@@ -349,7 +349,6 @@ static device_method_t isp_pci_methods[] = {
DEVMETHOD(device_detach, isp_pci_detach),
{ 0, 0 }
};
-static void isp_pci_intr(void *);
static driver_t isp_pci_driver = {
"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
@@ -509,8 +508,6 @@ isp_get_specific_options(device_t dev, ispsoftc_t *isp)
int bitmap;
int unit = device_get_unit(dev);
- callout_handle_init(&isp->isp_osinfo.ldt);
- callout_handle_init(&isp->isp_osinfo.gdt);
if (IS_SCSI(isp)) {
return;
@@ -701,9 +698,6 @@ isp_get_specific_options(device_t dev, ispsoftc_t *isp)
}
}
- callout_handle_init(&isp->isp_osinfo.ldt);
- callout_handle_init(&isp->isp_osinfo.gdt);
-
if (IS_SCSI(isp)) {
return;
}
@@ -1149,8 +1143,21 @@ isp_pci_attach(device_t dev)
data = pci_read_config(dev, PCIR_ROMADDR, 4);
data &= ~1;
pci_write_config(dev, PCIR_ROMADDR, data, 4);
-
+#if __FreeBSD_version > 700025
+ if (IS_24XX(isp) || IS_2322(isp)) {
+ pcs->msicount = pci_msi_count(dev);
+ if (pcs->msicount > 1) {
+ pcs->msicount = 1;
+ }
+ if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
+ iqd = 1;
+ } else {
+ iqd = 0;
+ }
+ }
+#else
iqd = 0;
+#endif
irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
RF_ACTIVE | RF_SHAREABLE);
if (irq == NULL) {
@@ -1164,7 +1171,7 @@ isp_pci_attach(device_t dev)
locksetup++;
#endif
- if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_pci_intr, isp,
+ if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp,
&pcs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
@@ -1205,35 +1212,29 @@ isp_pci_attach(device_t dev)
ISP_UNLOCK(isp);
goto bad;
}
- /*
- * XXXX: Here is where we might unload the f/w module
- * XXXX: (or decrease the reference count to it).
- */
ISP_UNLOCK(isp);
-
return (0);
bad:
-
if (pcs && pcs->ih) {
(void) bus_teardown_intr(dev, irq, pcs->ih);
}
-
#if __FreeBSD_version >= 500000
if (locksetup && isp) {
mtx_destroy(&isp->isp_osinfo.lock);
}
#endif
-
if (irq) {
(void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
}
-
-
+#if __FreeBSD_version > 700025
+ if (pcs && pcs->msicount) {
+ pci_release_msi(dev);
+ }
+#endif
if (regs) {
(void) bus_release_resource(dev, rtp, rgd, regs);
}
-
if (pcs) {
if (pcs->pci_isp.isp_param) {
#ifdef ISP_FW_CRASH_DUMP
@@ -1244,11 +1245,6 @@ bad:
free(pcs->pci_isp.isp_param, M_DEVBUF);
}
}
-
- /*
- * XXXX: Here is where we might unload the f/w module
- * XXXX: (or decrease the reference count to it).
- */
return (ENXIO);
}
@@ -1267,24 +1263,6 @@ isp_pci_detach(device_t dev)
return (0);
}
-static void
-isp_pci_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);
-}
-
-
#define IspVirt2Off(a, x) \
(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
_BLK_REG_SHFT] + ((x) & 0xfff))
@@ -1317,8 +1295,7 @@ isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
}
static int
-isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp,
- uint16_t *semap, uint16_t *mbp)
+isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
{
uint16_t isr, sema;
@@ -1710,7 +1687,6 @@ imc(void *arg, bus_dma_segment_t *segs, int nseg, int error)
static int
isp_pci_mbxdma(ispsoftc_t *isp)
{
- struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
caddr_t base;
uint32_t len;
int i, error, ns;
@@ -1725,9 +1701,11 @@ isp_pci_mbxdma(ispsoftc_t *isp)
if (isp->isp_rquest) {
return (0);
}
+ ISP_UNLOCK(isp);
if (isp->isp_maxcmds == 0) {
isp_prt(isp, ISP_LOGERR, "maxcmds not set");
+ ISP_LOCK(isp);
return (1);
}
@@ -1740,22 +1718,34 @@ isp_pci_mbxdma(ispsoftc_t *isp)
slim = (1 << 24);
}
+ len = isp->isp_maxcmds * sizeof (struct isp_pcmd);
+ isp->isp_osinfo.pcmd_pool =
+ (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+ if (isp->isp_osinfo.pcmd_pool == NULL) {
+ isp_prt(isp, ISP_LOGERR, "cannot allocate pcmds");
+ ISP_LOCK(isp);
+ return (1);
+ }
+
/*
* XXX: We don't really support 64 bit target mode for parallel scsi yet
*/
#ifdef ISP_TARGET_MODE
if (IS_SCSI(isp) && sizeof (bus_addr_t) > 4) {
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
+ ISP_LOCK(isp);
isp_prt(isp, ISP_LOGERR, "we cannot do DAC for SPI cards yet");
return (1);
}
#endif
- ISP_UNLOCK(isp);
- if (isp_dma_tag_create(BUS_DMA_ROOTARG(pcs->pci_dev), 1, slim, llim,
- hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS, slim, 0,
- &pcs->dmat)) {
- isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
+ if (isp_dma_tag_create(
+ BUS_DMA_ROOTARG(((struct isp_pcisoftc *)isp)->pci_dev),
+ 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, ISP_NSEGS,
+ slim, 0, &isp->isp_osinfo.dmat)) {
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "could not create master dma tag");
return (1);
}
@@ -1763,30 +1753,22 @@ isp_pci_mbxdma(ispsoftc_t *isp)
len = sizeof (XS_T **) * isp->isp_maxcmds;
isp->isp_xflist = (XS_T **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (isp->isp_xflist == NULL) {
- isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
return (1);
}
#ifdef ISP_TARGET_MODE
len = sizeof (void **) * isp->isp_maxcmds;
isp->isp_tgtlist = (void **) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
if (isp->isp_tgtlist == NULL) {
- isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array");
- ISP_LOCK(isp);
- return (1);
- }
-#endif
- len = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
- pcs->dmaps = (bus_dmamap_t *) malloc(len, M_DEVBUF, M_WAITOK);
- if (pcs->dmaps == NULL) {
- isp_prt(isp, ISP_LOGERR, "can't alloc dma map storage");
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
-#ifdef ISP_TARGET_MODE
- free(isp->isp_tgtlist, M_DEVBUF);
-#endif
ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGERR, "cannot alloc tgtlist array");
return (1);
}
+#endif
/*
* Allocate and map the request, result queues, plus FC scratch area.
@@ -1801,12 +1783,12 @@ isp_pci_mbxdma(ispsoftc_t *isp)
/*
* Create a tag for the control spaces- force it to within 32 bits.
*/
- if (isp_dma_tag_create(pcs->dmat, QENTRY_LEN, slim,
+ if (isp_dma_tag_create(isp->isp_osinfo.dmat, QENTRY_LEN, slim,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR,
NULL, NULL, len, ns, slim, 0, &isp->isp_cdmat)) {
isp_prt(isp, ISP_LOGERR,
"cannot create a dma tag for control spaces");
- free(pcs->dmaps, M_DEVBUF);
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
#ifdef ISP_TARGET_MODE
free(isp->isp_tgtlist, M_DEVBUF);
@@ -1820,26 +1802,35 @@ isp_pci_mbxdma(ispsoftc_t *isp)
isp_prt(isp, ISP_LOGERR,
"cannot allocate %d bytes of CCB memory", len);
bus_dma_tag_destroy(isp->isp_cdmat);
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
free(isp->isp_xflist, M_DEVBUF);
#ifdef ISP_TARGET_MODE
free(isp->isp_tgtlist, M_DEVBUF);
#endif
- free(pcs->dmaps, M_DEVBUF);
ISP_LOCK(isp);
return (1);
}
for (i = 0; i < isp->isp_maxcmds; i++) {
- error = bus_dmamap_create(pcs->dmat, 0, &pcs->dmaps[i]);
+ struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i];
+ error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap);
if (error) {
isp_prt(isp, ISP_LOGERR,
"error %d creating per-cmd DMA maps", error);
while (--i >= 0) {
- bus_dmamap_destroy(pcs->dmat, pcs->dmaps[i]);
+ bus_dmamap_destroy(isp->isp_osinfo.dmat,
+ isp->isp_osinfo.pcmd_pool[i].dmap);
}
goto bad;
}
+ isp_callout_init(&pcmd->wdog);
+ if (i == isp->isp_maxcmds-1) {
+ pcmd->next = NULL;
+ } else {
+ pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1];
+ }
}
+ isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0];
im.isp = isp;
im.error = 0;
@@ -1867,9 +1858,9 @@ bad:
#ifdef ISP_TARGET_MODE
free(isp->isp_tgtlist, M_DEVBUF);
#endif
- free(pcs->dmaps, M_DEVBUF);
- ISP_LOCK(isp);
+ free(isp->isp_osinfo.pcmd_pool, M_DEVBUF);
isp->isp_rquest = NULL;
+ ISP_LOCK(isp);
return (1);
}
@@ -1912,8 +1903,6 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
struct ccb_scsiio *csio;
ispsoftc_t *isp;
- struct isp_pcisoftc *pcs;
- bus_dmamap_t *dp;
ct_entry_t *cto, *qe;
uint8_t scsi_status;
uint32_t curi, nxti, handle;
@@ -1993,12 +1982,12 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->ct_resid = 0;
cto->ct_scsi_status = 0;
- pcs = (struct isp_pcisoftc *)isp;
- dp = &pcs->dmaps[isp_handle_index(handle)];
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
}
nxti = *mp->nxtip;
@@ -2282,7 +2271,6 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
curip = nxti;
nxti = ISP_NXT_QENTRY(curip, RQUEST_QUEUE_LEN(isp));
if (nxti == mp->optr) {
- ISP_UNLOCK(isp);
isp_prt(isp, ISP_LOGTDEBUG0,
"tdma_mkfc: request queue overflow");
mp->error = MUSHERR_NOQENTRIES;
@@ -2365,8 +2353,6 @@ dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
- struct isp_pcisoftc *pcs;
- bus_dmamap_t *dp;
bus_dma_segment_t *eseg;
ispreqt7_t *rq;
int seglim, datalen;
@@ -2387,14 +2373,14 @@ dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- pcs = (struct isp_pcisoftc *)mp->isp;
- dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
nxti = *mp->nxtip;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
}
datalen = XS_XFRLEN(csio);
@@ -2472,8 +2458,6 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
- struct isp_pcisoftc *pcs;
- bus_dmamap_t *dp;
bus_dma_segment_t *eseg;
ispreq64_t *rq;
int seglim, datalen;
@@ -2493,14 +2477,14 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- pcs = (struct isp_pcisoftc *)mp->isp;
- dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
nxti = *mp->nxtip;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
}
datalen = XS_XFRLEN(csio);
@@ -2606,8 +2590,6 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
- struct isp_pcisoftc *pcs;
- bus_dmamap_t *dp;
bus_dma_segment_t *eseg;
ispreq_t *rq;
int seglim, datalen;
@@ -2627,14 +2609,14 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
- pcs = (struct isp_pcisoftc *)mp->isp;
- dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
nxti = *mp->nxtip;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREREAD);
} else {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
+ bus_dmamap_sync(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, BUS_DMASYNC_PREWRITE);
}
datalen = XS_XFRLEN(csio);
@@ -2728,15 +2710,12 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
}
/*
- * We enter with ISP_LOCK held
*/
static int
isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
uint32_t *nxtip, uint32_t optr)
{
- struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
ispreq_t *qep;
- bus_dmamap_t *dp = NULL;
mush_t mush, *mp;
void (*eptr)(void *, bus_dma_segment_t *, int, int);
@@ -2757,9 +2736,7 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
mp->nxtip = nxtip;
mp->optr = optr;
mp->error = 0;
- ISPLOCK_2_CAMLOCK(isp);
(*eptr)(mp, NULL, 0, 0);
- CAMLOCK_2_ISPLOCK(isp);
goto mbxsync;
}
} else
@@ -2791,16 +2768,21 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
mp->optr = optr;
mp->error = 0;
- ISPLOCK_2_CAMLOCK(isp);
if ((csio->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
if ((csio->ccb_h.flags & CAM_DATA_PHYS) == 0) {
- int error, s;
- dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
- s = splsoftvm();
- error = bus_dmamap_load(pcs->dmat, *dp,
- csio->data_ptr, csio->dxfer_len, eptr, mp, 0);
+ int error;
+#if __FreeBSD_version < 500000
+ int s = splsoftvm();
+#endif
+ error = bus_dmamap_load(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap, csio->data_ptr,
+ csio->dxfer_len, eptr, mp, 0);
+#if __FreeBSD_version < 500000
+ splx(s);
+#endif
if (error == EINPROGRESS) {
- bus_dmamap_unload(pcs->dmat, *dp);
+ bus_dmamap_unload(isp->isp_osinfo.dmat,
+ PISP_PCMD(csio)->dmap);
mp->error = EINVAL;
isp_prt(isp, ISP_LOGERR,
"deferred dma allocation not supported");
@@ -2811,7 +2793,6 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
#endif
mp->error = error;
}
- splx(s);
} else {
/* Pointer to physical buffer */
struct bus_dma_segment seg;
@@ -2836,7 +2817,6 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
(*eptr)(mp, segs, csio->sglist_cnt, 0);
}
}
- CAMLOCK_2_ISPLOCK(isp);
if (mp->error) {
int retval = CMD_COMPLETE;
if (mp->error == MUSHERR_NOQENTRIES) {
@@ -2877,20 +2857,6 @@ mbxsync:
}
static void
-isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle)
-{
- struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
- bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)];
- if ((xs->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTREAD);
- } else {
- bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_POSTWRITE);
- }
- bus_dmamap_unload(pcs->dmat, *dp);
-}
-
-
-static void
isp_pci_reset0(ispsoftc_t *isp)
{
ISP_DISABLE_INTS(isp);
diff --git a/sys/dev/isp/isp_tpublic.h b/sys/dev/isp/isp_tpublic.h
index 63e74540a62f..b16440b0748e 100644
--- a/sys/dev/isp/isp_tpublic.h
+++ b/sys/dev/isp/isp_tpublic.h
@@ -54,6 +54,7 @@ typedef enum {
QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */
QIN_GETINFO, /* the argument is a pointer to a info_t */
QIN_SETINFO, /* the argument is a pointer to a info_t */
+ QIN_GETDLIST, /* the argument is a pointer to a fc_dlist_t */
QIN_ENABLE, /* the argument is a pointer to a enadis_t */
QIN_DISABLE, /* the argument is a pointer to a enadis_t */
QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */
@@ -72,7 +73,7 @@ typedef enum {
* in, and the external module to call back with a QIN_HBA_REG that
* passes back the corresponding information.
*/
-#define QR_VERSION 15
+#define QR_VERSION 16
typedef struct {
/* NB: tags from here to r_version must never change */
void * r_identity;
@@ -87,8 +88,7 @@ typedef struct {
} hba_register_t;
/*
- * An information structure that is used to get or set per-channel
- * transport layer parameters.
+ * An information structure that is used to get or set per-channel transport layer parameters.
*/
typedef struct {
void * i_identity;
@@ -109,6 +109,16 @@ typedef struct {
} info_t;
/*
+ * An information structure to return a list of logged in WWPNs. FC specific.
+ */
+typedef struct {
+ void * d_identity;
+ int d_channel;
+ int d_error;
+ int d_count;
+ uint64_t * d_wwpns;
+} fc_dlist_t;
+/*
* Notify structure
*/
typedef enum {
@@ -324,12 +334,14 @@ typedef struct tmd_cmd {
#define L0LUN_TO_FLATLUN(lptr) ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1]))
#define FLATLUN_TO_L0LUN(lptr, lun) \
- (lptr)[1] = lun; \
+ (lptr)[1] = lun & 0xff; \
if (sizeof (lun) == 1) { \
(lptr)[0] = 0; \
} else { \
- int nl = (lun); \
- if (nl < 256) { \
+ uint16_t nl = lun; \
+ if (nl == LUN_ANY) { \
+ (lptr)[0] = (nl >> 8) & 0xff; \
+ } else if (nl < 256) { \
(lptr)[0] = 0; \
} else { \
(lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \