diff --git a/sys/dev/isci/isci.h b/sys/dev/isci/isci.h index 66a0330c4bd..70ba16afd3c 100644 --- a/sys/dev/isci/isci.h +++ b/sys/dev/isci/isci.h @@ -122,6 +122,7 @@ struct ISCI_CONTROLLER SCI_CONTROLLER_HANDLE_T scif_controller_handle; struct ISCI_DOMAIN domain[SCI_MAX_DOMAINS]; BOOL is_started; + BOOL has_been_scanned; uint32_t initial_discovery_mask; BOOL is_frozen; uint8_t *remote_device_memory; diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c index f2409289e4b..38d91acec7d 100644 --- a/sys/dev/isci/isci_controller.c +++ b/sys/dev/isci/isci_controller.c @@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include + #include #include @@ -300,6 +303,16 @@ SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller) TUNABLE_INT_FETCH("hw.isci.io_shortage", &io_shortage); controller->sim_queue_depth += io_shortage; + /* Attach to CAM using xpt_bus_register now, then immediately freeze + * the simq. It will get released later when initial domain discovery + * is complete. + */ + controller->has_been_scanned = FALSE; + mtx_lock(&controller->lock); + isci_controller_attach_to_cam(controller); + xpt_freeze_simq(controller->sim, 1); + mtx_unlock(&controller->lock); + return (scif_controller_initialize(controller->scif_controller_handle)); } @@ -441,13 +454,13 @@ void isci_controller_start(void *controller_handle) void isci_controller_domain_discovery_complete( struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain) { - if (isci_controller->sim == NULL) + if (!isci_controller->has_been_scanned) { - /* Controller has not been attached to CAM yet. We'll clear + /* Controller has not been scanned yet. We'll clear * the discovery bit for this domain, then check if all bits * are now clear. That would indicate that all domains are - * done with discovery and we can then attach the controller - * to CAM. + * done with discovery and we can then proceed with initial + * scan. */ isci_controller->initial_discovery_mask &= @@ -457,7 +470,25 @@ void isci_controller_domain_discovery_complete( struct isci_softc *driver = isci_controller->isci; uint8_t next_index = isci_controller->index + 1; - isci_controller_attach_to_cam(isci_controller); + isci_controller->has_been_scanned = TRUE; + + /* Unfreeze simq to allow initial scan to proceed. */ + xpt_release_simq(isci_controller->sim, TRUE); + +#if __FreeBSD_version < 800000 + /* When driver is loaded after boot, we need to + * explicitly rescan here for versions <8.0, because + * CAM only automatically scans new buses at boot + * time. + */ + union ccb *ccb = xpt_alloc_ccb_nowait(); + + xpt_create_path(&ccb->ccb_h.path, xpt_periph, + cam_sim_path(isci_controller->sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); + + xpt_rescan(ccb); +#endif if (next_index < driver->controller_count) { /* There are more controllers that need to diff --git a/sys/dev/isci/isci_remote_device.c b/sys/dev/isci/isci_remote_device.c index 2388dae39ba..d22b4d4abff 100644 --- a/sys/dev/isci/isci_remote_device.c +++ b/sys/dev/isci/isci_remote_device.c @@ -74,13 +74,12 @@ scif_cb_remote_device_ready(SCI_CONTROLLER_HANDLE_T controller, isci_controller->remote_device[device_index] = isci_remote_device; - if (isci_controller->sim != NULL) { - /* The sim object is not NULL, meaning we have attached - * the controller to CAM already. In that case, create - * a CCB to instruct CAM to rescan this device. - * If the sim object is NULL, this device will get - * scanned as part of the initial scan when the - * controller is attached to CAM. + if (isci_controller->has_been_scanned) { + /* The sim object has been scanned at least once + * already. In that case, create a CCB to instruct + * CAM to rescan this device. + * If the sim object has not been scanned, this device + * will get scanned as part of the initial scan. */ union ccb *ccb = xpt_alloc_ccb_nowait();