Allow fibre channel 'bus resets' to go through. Handle Loop Down/Loop Up

events by freezing/unfreezing the simq- nice to have such control at this
level! Do bus resets in attach layer (non-CAM defined code).
This commit is contained in:
Matt Jacob 1999-02-09 01:08:38 +00:00
parent 3c688670f5
commit 2b05293160
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=43790

View file

@ -1,5 +1,5 @@
/* $Id: isp_freebsd.c,v 1.10 1998/12/28 19:22:26 mjacob Exp $ */
/* release_01_29_99 */
/* $Id: isp_freebsd.c,v 1.11 1999/01/30 07:29:00 mjacob Exp $ */
/* release_02_05_99 */
/*
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
*
@ -346,8 +346,10 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
} else {
*dptr &= ~DPARM_SYNC;
}
IDPRINTF(3, ("%s: target %d new dev_flags 0x%x\n",
isp->isp_name, tgt,
IDPRINTF(3, ("%s: set target %d period %d offset %d "
"dev_flags 0x%x\n", isp->isp_name, tgt,
sdp->isp_devparam[tgt].sync_period,
sdp->isp_devparam[tgt].sync_offset,
sdp->isp_devparam[tgt].dev_flags));
s = splcam();
sdp->isp_devparam[tgt].dev_update = 1;
@ -450,18 +452,16 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
break;
}
case XPT_RESET_BUS: /* Reset the specified bus */
if (isp->isp_type & ISP_HA_FC) {
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
}
s = splcam();
error = isp_control(isp, ISPCTL_RESET_BUS, NULL);
(void) splx(s);
if (error)
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
else
else {
if (isp->isp_path != NULL)
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
ccb->ccb_h.status = CAM_REQ_CMP;
}
xpt_done(ccb);
break;
@ -548,6 +548,10 @@ isp_done(struct ccb_scsiio *sccb)
}
}
if (isp->isp_osinfo.simqfrozen) {
xpt_print_path(sccb->ccb_h.path);
printf("isp_done releasing SIMQ\n");
sccb->ccb_h.status |= CAM_RELEASE_SIMQ;
isp->isp_osinfo.simqfrozen = 0;
}
@ -568,6 +572,29 @@ isp_async(isp, cmd, arg)
{
int rv = 0;
switch (cmd) {
case ISPASYNC_LOOP_DOWN:
if (isp->isp_path) {
/*
* We can get multiple LOOP downs, so only count one.
*/
if (isp->isp_osinfo.simqfrozen == 0) {
xpt_freeze_simq(isp->isp_sim, 1);
isp->isp_osinfo.simqfrozen = 1;
xpt_print_path(isp->isp_path);
printf("freezing SIMQ until loop comes up\n");
}
}
break;
case ISPASYNC_LOOP_UP:
if (isp->isp_path) {
xpt_print_path(isp->isp_path);
if (isp->isp_osinfo.simqfrozen) {
isp->isp_osinfo.simqfrozen = 0;
printf("releasing frozen SIMQ\n");
xpt_release_simq(isp->isp_sim, 1);
}
}
break;
case ISPASYNC_NEW_TGT_PARAMS:
if (isp->isp_type & ISP_HA_SCSI) {
int flags, tgt;
@ -603,9 +630,9 @@ isp_async(isp, cmd, arg)
neg.valid |= CCB_TRANS_SYNC_RATE_VALID |
CCB_TRANS_SYNC_OFFSET_VALID;
}
xpt_print_path(tmppath);
printf("new target params period %d offset %d\n",
neg.sync_period, neg.sync_offset);
IDPRINTF(3, ("%s: new params target %d period %d "
"offset %d flags 0x%x\n", isp->isp_name, tgt,
neg.sync_period, neg.sync_offset, flags));
xpt_setup_ccb(&neg.ccb_h, tmppath, 1);
xpt_async(AC_TRANSFER_NEG, tmppath, &neg);
xpt_free_path(tmppath);
@ -662,6 +689,9 @@ isp_attach(struct ispsoftc *isp)
((sdparam *)isp->isp_param)->isp_initiator_id;
scbus->maxtarg = MAX_TARGETS-1;
}
(void) isp_control(isp, ISPCTL_RESET_BUS, NULL);
/*
* Prepare the scsibus_data area for the upperlevel scsi code.
*/