svn commit: r355010 - in head/sys/cam: . scsi
Ian Lepore
ian at freebsd.org
Fri Nov 22 19:00:42 UTC 2019
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];
More information about the svn-src-all
mailing list