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