On Fri, 2019-11-22 at 18:39 +0000, Alexander Motin wrote: > Author: mav > Date: Fri Nov 22 18:39:51 2019 > New Revision: 355010 > URL: https://svnweb.freebsd.org/changeset/base/355010 > > Log: > Make CAM use root_mount_hold_token() to delay boot. > > Before this change CAM used config_intrhook_establish() for this > purpose, > but that approach does not allow to delay it again after releasing > once. > > USB stack uses root_mount_hold() to delay boot until bus scan is > complete. > But once it is, CAM had no time to scan SCSI bus, registered by > umass(4), > if it already done other scans and called > config_intrhook_disestablish(). > The new approach makes it work smooth, assuming the USB device is > found > during the initial bus scan. Devices appearing on USB bus later > may still > require setting kern.cam.boot_delay, but hopefully those are > minority. > > MFC after: 2 weeks > Sponsored by: iXsystems, Inc. >
This is probably the fix for this PR? https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=144824 -- Ian > Modified: > head/sys/cam/cam_xpt.c > head/sys/cam/scsi/scsi_enc.c > head/sys/cam/scsi/scsi_enc_internal.h > > Modified: head/sys/cam/cam_xpt.c > ===================================================================== > ========= > --- head/sys/cam/cam_xpt.c Fri Nov 22 18:18:36 2019 (r355009) > +++ head/sys/cam/cam_xpt.c Fri Nov 22 18:39:51 2019 (r355010) > @@ -99,13 +99,6 @@ MALLOC_DEFINE(M_CAMDEV, "CAM DEV", "CAM devices"); > MALLOC_DEFINE(M_CAMCCB, "CAM CCB", "CAM CCBs"); > MALLOC_DEFINE(M_CAMPATH, "CAM path", "CAM paths"); > > -/* Object for defering XPT actions to a taskqueue */ > -struct xpt_task { > - struct task task; > - void *data1; > - uintptr_t data2; > -}; > - > struct xpt_softc { > uint32_t xpt_generation; > > @@ -129,10 +122,10 @@ struct xpt_softc { > TAILQ_HEAD(,cam_eb) xpt_busses; > u_int bus_generation; > > - struct intr_config_hook xpt_config_hook; > - > int boot_delay; > struct callout boot_callout; > + struct task boot_task; > + struct root_hold_token xpt_rootmount; > > struct mtx xpt_topo_lock; > struct mtx xpt_lock; > @@ -273,6 +266,7 @@ static struct cam_et* > static struct cam_ed* > xpt_find_device(struct cam_et *target, lun_id_t > lun_id); > static void xpt_config(void *arg); > +static void xpt_hold_boot_locked(void); > static int xpt_schedule_dev(struct camq *queue, cam_pinfo > *dev_pinfo, > u_int32_t new_priority); > static xpt_devicefunc_t xptpassannouncefunc; > @@ -881,7 +875,7 @@ xpt_rescan(union ccb *ccb) > } > } > TAILQ_INSERT_TAIL(&xsoftc.ccb_scanq, &ccb->ccb_h, > sim_links.tqe); > - xsoftc.buses_to_config++; > + xpt_hold_boot_locked(); > wakeup(&xsoftc.ccb_scanq); > xpt_unlock_buses(); > } > @@ -913,6 +907,7 @@ xpt_init(void *dummy) > */ > xsoftc.boot_delay = CAM_BOOT_DELAY; > #endif > + > /* > * The xpt layer is, itself, the equivalent of a SIM. > * Allow 16 ccbs in the ccb pool for it. This should > @@ -979,14 +974,11 @@ xpt_init(void *dummy) > "- failing attach\n"); > return (ENOMEM); > } > + > /* > * Register a callback for when interrupts are enabled. > */ > - xsoftc.xpt_config_hook.ich_func = xpt_config; > - if (config_intrhook_establish(&xsoftc.xpt_config_hook) != 0) { > - printf("xpt_init: config_intrhook_establish failed " > - "- failing attach\n"); > - } > + config_intrhook_oneshot(xpt_config, NULL); > > return (0); > } > @@ -5148,6 +5140,10 @@ xpt_stop_tags(struct cam_path *path) > xpt_action((union ccb *)&crs); > } > > +/* > + * Assume all possible buses are detected by this time, so allow > boot > + * as soon as they all are scanned. > + */ > static void > xpt_boot_delay(void *arg) > { > @@ -5155,12 +5151,26 @@ xpt_boot_delay(void *arg) > xpt_release_boot(); > } > > +/* > + * Now that all config hooks have completed, start boot_delay timer, > + * waiting for possibly still undetected buses (USB) to appear. > + */ > static void > +xpt_ch_done(void *arg) > +{ > + > + callout_init(&xsoftc.boot_callout, 1); > + callout_reset_sbt(&xsoftc.boot_callout, SBT_1MS * > xsoftc.boot_delay, 0, > + xpt_boot_delay, NULL, 0); > +} > +SYSINIT(xpt_hw_delay, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, > xpt_ch_done, NULL); > + > +/* > + * Now that interrupts are enabled, go find our devices > + */ > +static void > xpt_config(void *arg) > { > - /* > - * Now that interrupts are enabled, go find our devices > - */ > if (taskqueue_start_threads(&xsoftc.xpt_taskq, 1, PRIBIO, "CAM > taskq")) > printf("xpt_config: failed to create taskqueue > thread.\n"); > > @@ -5179,9 +5189,7 @@ xpt_config(void *arg) > > periphdriver_init(1); > xpt_hold_boot(); > - callout_init(&xsoftc.boot_callout, 1); > - callout_reset_sbt(&xsoftc.boot_callout, SBT_1MS * > xsoftc.boot_delay, 0, > - xpt_boot_delay, NULL, 0); > + > /* Fire up rescan thread. */ > if (kproc_kthread_add(xpt_scanner_thread, NULL, &cam_proc, > NULL, 0, 0, > "cam", "scanner")) { > @@ -5190,31 +5198,38 @@ xpt_config(void *arg) > } > > void > +xpt_hold_boot_locked(void) > +{ > + > + if (xsoftc.buses_to_config++ == 0) > + root_mount_hold_token("CAM", &xsoftc.xpt_rootmount); > +} > + > +void > xpt_hold_boot(void) > { > + > xpt_lock_buses(); > - xsoftc.buses_to_config++; > + xpt_hold_boot_locked(); > xpt_unlock_buses(); > } > > void > xpt_release_boot(void) > { > - xpt_lock_buses(); > - xsoftc.buses_to_config--; > - if (xsoftc.buses_to_config == 0 && xsoftc.buses_config_done == > 0) { > - struct xpt_task *task; > > - xsoftc.buses_config_done = 1; > - xpt_unlock_buses(); > - /* Call manually because we don't have any buses */ > - task = malloc(sizeof(struct xpt_task), M_CAMXPT, > M_NOWAIT); > - if (task != NULL) { > - TASK_INIT(&task->task, 0, > xpt_finishconfig_task, task); > - taskqueue_enqueue(taskqueue_thread, &task- > >task); > - } > - } else > - xpt_unlock_buses(); > + xpt_lock_buses(); > + if (--xsoftc.buses_to_config == 0) { > + if (xsoftc.buses_config_done == 0) { > + xsoftc.buses_config_done = 1; > + xsoftc.buses_to_config++; > + TASK_INIT(&xsoftc.boot_task, 0, > xpt_finishconfig_task, > + NULL); > + taskqueue_enqueue(taskqueue_thread, > &xsoftc.boot_task); > + } else > + root_mount_rel(&xsoftc.xpt_rootmount); > + } > + xpt_unlock_buses(); > } > > /* > @@ -5252,10 +5267,7 @@ xpt_finishconfig_task(void *context, int > pending) > if (!bootverbose) > xpt_for_all_devices(xptpassannouncefunc, NULL); > > - /* Release our hook so that the boot can continue. */ > - config_intrhook_disestablish(&xsoftc.xpt_config_hook); > - > - free(context, M_CAMXPT); > + xpt_release_boot(); > } > > cam_status > > Modified: head/sys/cam/scsi/scsi_enc.c > ===================================================================== > ========= > --- head/sys/cam/scsi/scsi_enc.c Fri Nov 22 18:18:36 2019 (r355 > 009) > +++ head/sys/cam/scsi/scsi_enc.c Fri Nov 22 18:39:51 2019 (r355 > 010) > @@ -205,10 +205,7 @@ enc_dtor(struct cam_periph *periph) > if (enc->enc_vec.softc_cleanup != NULL) > enc->enc_vec.softc_cleanup(enc); > > - if (enc->enc_boot_hold_ch.ich_func != NULL) { > - config_intrhook_disestablish(&enc->enc_boot_hold_ch); > - enc->enc_boot_hold_ch.ich_func = NULL; > - } > + root_mount_rel(&enc->enc_rootmount); > > ENC_FREE(enc); > } > @@ -835,7 +832,6 @@ enc_daemon(void *arg) > cam_periph_lock(enc->periph); > while ((enc->enc_flags & ENC_FLAG_SHUTDOWN) == 0) { > if (enc->pending_actions == 0) { > - struct intr_config_hook *hook; > > /* > * Reset callout and msleep, or > @@ -848,11 +844,7 @@ enc_daemon(void *arg) > * We've been through our state machine at > least > * once. Allow the transition to userland. > */ > - hook = &enc->enc_boot_hold_ch; > - if (hook->ich_func != NULL) { > - config_intrhook_disestablish(hook); > - hook->ich_func = NULL; > - } > + root_mount_rel(&enc->enc_rootmount); > > callout_reset(&enc->status_updater, 60*hz, > enc_status_updater, enc); > @@ -891,22 +883,6 @@ enc_kproc_init(enc_softc_t *enc) > cam_periph_release(enc->periph); > return (result); > } > - > -/** > - * \brief Interrupt configuration hook callback associated with > - * enc_boot_hold_ch. > - * > - * Since interrupts are always functional at the time of enclosure > - * configuration, there is nothing to be done when the callback > occurs. > - * This hook is only registered to hold up boot processing while > initial > - * eclosure processing occurs. > - * > - * \param arg The enclosure softc, but currently unused in this > callback. > - */ > -static void > -enc_nop_confighook_cb(void *arg __unused) > -{ > -} > > static cam_status > enc_ctor(struct cam_periph *periph, void *arg) > @@ -964,9 +940,7 @@ enc_ctor(struct cam_periph *periph, void *arg) > * present. > */ > if (enc->enc_vec.poll_status != NULL) { > - enc->enc_boot_hold_ch.ich_func = enc_nop_confighook_cb; > - enc->enc_boot_hold_ch.ich_arg = enc; > - config_intrhook_establish(&enc->enc_boot_hold_ch); > + root_mount_hold_token(periph->periph_name, &enc- > >enc_rootmount); > } > > /* > > Modified: head/sys/cam/scsi/scsi_enc_internal.h > ===================================================================== > ========= > --- head/sys/cam/scsi/scsi_enc_internal.h Fri Nov 22 18:18:36 > 2019 (r355009) > +++ head/sys/cam/scsi/scsi_enc_internal.h Fri Nov 22 18:39:51 > 2019 (r355010) > @@ -163,7 +163,7 @@ struct enc_softc { > > struct enc_fsm_state *enc_fsm_states; > > - struct intr_config_hook enc_boot_hold_ch; > + struct root_hold_token enc_rootmount; > > #define ENC_ANNOUNCE_SZ 400 > char announce_buf[ENC_ANNOUNCE_SZ]; _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"