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 _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"