diff options
Diffstat (limited to 'sys/dev/isp/isp_freebsd.c')
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 64 |
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; |