diff options
author | mjacob <mjacob@FreeBSD.org> | 2000-07-04 01:05:43 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2000-07-04 01:05:43 +0000 |
commit | e0a8dae616ce837fcb0a631c17d35ef5deb6d5e1 (patch) | |
tree | f020cb7e6d3f0ba92b524b376f2d9c90991597ef | |
parent | 22ee60424c34491a4fa0ac2e999919c58366bc13 (diff) | |
download | FreeBSD-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.c | 163 |
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 { |