Checkpoint of work in progress in cleaning up target mode. It actually

seems to work well in RELENG_4. However, 5.X locking foo means that I'll
have to do some quick redesign.

Add ioctl handlers for ISP_GETROLE and ISP_SETROLE ioctls.
This commit is contained in:
Matt Jacob 2004-02-07 03:47:33 +00:00
parent 2cd44270e5
commit 746e9c8540

View File

@ -248,7 +248,7 @@ static int
ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
{
struct ispsoftc *isp;
int retval = ENOTTY;
int nr, retval = ENOTTY;
isp = isplist;
while (isp) {
@ -304,6 +304,19 @@ ispioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
retval = 0;
break;
}
case ISP_GETROLE:
*(int *)addr = isp->isp_role;
retval = 0;
break;
case ISP_SETROLE:
nr = *(int *)addr;
if (nr & ~(ISP_ROLE_INITIATOR|ISP_ROLE_TARGET)) {
retval = EINVAL;
break;
}
*(int *)addr = isp->isp_role;
isp->isp_role = nr;
/* FALLTHROUGH */
case ISP_RESETHBA:
ISP_LOCK(isp);
isp_reinit(isp);
@ -624,9 +637,17 @@ isp_psema_sig_rqe(struct ispsoftc *isp, int bus)
return (-1);
}
#else
/*
* It's not allowed for us to use tsleep any more because
* a caller might have a non-sleepable lock held.
*/
#if 0
if (tsleep(&isp->isp_osinfo.tgtcv0[bus], PZERO, "cv_isp", 0)) {
return (-1);
}
#else
return (-1);
#endif
#endif
isp->isp_osinfo.tmflags[bus] |= TM_BUSY;
}
@ -668,6 +689,7 @@ isp_vsema_rqe(struct ispsoftc *isp, int bus)
cv_signal(&isp->isp_osinfo.tgtcv0[bus]);
#else
cv_signal(&isp->isp_osinfo.tgtcv0[bus]);
/* wakeup(&isp->isp_osinfo.tgtcv0[bus]); */
#endif
}
isp->isp_osinfo.tmflags[bus] &= ~TM_BUSY;
@ -770,11 +792,11 @@ destroy_lun_state(struct ispsoftc *isp, tstate_t *tptr)
static void
isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
{
const char lfmt[] = "Lun now %sabled for target mode on channel %d";
const char lfmt[] = "lun %d now %sabled for target mode on channel %d";
struct ccb_en_lun *cel = &ccb->cel;
tstate_t *tptr;
u_int16_t rstat;
int bus, cmd, av, wildcard;
int bus, cmd, av, wildcard, tm_on;
lun_id_t lun;
target_id_t tgt;
@ -802,11 +824,17 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
return;
}
} else {
/*
* There's really no point in doing this yet w/o multi-tid
* capability. Even then, it's problematic.
*/
#if 0
if (tgt != CAM_TARGET_WILDCARD &&
tgt != FCPARAM(isp)->isp_iid) {
ccb->ccb_h.status = CAM_TID_INVALID;
return;
}
#endif
/*
* This is as a good a place as any to check f/w capabilities.
*/
@ -823,6 +851,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
isp_prt(isp, ISP_LOGERR,
"firmware not SCCLUN capable");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
return;
}
}
@ -837,6 +867,8 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
wildcard = 0;
}
tm_on = (isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) != 0;
/*
* Next check to see whether this is a target/lun wildcard action.
*
@ -884,7 +916,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
* enabled/disabled with respect to target mode.
*/
av = bus << 31;
if (cel->enable && !(isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED)) {
if (cel->enable && tm_on == 0) {
av |= ENABLE_TARGET_FLAG;
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
if (av) {
@ -899,8 +931,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
isp->isp_osinfo.tmflags[bus] |= TM_TMODE_ENABLED;
isp_prt(isp, ISP_LOGINFO,
"Target Mode enabled on channel %d", bus);
} else if (cel->enable == 0 &&
(isp->isp_osinfo.tmflags[bus] & TM_TMODE_ENABLED) && wildcard) {
} else if (cel->enable == 0 && tm_on && wildcard) {
if (are_any_luns_enabled(isp, bus)) {
ccb->ccb_h.status = CAM_SCSI_BUSY;
return;
@ -1048,7 +1079,6 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
goto out;
}
isp->isp_osinfo.tmflags[bus] &= ~TM_TMODE_ENABLED;
xpt_print_path(ccb->ccb_h.path);
isp_prt(isp, ISP_LOGINFO,
"Target Mode disabled on channel %d", bus);
}
@ -1066,8 +1096,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
if (cel->enable)
destroy_lun_state(isp, tptr);
} else {
xpt_print_path(ccb->ccb_h.path);
isp_prt(isp, ISP_LOGINFO, lfmt,
isp_prt(isp, ISP_LOGINFO, lfmt, lun,
(cel->enable) ? "en" : "dis", bus);
rls_lun_statep(isp, tptr);
if (cel->enable == 0) {
@ -1083,28 +1112,46 @@ isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb)
tstate_t *tptr;
struct ccb_hdr_slist *lp;
struct ccb_hdr *curelm;
int found;
int found, *ctr;
union ccb *accb = ccb->cab.abort_ccb;
isp_prt(isp, ISP_LOGTDEBUG0, "aborting ccb %p", accb);
if (accb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
int badpath = 0;
if (IS_FC(isp) && (accb->ccb_h.target_id !=
((fcparam *) isp->isp_param)->isp_loopid)) {
return (CAM_PATH_INVALID);
badpath = 1;
} else if (IS_SCSI(isp) && (accb->ccb_h.target_id !=
((sdparam *) isp->isp_param)->isp_initiator_id)) {
badpath = 1;
}
if (badpath) {
/*
* Being restrictive about target ids is really about
* making sure we're aborting for the right multi-tid
* path. This doesn't really make much sense at present.
*/
#if 0
return (CAM_PATH_INVALID);
#endif
}
}
tptr = get_lun_statep(isp, XS_CHANNEL(ccb), accb->ccb_h.target_lun);
if (tptr == NULL) {
isp_prt(isp, ISP_LOGTDEBUG0,
"isp_abort_tgt_ccb: can't get statep");
return (CAM_PATH_INVALID);
}
if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
lp = &tptr->atios;
ctr = &tptr->atio_count;
} else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
lp = &tptr->inots;
ctr = &tptr->inot_count;
} else {
rls_lun_statep(isp, tptr);
isp_prt(isp, ISP_LOGTDEBUG0,
"isp_abort_tgt_ccb: bad func %d\n", accb->ccb_h.func_code);
return (CAM_UA_ABORT);
}
curelm = SLIST_FIRST(lp);
@ -1128,9 +1175,13 @@ isp_abort_tgt_ccb(struct ispsoftc *isp, union ccb *ccb)
}
rls_lun_statep(isp, tptr);
if (found) {
*ctr--;
accb->ccb_h.status = CAM_REQ_ABORTED;
xpt_done(accb);
return (CAM_REQ_CMP);
}
isp_prt(isp, ISP_LOGTDEBUG0,
"isp_abort_tgt_ccb: CCB %p not found\n", ccb);
return (CAM_PATH_INVALID);
}
@ -1422,6 +1473,12 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
tptr = get_lun_statep(isp, bus, aep->at_lun);
if (tptr == NULL) {
tptr = get_lun_statep(isp, bus, CAM_LUN_WILDCARD);
if (tptr == NULL) {
isp_endcmd(isp, aep,
SCSI_STATUS_CHECK_COND | ECMD_SVALID |
(0x5 << 12) | (0x25 << 16), 0);
return (0);
}
iswildcard = 1;
} else {
iswildcard = 0;
@ -1463,6 +1520,9 @@ isp_handle_platform_atio(struct ispsoftc *isp, at_entry_t *aep)
return (0);
}
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
aep->at_lun, tptr->atio_count);
if (iswildcard) {
atiop->ccb_h.target_id = aep->at_tgt;
atiop->ccb_h.target_lun = aep->at_lun;
@ -1533,8 +1593,15 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
}
tptr = get_lun_statep(isp, 0, lun);
if (tptr == NULL) {
isp_prt(isp, ISP_LOGWARN, "no state pointer for lun %d", lun);
isp_prt(isp, ISP_LOGTDEBUG0,
"[0x%x] no state pointer for lun %d", aep->at_rxid, lun);
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
if (tptr == NULL) {
isp_endcmd(isp, aep,
SCSI_STATUS_CHECK_COND | ECMD_SVALID |
(0x5 << 12) | (0x25 << 16), 0);
return (0);
}
}
if (tptr == NULL) {
@ -1569,6 +1636,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
atp = isp_get_atpd(isp, 0);
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
if (atiop == NULL || atp == NULL) {
/*
* Because we can't autofeed sense data back with
* a command for parallel SCSI, we can't give back
@ -1589,7 +1657,7 @@ isp_handle_platform_atio2(struct ispsoftc *isp, at2_entry_t *aep)
atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO2 lun %d, count now %d",
isp_prt(isp, ISP_LOGTDEBUG0, "Take FREE ATIO lun %d, count now %d",
lun, tptr->atio_count);
if (tptr == &isp->isp_osinfo.tsdflt[0]) {
@ -1782,8 +1850,12 @@ isp_handle_platform_notify_fc(struct ispsoftc *isp, in_fcentry_t *inp)
inot = (struct ccb_immed_notify *)
SLIST_FIRST(&tptr->inots);
if (inot) {
tptr->inot_count--;
SLIST_REMOVE_HEAD(&tptr->inots,
sim_links.sle);
isp_prt(isp, ISP_LOGTDEBUG0,
"Take FREE INOT count now %d",
tptr->inot_count);
}
}
isp_prt(isp, ISP_LOGWARN,
@ -2177,15 +2249,19 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
*/
tptr->atio_count++;
isp_prt(isp, ISP_LOGTDEBUG0,
"Put FREE ATIO2, lun %d, count now %d",
"Put FREE ATIO, lun %d, count now %d",
ccb->ccb_h.target_lun, tptr->atio_count);
SLIST_INSERT_HEAD(&tptr->atios, &ccb->ccb_h,
sim_links.sle);
} else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) {
tptr->inot_count++;
isp_prt(isp, ISP_LOGTDEBUG0,
"Put FREE INOT, lun %d, count now %d",
ccb->ccb_h.target_lun, tptr->inot_count);
SLIST_INSERT_HEAD(&tptr->inots, &ccb->ccb_h,
sim_links.sle);
} else {
;
isp_prt(isp, ISP_LOGWARN, "Got Notify ACK");;
}
rls_lun_statep(isp, tptr);
ccb->ccb_h.status = CAM_REQ_INPROG;