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.
This commit is contained in:
Matt Jacob 2000-07-04 01:05:43 +00:00
parent df9d46b6d9
commit f6e75de230

View File

@ -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 {