--- sys/conf/options 2005/10/14 18:25:27 +++ sys/conf/options 2005/11/20 13:36:10 @@ -305,6 +305,7 @@ # Options used only in dev/isp/* ISP_TARGET_MODE opt_isp.h ISP_FW_CRASH_DUMP opt_isp.h +ISP_MP_FRIENDLY opt_isp.h # Options used in the 'ata' ATA/ATAPI driver ATA_STATIC_ID opt_ata.h --- sys/dev/isp/isp.c 2005/10/29 02:50:32 +++ sys/dev/isp/isp.c 2005/11/20 13:36:10 @@ -4182,7 +4182,7 @@ break; case ASYNC_LOOP_UP: - isp->isp_sendmarker = 1; + isp->isp_sendmarker |= (1 << bus); FCPARAM(isp)->isp_fwstate = FW_CONFIG_WAIT; FCPARAM(isp)->isp_loopstate = LOOP_LIP_RCVD; isp_mark_getpdb_all(isp); --- sys/dev/isp/isp_freebsd.c 2005/10/29 02:50:32 +++ sys/dev/isp/isp_freebsd.c 2005/11/20 13:39:06 @@ -206,6 +206,9 @@ (void) make_dev(&isp_cdevsw, device_get_unit(isp->isp_dev), UID_ROOT, GID_OPERATOR, 0600, "%s", device_get_nameunit(isp->isp_dev)); +#ifdef ISP_MP_FRIENDLY + callout_init(&isp->isp_osinfo.callout, 0); +#endif if (isp->isp_role != ISP_ROLE_NONE) { isp->isp_state = ISP_RUNSTATE; ENABLE_INTS(isp); @@ -2776,6 +2779,51 @@ } } +#ifdef ISP_MP_FRIENDLY +static void +xptdone(struct cam_periph *periph, union ccb *done_ccb) +{ + + /* Caller will release the CCB */ + wakeup(&done_ccb->ccb_h.cbfcnp); +} + +static void +isp_rescan(void *arg) +{ + struct ispsoftc *isp; + union ccb *ccb, inccb; + int bus; + + isp = arg; + ccb = xpt_alloc_ccb(); + for (bus = 0; bus < 2; bus++) { + if (((1 << bus) & isp->isp_sendmarker) == 0) + continue; + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, bus, + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + break; + } + isp_prt(isp, ISP_LOGINFO, "Rescanning bus %d", bus); + inccb.ccb_h.func_code = XPT_SCAN_BUS; + inccb.ccb_h.path_id = bus; + inccb.ccb_h.target_id = CAM_TARGET_WILDCARD; + inccb.ccb_h.target_lun = CAM_LUN_WILDCARD; + inccb.crcn.flags = CAM_FLAG_NONE; + inccb.ccb_h.pinfo.priority = 5; + xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, + inccb.ccb_h.pinfo.priority); + xpt_merge_ccb(ccb, &inccb); + ccb->ccb_h.cbfcnp = xptdone; + cam_periph_runccb(ccb, NULL, 0, 0, NULL); + xpt_free_path(ccb->ccb_h.path); + } + xpt_free_ccb(ccb); +} + +static int loop_was_down = 0; +#endif /* ISP_MP_FRIENDLY */ + int isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) { @@ -2900,17 +2948,34 @@ break; case ISPASYNC_LOOP_DOWN: if (isp->isp_path) { +#ifdef ISP_MP_FRIENDLY + ISPLOCK_2_CAMLOCK(isp); + xpt_bus_deregister(cam_sim_path(isp->isp_sim)); + xpt_free_path(isp->isp_path); + cam_sim_free(isp->isp_sim, TRUE); + CAMLOCK_2_ISPLOCK(isp); + loop_was_down = 1; +#else isp_freeze_loopdown(isp, "ISPASYNC_LOOP_DOWN"); +#endif } isp_prt(isp, ISP_LOGINFO, "Loop DOWN"); break; case ISPASYNC_LOOP_UP: +#ifdef ISP_MP_FRIENDLY + if (!loop_was_down) + break; + loop_was_down = 0; + callout_stop(&isp->isp_osinfo.callout); + callout_reset(&isp->isp_osinfo.callout, 15 * hz, isp_rescan, isp); +#else /* * Now we just note that Loop has come up. We don't * actually do anything because we're waiting for a * Change Notify before activating the FC cleanup * thread to look at the state of the loop again. */ +#endif isp_prt(isp, ISP_LOGINFO, "Loop UP"); break; case ISPASYNC_PROMENADE: --- sys/dev/isp/isp_freebsd.h 2005/05/29 04:45:51 +++ sys/dev/isp/isp_freebsd.h 2005/11/20 13:36:10 @@ -47,10 +47,11 @@ #include #include -#include #include +#include #include #include +#include #include #include #include @@ -140,6 +141,7 @@ struct mtx lock; struct cv kthread_cv; struct proc *kproc; + struct callout callout; bus_dma_tag_t cdmat; bus_dmamap_t cdmap; #define isp_cdmat isp_osinfo.cdmat