Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Apr 2011 19:03:18 +0000
From:      Alexander Best <arundel@freebsd.org>
To:        Alexander Motin <mav@FreeBSD.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r220412 - in head: share/man/man4 sys/cam/ata
Message-ID:  <20110407190318.GA97508@freebsd.org>
In-Reply-To: <201104070817.p378HrHc033571@svn.freebsd.org>
References:  <201104070817.p378HrHc033571@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu Apr  7 11, Alexander Motin wrote:
> Author: mav
> Date: Thu Apr  7 08:17:53 2011
> New Revision: 220412
> URL: http://svn.freebsd.org/changeset/base/220412
> 
> Log:
>   Make ada(4) driver to control device write cache, same as ata(4) does.
>   Add kern.cam.ada.write_cache sysctl/tunable to control it alike hw.ata.wc.

how hard would it be to support per device sysctls/tunables? i'd really like to
do:

kern.cam.ada.0.write_cache=0 (root fs)
kern.cam.ada.1.write_cache=1 (/usr, /var, etc.)

cheers.
alex

> 
> Modified:
>   head/share/man/man4/ada.4
>   head/sys/cam/ata/ata_da.c
> 
> Modified: head/share/man/man4/ada.4
> ==============================================================================
> --- head/share/man/man4/ada.4	Thu Apr  7 07:34:01 2011	(r220411)
> +++ head/share/man/man4/ada.4	Thu Apr  7 08:17:53 2011	(r220412)
> @@ -25,7 +25,7 @@
>  .\"
>  .\" $FreeBSD$
>  .\"
> -.Dd October 24, 2010
> +.Dd April 7, 2011
>  .Dt ADA 4
>  .Os
>  .Sh NAME
> @@ -123,6 +123,11 @@ seconds.
>  This variable determines whether to spin-down disks when shutting down.
>  Set to 1 to enable spin-down, 0 to disable.  
>  The default is currently enabled.
> +.It kern.cam.ada.write_cache
> +.Pp
> +This variable determines whether device write cache should be enabled or not.
> +Set to 1 to enable write cache, 0 to disable, -1 to left it as-is.
> +The default is currently enabled.
>  .El
>  .Sh FILES
>  .Bl -tag -width ".Pa /dev/ada*" -compact
> 
> Modified: head/sys/cam/ata/ata_da.c
> ==============================================================================
> --- head/sys/cam/ata/ata_da.c	Thu Apr  7 07:34:01 2011	(r220411)
> +++ head/sys/cam/ata/ata_da.c	Thu Apr  7 08:17:53 2011	(r220412)
> @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
>  #define ATA_MAX_28BIT_LBA               268435455UL
>  
>  typedef enum {
> +	ADA_STATE_WCACHE,
>  	ADA_STATE_NORMAL
>  } ada_state;
>  
> @@ -89,6 +90,7 @@ typedef enum {
>  } ada_quirks;
>  
>  typedef enum {
> +	ADA_CCB_WCACHE		= 0x01,
>  	ADA_CCB_BUFFER_IO	= 0x03,
>  	ADA_CCB_WAITING		= 0x04,
>  	ADA_CCB_DUMP		= 0x05,
> @@ -186,6 +188,10 @@ static void		adashutdown(void *arg, int 
>  #define	ADA_DEFAULT_SPINDOWN_SHUTDOWN	1
>  #endif
>  
> +#ifndef	ADA_DEFAULT_WRITE_CACHE
> +#define	ADA_DEFAULT_WRITE_CACHE	1
> +#endif
> +
>  /*
>   * Most platforms map firmware geometry to actual, but some don't.  If
>   * not overridden, default to nothing.
> @@ -198,6 +204,7 @@ static int ada_retry_count = ADA_DEFAULT
>  static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
>  static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
>  static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN;
> +static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE;
>  
>  SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
>              "CAM Direct Access Disk driver");
> @@ -213,6 +220,9 @@ TUNABLE_INT("kern.cam.ada.ada_send_order
>  SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW,
>             &ada_spindown_shutdown, 0, "Spin down upon shutdown");
>  TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
> +SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RW,
> +           &ada_write_cache, 0, "Enable disk write cache");
> +TUNABLE_INT("kern.cam.ada.write_cache", &ada_write_cache);
>  
>  /*
>   * ADA_ORDEREDTAG_INTERVAL determines how often, relative
> @@ -568,6 +578,7 @@ adaasync(void *callback_arg, u_int32_t c
>  	struct cam_path *path, void *arg)
>  {
>  	struct cam_periph *periph;
> +	struct ada_softc *softc;
>  
>  	periph = (struct cam_periph *)callback_arg;
>  	switch (code) {
> @@ -600,6 +611,28 @@ adaasync(void *callback_arg, u_int32_t c
>  				"due to status 0x%x\n", status);
>  		break;
>  	}
> +	case AC_SENT_BDR:
> +	case AC_BUS_RESET:
> +	{
> +		struct ccb_getdev cgd;
> +
> +		softc = (struct ada_softc *)periph->softc;
> +		cam_periph_async(periph, code, path, arg);
> +		if (ada_write_cache < 0)
> +			break;
> +		if (softc->state != ADA_STATE_NORMAL)
> +			break;
> +		xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL);
> +		cgd.ccb_h.func_code = XPT_GDEV_TYPE;
> +		xpt_action((union ccb *)&cgd);
> +		if ((cgd.ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) == 0)
> +			break;
> +		softc->state = ADA_STATE_WCACHE;
> +		cam_periph_acquire(periph);
> +		cam_freeze_devq_arg(periph->path,
> +		    RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
> +		xpt_schedule(periph, CAM_PRIORITY_DEV);
> +	}
>  	default:
>  		cam_periph_async(periph, code, path, arg);
>  		break;
> @@ -691,7 +724,6 @@ adaregister(struct cam_periph *periph, v
>  	}
>  	if (cgd->ident_data.support.command2 & ATA_SUPPORT_CFA)
>  		softc->flags |= ADA_FLAG_CAN_CFA;
> -	softc->state = ADA_STATE_NORMAL;
>  
>  	periph->softc = softc;
>  
> @@ -788,7 +820,7 @@ adaregister(struct cam_periph *periph, v
>  	 * them and the only alternative would be to
>  	 * not attach the device on failure.
>  	 */
> -	xpt_register_async(AC_LOST_DEVICE,
> +	xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
>  			   adaasync, periph, periph->path);
>  
>  	/*
> @@ -800,6 +832,16 @@ adaregister(struct cam_periph *periph, v
>  	    (ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL,
>  	    adasendorderedtag, softc);
>  
> +	if (ada_write_cache >= 0 &&
> +	    cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
> +		softc->state = ADA_STATE_WCACHE;
> +		cam_periph_acquire(periph);
> +		cam_freeze_devq_arg(periph->path,
> +		    RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
> +		xpt_schedule(periph, CAM_PRIORITY_DEV);
> +	} else
> +		softc->state = ADA_STATE_NORMAL;
> +
>  	return(CAM_REQ_CMP);
>  }
>  
> @@ -1009,6 +1051,23 @@ out:
>  		adaschedule(periph);
>  		break;
>  	}
> +	case ADA_STATE_WCACHE:
> +	{
> +		cam_fill_ataio(ataio,
> +		    1,
> +		    adadone,
> +		    CAM_DIR_NONE,
> +		    0,
> +		    NULL,
> +		    0,
> +		    ada_default_timeout*1000);
> +
> +		ata_28bit_cmd(ataio, ATA_SETFEATURES, ada_write_cache ?
> +		    ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
> +		start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE;
> +		xpt_action(start_ccb);
> +		break;
> +	}
>  	}
>  }
>  
> @@ -1097,6 +1156,36 @@ adadone(struct cam_periph *periph, union
>  			biodone(bp);
>  		break;
>  	}
> +	case ADA_CCB_WCACHE:
> +	{
> +		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
> +			if (adaerror(done_ccb, 0, 0) == ERESTART) {
> +				return;
> +			} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
> +				cam_release_devq(done_ccb->ccb_h.path,
> +				    /*relsim_flags*/0,
> +				    /*reduction*/0,
> +				    /*timeout*/0,
> +				    /*getcount_only*/0);
> +			}
> +		}
> +
> +		softc->state = ADA_STATE_NORMAL;
> +		/*
> +		 * Since our peripheral may be invalidated by an error
> +		 * above or an external event, we must release our CCB
> +		 * before releasing the reference on the peripheral.
> +		 * The peripheral will only go away once the last reference
> +		 * is removed, and we need it around for the CCB release
> +		 * operation.
> +		 */
> +		xpt_release_ccb(done_ccb);
> +		cam_release_devq(periph->path,
> +		    RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
> +		adaschedule(periph);
> +		cam_periph_release_locked(periph);
> +		return;
> +	}
>  	case ADA_CCB_WAITING:
>  	{
>  		/* Caller will release the CCB */

-- 
a13x



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110407190318.GA97508>