summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2000-07-04 01:05:43 +0000
committermjacob <mjacob@FreeBSD.org>2000-07-04 01:05:43 +0000
commite0a8dae616ce837fcb0a631c17d35ef5deb6d5e1 (patch)
treef020cb7e6d3f0ba92b524b376f2d9c90991597ef
parent22ee60424c34491a4fa0ac2e999919c58366bc13 (diff)
downloadFreeBSD-src-e0a8dae616ce837fcb0a631c17d35ef5deb6d5e1.zip
FreeBSD-src-e0a8dae616ce837fcb0a631c17d35ef5deb6d5e1.tar.gz
Add in config_hook for catching when interrupts are safe- this allows
us to not the ints are ok and also to (re)ENABLE isp interrupts. Remove all splcam()/splx() invocates and replace them with ISP_LOCK/ISP_UNLOCK macros.
-rw-r--r--sys/dev/isp/isp_freebsd.c163
1 files changed, 91 insertions, 72 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index e1c1943..d1c513c 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -34,6 +34,7 @@
*/
#include <dev/isp/isp_freebsd.h>
+static void isp_intr_enable(void *);
static void isp_cam_async(void *, u_int32_t, struct cam_path *, void *);
static void isp_poll(struct cam_sim *);
static void isp_relsim(void *);
@@ -42,7 +43,6 @@ static void isp_action(struct cam_sim *, union ccb *);
static struct ispsoftc *isplist = NULL;
-/* #define ISP_LUN0_ONLY 1 */
#ifdef DEBUG
int isp_debug = 2;
#elif defined(CAMDEBUG) || defined(DIAGNOSTIC)
@@ -84,6 +84,16 @@ isp_attach(struct ispsoftc *isp)
cam_simq_free(devq);
return;
}
+
+ isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
+ isp->isp_osinfo.ehook.ich_arg = isp;
+ if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
+ printf("%s: could not establish interrupt enable hook\n",
+ isp->isp_name);
+ cam_sim_free(sim, TRUE);
+ return;
+ }
+
if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
cam_sim_free(sim, TRUE);
return;
@@ -155,6 +165,15 @@ isp_attach(struct ispsoftc *isp)
}
}
+static void
+isp_intr_enable(void *arg)
+{
+ struct ispsoftc *isp = arg;
+ ENABLE_INTS(isp);
+ isp->isp_osinfo.intsok = 1;
+ /* Release our hook so that the boot can continue. */
+ config_intrhook_disestablish(&isp->isp_osinfo.ehook);
+}
/*
* Put the target mode functions here, because some are inlines
@@ -186,18 +205,18 @@ static __inline int
is_lun_enabled(struct ispsoftc *isp, lun_id_t lun)
{
tstate_t *tptr;
- int s = splsoftcam();
+ ISP_LOCK(isp);
if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) {
- splx(s);
+ ISP_UNLOCK(isp);
return (0);
}
do {
if (tptr->lun == (lun_id_t) lun) {
- splx(s);
+ ISP_UNLOCK(isp);
return (1);
}
} while ((tptr = tptr->next) != NULL);
- splx(s);
+ ISP_UNLOCK(isp);
return (0);
}
@@ -217,30 +236,29 @@ static __inline tstate_t *
get_lun_statep(struct ispsoftc *isp, lun_id_t lun)
{
tstate_t *tptr;
- int s;
- s = splsoftcam();
+ ISP_LOCK(isp);
if (lun == CAM_LUN_WILDCARD) {
tptr = &isp->isp_osinfo.tsdflt;
tptr->hold++;
- splx(s);
+ ISP_UNLOCK(isp);
return (tptr);
} else {
tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)];
}
if (tptr == NULL) {
- splx(s);
+ ISP_UNLOCK(isp);
return (NULL);
}
do {
if (tptr->lun == lun) {
tptr->hold++;
- splx(s);
+ ISP_UNLOCK(isp);
return (tptr);
}
} while ((tptr = tptr->next) != NULL);
- splx(s);
+ ISP_UNLOCK(isp);
return (tptr);
}
@@ -254,28 +272,28 @@ rls_lun_statep(struct ispsoftc *isp, tstate_t *tptr)
static __inline int
isp_psema_sig_rqe(struct ispsoftc *isp)
{
- int s = splcam();
+ ISP_LOCK(isp);
while (isp->isp_osinfo.tmflags & TM_BUSY) {
isp->isp_osinfo.tmflags |= TM_WANTED;
if (tsleep(&isp->isp_osinfo.tmflags, PRIBIO|PCATCH, "i0", 0)) {
- splx(s);
+ ISP_UNLOCK(isp);
return (-1);
}
isp->isp_osinfo.tmflags |= TM_BUSY;
}
- splx(s);
+ ISP_UNLOCK(isp);
return (0);
}
static __inline int
isp_cv_wait_timed_rqe(struct ispsoftc *isp, int timo)
{
- int s = splcam();
+ ISP_LOCK(isp);
if (tsleep(&isp->isp_osinfo.rstatus, PRIBIO, "qt1", timo)) {
- splx(s);
+ ISP_UNLOCK(isp);
return (-1);
}
- splx(s);
+ ISP_UNLOCK(isp);
return (0);
}
@@ -289,19 +307,18 @@ isp_cv_signal_rqe(struct ispsoftc *isp, int status)
static __inline void
isp_vsema_rqe(struct ispsoftc *isp)
{
- int s = splcam();
+ ISP_LOCK(isp);
if (isp->isp_osinfo.tmflags & TM_WANTED) {
isp->isp_osinfo.tmflags &= ~TM_WANTED;
wakeup(&isp->isp_osinfo.tmflags);
}
isp->isp_osinfo.tmflags &= ~TM_BUSY;
- splx(s);
+ ISP_UNLOCK(isp);
}
static cam_status
create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt)
{
- int s;
cam_status status;
lun_id_t lun;
tstate_t *tptr, *new;
@@ -330,7 +347,7 @@ create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt)
SLIST_INIT(&new->inots);
new->hold = 1;
- s = splsoftcam();
+ ISP_LOCK(isp);
if ((tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)]) == NULL) {
isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(lun)] = new;
} else {
@@ -338,7 +355,7 @@ create_lun_state(struct ispsoftc *isp, struct cam_path *path, tstate_t **rslt)
tptr = tptr->next;
tptr->next = new;
}
- splx(s);
+ ISP_UNLOCK(isp);
*rslt = new;
return (CAM_REQ_CMP);
}
@@ -347,16 +364,15 @@ static __inline void
destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
{
tstate_t *lw, *pw;
- int s;
- s = splsoftcam();
+ ISP_LOCK(isp);
if (tptr->hold) {
- splx(s);
+ ISP_UNLOCK(isp);
return;
}
pw = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)];
if (pw == NULL) {
- splx(s);
+ ISP_UNLOCK(isp);
return;
} else if (pw->lun == tptr->lun) {
isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(tptr->lun)] = pw->next;
@@ -372,12 +388,12 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
pw = pw->next;
}
if (pw == NULL) {
- splx(s);
+ ISP_UNLOCK(isp);
return;
}
}
free(tptr, M_DEVBUF);
- splx(s);
+ ISP_UNLOCK(isp);
}
static void
@@ -406,18 +422,18 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
int rv;
fcparam *fcp = isp->isp_param;
- s = splcam();
+ ISP_LOCK(isp);
rv = isp_control(isp, ISPCTL_FCLINK_TEST, NULL);
- (void) splx(s);
+ ISP_UNLOCK(isp);
if (rv || fcp->isp_fwstate != FW_READY) {
xpt_print_path(ccb->ccb_h.path);
printf("link status not good yet\n");
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
return;
}
- s = splcam();
+ ISP_LOCK(isp);
rv = isp_control(isp, ISPCTL_PDB_SYNC, NULL);
- (void) splx(s);
+ ISP_UNLOCK(isp);
if (rv || fcp->isp_fwstate != FW_READY) {
xpt_print_path(ccb->ccb_h.path);
printf("could not get a good port database read\n");
@@ -451,16 +467,16 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
SLIST_INIT(&tptr->atios);
SLIST_INIT(&tptr->inots);
av = 1;
- s = splcam();
+ ISP_LOCK(isp);
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
if (av) {
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
xpt_free_path(tptr->owner);
- splx(s);
+ ISP_UNLOCK(isp);
return;
}
isp->isp_osinfo.tmflags |= TM_TMODE_ENABLED;
- splx(s);
+ ISP_UNLOCK(isp);
} else {
if ((isp->isp_osinfo.tmflags & TM_TMODE_ENABLED) == 0) {
ccb->ccb_h.status = CAM_LUN_INVALID;
@@ -471,15 +487,15 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
return;
}
av = 0;
- s = splcam();
+ ISP_LOCK(isp);
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
if (av) {
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
- splx(s);
+ ISP_UNLOCK(isp);
return;
}
isp->isp_osinfo.tmflags &= ~TM_TMODE_ENABLED;
- splx(s);
+ ISP_UNLOCK(isp);
ccb->ccb_h.status = CAM_REQ_CMP;
}
xpt_print_path(ccb->ccb_h.path);
@@ -532,7 +548,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
return;
}
- s = splcam();
+ ISP_LOCK(isp);
if (cel->enable) {
u_int32_t seq = isp->isp_osinfo.rollinfo++;
rstat = LUN_ERR;
@@ -596,7 +612,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
}
out:
isp_vsema_rqe(isp);
- splx(s);
+ ISP_UNLOCK(isp);
if (rstat != LUN_OK) {
xpt_print_path(ccb->ccb_h.path);
@@ -1149,11 +1165,11 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
if (IS_SCSI(isp)) {
u_int16_t oflags, nflags;
sdparam *sdp = isp->isp_param;
- int s, rvf, tgt;
+ int rvf, tgt;
tgt = xpt_path_target_id(path);
rvf = ISP_FW_REVX(isp->isp_fwrev);
- s = splcam();
+ ISP_LOCK(isp);
sdp += cam_sim_bus(sim);
isp->isp_update |= (1 << cam_sim_bus(sim));
nflags = DPARM_SAFE_DFLT;
@@ -1167,7 +1183,7 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
sdp->isp_devparam[tgt].dev_update = 1;
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
sdp->isp_devparam[tgt].dev_flags = oflags;
- (void) splx(s);
+ ISP_UNLOCK(isp);
}
break;
default:
@@ -1186,7 +1202,7 @@ static void
isp_relsim(void *arg)
{
struct ispsoftc *isp = arg;
- int s = splcam();
+ ISP_LOCK(isp);
if (isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED) {
int wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_TIMED;
isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_TIMED;
@@ -1195,7 +1211,7 @@ isp_relsim(void *arg)
IDPRINTF(3, ("%s: timed relsimq\n", isp->isp_name));
}
}
- splx(s);
+ ISP_UNLOCK(isp);
}
static void
@@ -1204,13 +1220,13 @@ isp_watchdog(void *arg)
ISP_SCSI_XFER_T *xs = arg;
struct ispsoftc *isp = XS_ISP(xs);
u_int32_t handle;
- int s = splcam();
/*
* We've decided this command is dead. Make sure we're not trying
* 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) {
u_int16_t r;
@@ -1218,14 +1234,14 @@ isp_watchdog(void *arg)
if (XS_CMD_DONE_P(xs)) {
PRINTF("%s: watchdog found done cmd (handle 0x%x)\n",
isp->isp_name, handle);
- (void) splx(s);
+ ISP_UNLOCK(isp);
return;
}
if (XS_CMD_WDOG_P(xs)) {
PRINTF("%s: recursive watchdog (handle 0x%x)\n",
isp->isp_name, handle);
- (void) splx(s);
+ ISP_UNLOCK(isp);
return;
}
@@ -1238,6 +1254,9 @@ isp_watchdog(void *arg)
isp->isp_name, handle, r));
xpt_done((union ccb *) xs);
} else if (XS_CMD_GRACE_P(xs)) {
+ if (XS_XFRLEN(xs)) {
+ ISP_DMAFREE(isp, xs, handle);
+ }
isp_destroy_handle(isp, handle);
xpt_print_path(xs->ccb_h.path);
printf("%s: watchdog timeout (%x, %x)\n",
@@ -1252,7 +1271,7 @@ isp_watchdog(void *arg)
XS_CMD_C_WDOG(xs);
xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
if (isp_getrqentry(isp, &iptr, &optr, (void **) &mp)) {
- (void) splx(s);
+ ISP_UNLOCK(isp);
return;
}
XS_CMD_S_GRACE(xs);
@@ -1268,13 +1287,13 @@ isp_watchdog(void *arg)
} else {
IDPRINTF(2, ("%s: watchdog with no command\n", isp->isp_name));
}
- (void) splx(s);
+ ISP_UNLOCK(isp);
}
static void
isp_action(struct cam_sim *sim, union ccb *ccb)
{
- int s, bus, tgt, error;
+ int bus, tgt, error;
struct ispsoftc *isp;
struct ccb_trans_settings *cts;
@@ -1285,11 +1304,11 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.sim_priv.entries[1].ptr = isp;
if (isp->isp_state != ISP_RUNSTATE &&
ccb->ccb_h.func_code == XPT_SCSI_IO) {
- s = splcam();
+ ISP_LOCK(isp);
DISABLE_INTS(isp);
isp_init(isp);
if (isp->isp_state != ISP_INITSTATE) {
- (void) splx(s);
+ ISP_UNLOCK(isp);
/*
* Lie. Say it was a selection timeout.
*/
@@ -1300,7 +1319,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
isp->isp_state = ISP_RUNSTATE;
ENABLE_INTS(isp);
- (void) splx(s);
+ ISP_UNLOCK(isp);
}
IDPRINTF(4, ("%s: isp_action code %x\n", isp->isp_name,
ccb->ccb_h.func_code));
@@ -1332,9 +1351,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
#endif
((struct ccb_scsiio *) ccb)->scsi_status = SCSI_STATUS_OK;
- s = splcam();
+ ISP_LOCK(isp);
error = ispscsicmd((ISP_SCSI_XFER_T *) ccb);
- splx(s);
+ ISP_UNLOCK(isp);
switch (error) {
case CMD_QUEUED:
ccb->ccb_h.status |= CAM_SIM_QUEUED;
@@ -1399,7 +1418,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
xpt_done(ccb);
break;
}
- s = splsoftcam();
+ ISP_LOCK(isp);
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
SLIST_INSERT_HEAD(&tptr->atios,
&ccb->ccb_h, sim_links.sle);
@@ -1407,14 +1426,14 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
sim_links.sle);
}
- splx(s);
+ ISP_UNLOCK(isp);
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;
break;
}
case XPT_CONT_TARGET_IO:
{
- s = splcam();
+ ISP_LOCK(isp);
ccb->ccb_h.status = isp_target_start_ctio(isp, ccb);
if (ccb->ccb_h.status != CAM_REQ_INPROG) {
if (isp->isp_osinfo.simqfrozen == 0) {
@@ -1428,7 +1447,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
} else {
ccb->ccb_h.status |= CAM_SIM_QUEUED;
}
- splx(s);
+ ISP_UNLOCK(isp);
break;
}
#endif
@@ -1438,9 +1457,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
tgt = ccb->ccb_h.target_id;
tgt |= (bus << 16);
- s = splcam();
+ ISP_LOCK(isp);
error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
- (void) splx(s);
+ ISP_UNLOCK(isp);
if (error) {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
} else {
@@ -1463,9 +1482,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
#endif
case XPT_SCSI_IO:
- s = splcam();
+ ISP_LOCK(isp);
error = isp_control(isp, ISPCTL_ABORT_CMD, ccb);
- (void) splx(s);
+ ISP_UNLOCK(isp);
if (error) {
ccb->ccb_h.status = CAM_UA_ABORT;
} else {
@@ -1483,7 +1502,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
cts = &ccb->cts;
tgt = cts->ccb_h.target_id;
- s = splcam();
+ ISP_LOCK(isp);
if (IS_SCSI(isp)) {
sdparam *sdp = isp->isp_param;
u_int16_t *dptr;
@@ -1562,7 +1581,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
sdp->isp_devparam[tgt].dev_update = 1;
isp->isp_update |= (1 << bus);
}
- (void) splx(s);
+ ISP_UNLOCK(isp);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -1592,12 +1611,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
sdp += bus;
if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) {
- s = splcam();
+ ISP_LOCK(isp);
sdp->isp_devparam[tgt].dev_refresh = 1;
isp->isp_update |= (1 << bus);
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS,
NULL);
- (void) splx(s);
+ ISP_UNLOCK(isp);
dval = sdp->isp_devparam[tgt].cur_dflags;
oval = sdp->isp_devparam[tgt].cur_offset;
pval = sdp->isp_devparam[tgt].cur_period;
@@ -1607,7 +1626,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
pval = sdp->isp_devparam[tgt].sync_period;
}
- s = splcam();
+ ISP_LOCK(isp);
cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
if (dval & DPARM_DISC) {
@@ -1631,7 +1650,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
CCB_TRANS_SYNC_RATE_VALID |
CCB_TRANS_SYNC_OFFSET_VALID;
}
- splx(s);
+ ISP_UNLOCK(isp);
if (bootverbose || isp->isp_dblev >= 3)
printf("%s: %d.%d get %s period 0x%x offset "
"0x%x flags 0x%x\n", isp->isp_name, bus,
@@ -1674,9 +1693,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
}
case XPT_RESET_BUS: /* Reset the specified bus */
bus = cam_sim_bus(sim);
- s = splcam();
+ ISP_LOCK(isp);
error = isp_control(isp, ISPCTL_RESET_BUS, &bus);
- (void) splx(s);
+ ISP_UNLOCK(isp);
if (error)
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
else {
OpenPOWER on IntegriCloud