summaryrefslogtreecommitdiffstats
path: root/sys/dev/isp/isp_freebsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r--sys/dev/isp/isp_freebsd.c64
1 files changed, 35 insertions, 29 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 575b45c..0ca540f 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -115,7 +115,7 @@ isp_role_sysctl(SYSCTL_HANDLER_ARGS)
}
/* Actually change the role. */
- error = isp_fc_change_role(isp, chan, value);
+ error = isp_control(isp, ISPCTL_CHANGE_ROLE, chan, value);
ISP_UNLOCK(isp);
return (error);
}
@@ -474,18 +474,14 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
retval = EINVAL;
break;
}
- *(int *)addr = FCPARAM(isp, chan)->role;
-#ifdef ISP_INTERNAL_TARGET
ISP_LOCK(isp);
- retval = isp_fc_change_role(isp, chan, nr);
- ISP_UNLOCK(isp);
-#else
- FCPARAM(isp, chan)->role = nr;
-#endif
+ *(int *)addr = FCPARAM(isp, chan)->role;
} else {
+ ISP_LOCK(isp);
*(int *)addr = SDPARAM(isp, chan)->role;
- SDPARAM(isp, chan)->role = nr;
}
+ retval = isp_control(isp, ISPCTL_CHANGE_ROLE, chan, nr);
+ ISP_UNLOCK(isp);
retval = 0;
break;
@@ -2969,9 +2965,9 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
}
if (atp == NULL) {
/*
- * In case of target mode disable at least ISP2532 return
- * invalid zero ct_rxid value. Try to workaround that using
- * tag_id from the CCB, pointed by valid ct_syshandle.
+ * XXX: isp_clear_commands() generates fake CTIO with zero
+ * ct_rxid value, filling only ct_syshandle. Workaround
+ * that using tag_id from the CCB, pointed by ct_syshandle.
*/
atp = isp_find_atpd(isp, tptr, ccb->csio.tag_id);
}
@@ -4943,6 +4939,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
isp = (ispsoftc_t *)cam_sim_softc(sim);
mtx_assert(&isp->isp_lock, MA_OWNED);
+ isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
+ ISP_PCMD(ccb) = NULL;
if (isp->isp_state != ISP_RUNSTATE && ccb->ccb_h.func_code == XPT_SCSI_IO) {
isp_init(isp);
@@ -4950,15 +4948,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
/*
* Lie. Say it was a selection timeout.
*/
- ccb->ccb_h.status = CAM_SEL_TIMEOUT | CAM_DEV_QFRZN;
- xpt_freeze_devq(ccb->ccb_h.path, 1);
- xpt_done(ccb);
+ ccb->ccb_h.status = CAM_SEL_TIMEOUT;
+ isp_done((struct ccb_scsiio *) ccb);
return;
}
isp->isp_state = ISP_RUNSTATE;
}
- isp_prt(isp, ISP_LOGDEBUG2, "isp_action code %x", ccb->ccb_h.func_code);
- ISP_PCMD(ccb) = NULL;
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO: /* Execute the requested I/O operation */
@@ -4969,7 +4964,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
if ((ccb->ccb_h.flags & CAM_CDB_PHYS) != 0) {
ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
+ isp_done((struct ccb_scsiio *) ccb);
break;
}
}
@@ -4992,6 +4987,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
isp_prt(isp, ISP_LOGWARN, "out of PCMDs");
cam_freeze_devq(ccb->ccb_h.path);
cam_release_devq(ccb->ccb_h.path, RELSIM_RELEASE_AFTER_TIMEOUT, 0, 250, 0);
+ ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb);
break;
}
@@ -5024,10 +5020,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
} else {
isp_prt(isp, ISP_LOGDEBUG0, "%d.%d downtime (%d) > lim (%d)", XS_TGT(ccb), XS_LUN(ccb), ISP_FC_PC(isp, bus)->loop_down_time, lim);
}
- ccb->ccb_h.status = CAM_SEL_TIMEOUT|CAM_DEV_QFRZN;
- xpt_freeze_devq(ccb->ccb_h.path, 1);
- isp_free_pcmd(isp, ccb);
- xpt_done(ccb);
+ ccb->ccb_h.status = CAM_SEL_TIMEOUT;
+ isp_done((struct ccb_scsiio *) ccb);
break;
}
isp_prt(isp, ISP_LOGDEBUG0, "%d.%d retry later", XS_TGT(ccb), XS_LUN(ccb));
@@ -5480,7 +5474,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ISP_SET_PC(isp, bus, tm_enabled, 0);
ISP_SET_PC(isp, bus, tm_luns_enabled, 0);
#endif
- if (isp_fc_change_role(isp, bus, newrole) != 0) {
+ if (isp_control(isp, ISPCTL_CHANGE_ROLE,
+ bus, newrole) != 0) {
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
xpt_done(ccb);
break;
@@ -5646,7 +5641,7 @@ isp_done(XS_T *sccb)
* gone. If it reappears, we'll need to issue a
* rescan.
*/
- if (hdlidx > 0 && hdlidx < MAX_FC_TARG)
+ if (hdlidx >= 0 && hdlidx < MAX_FC_TARG)
fcp->portdb[hdlidx].reported_gone = 1;
}
if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
@@ -5659,16 +5654,18 @@ isp_done(XS_T *sccb)
xpt_print(sccb->ccb_h.path, "cam completion status 0x%x\n", sccb->ccb_h.status);
}
- if (callout_active(&PISP_PCMD(sccb)->wdog))
- callout_stop(&PISP_PCMD(sccb)->wdog);
- isp_free_pcmd(isp, (union ccb *) sccb);
+ if (ISP_PCMD(sccb)) {
+ if (callout_active(&PISP_PCMD(sccb)->wdog))
+ callout_stop(&PISP_PCMD(sccb)->wdog);
+ isp_free_pcmd(isp, (union ccb *) sccb);
+ }
xpt_done((union ccb *) sccb);
}
void
isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
{
- int bus;
+ int bus, now;
static const char prom0[] = "Chan %d PortID 0x%06x handle 0x%x %s %s WWPN 0x%08x%08x";
static const char prom2[] = "Chan %d PortID 0x%06x handle 0x%x %s %s tgt %u WWPN 0x%08x%08x";
char buf[64];
@@ -5909,6 +5906,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
va_start(ap, cmd);
bus = va_arg(ap, int);
lp = va_arg(ap, fcportdb_t *);
+ now = va_arg(ap, int);
va_end(ap);
fc = ISP_FC_PC(isp, bus);
/*
@@ -5921,7 +5919,15 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...)
*
*/
isp_gen_role_str(buf, sizeof (buf), lp->prli_word3);
- if (lp->dev_map_idx && lp->announced == 0) {
+ if (lp->dev_map_idx && lp->announced == 0 && now) {
+ lp->announced = 1;
+ tgt = lp->dev_map_idx - 1;
+ FCPARAM(isp, bus)->isp_dev_map[tgt] = 0;
+ lp->dev_map_idx = 0;
+ isp_make_gone(isp, lp, bus, tgt);
+ isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, buf, "gone at", tgt, (uint32_t) (lp->port_wwn >> 32), (uint32_t) lp->port_wwn);
+ isp_fcp_reset_crn(fc, tgt, /*tgt_set*/ 1);
+ } else if (lp->dev_map_idx && lp->announced == 0) {
lp->announced = 1;
lp->state = FC_PORTDB_STATE_ZOMBIE;
lp->gone_timer = ISP_FC_PC(isp, bus)->gone_device_time;
OpenPOWER on IntegriCloud