> Date: Sun, 20 Feb 2011 19:54:21 +1000 > From: David Gwynne <l...@animata.net> > > > how to manipulate write cache policy? > > the lsi firmwares dont implement handling of the mod page changes > unfortunately. you could call the ioctl this implements yourself > though from userland.
David, while I think that implementing the cache manipulation ioctls for mpii(4) is a good idea, there is a problem here. We don't have a tool in base that actually issues those ioctls. And unless I'm misreading the diff, this still leaves the cache disabled on the stupid Dell. > Index: mpii.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/mpii.c,v > retrieving revision 1.37 > diff -u -p -r1.37 mpii.c > --- mpii.c 29 Dec 2010 03:55:09 -0000 1.37 > +++ mpii.c 20 Feb 2011 09:18:58 -0000 > @@ -29,6 +29,7 @@ > #include <sys/kernel.h> > #include <sys/rwlock.h> > #include <sys/sensors.h> > +#include <sys/dkio.h> > #include <sys/tree.h> > > #include <machine/bus.h> > @@ -981,6 +982,51 @@ struct mpii_msg_sas_oper_reply { > u_int32_t ioc_loginfo; > } __packed; > > +struct mpii_msg_raid_action_request { > + u_int8_t action; > +#define MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) > + u_int8_t reserved1; > + u_int8_t chain_offset; > + u_int8_t function; > + > + u_int16_t vol_dev_handle; > + u_int8_t phys_disk_num; > + u_int8_t msg_flags; > + > + u_int8_t vp_id; > + u_int8_t vf_if; > + u_int16_t reserved2; > + > + u_int32_t reserved3; > + > + u_int32_t action_data; > +#define MPII_RAID_VOL_WRITE_CACHE_MASK (0x03) > +#define MPII_RAID_VOL_WRITE_CACHE_DISABLE (0x01) > +#define MPII_RAID_VOL_WRITE_CACHE_ENABLE (0x02) > + > + struct mpii_sge action_sge; > +} __packed; > + > +struct mpii_msg_raid_action_reply { > + u_int8_t action; > + u_int8_t reserved1; > + u_int8_t chain_offset; > + u_int8_t function; > + > + u_int16_t vol_dev_handle; > + u_int8_t phys_disk_num; > + u_int8_t msg_flags; > + > + u_int8_t vp_id; > + u_int8_t vf_if; > + u_int16_t reserved2; > + > + u_int16_t reserved3; > + u_int16_t ioc_status; > + > + u_int32_t action_data[5]; > +} __packed; > + > struct mpii_cfg_hdr { > u_int8_t page_version; > u_int8_t page_length; > @@ -1256,6 +1302,11 @@ struct mpii_cfg_raid_vol_pg0 { > #define MPII_CFG_RAID_VOL_0_STATUS_RESYNC (1<<16) > > u_int16_t volume_settings; > +#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK (0x3<<0) > +#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_UNCHANGED (0x0<<0) > +#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_DISABLED (0x1<<0) > +#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED (0x2<<0) > + > u_int8_t hot_spare_pool; > u_int8_t reserved1; > > @@ -1972,6 +2023,8 @@ int mpii_req_cfg_page(struct mpii_softc > > int mpii_get_ioc_pg8(struct mpii_softc *); > > +int mpii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *); > + > #if NBIO > 0 > int mpii_ioctl(struct device *, u_long, caddr_t); > int mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *); > @@ -4650,19 +4703,123 @@ mpii_scsi_cmd_done(struct mpii_ccb *ccb) > > mpii_push_reply(sc, ccb->ccb_rcb); > scsi_done(xs); > -} > +} Looks like you're introducing spurious whitespace here. > int > mpii_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag) > { > struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc; > + struct mpii_device *dev = sc->sc_devs[link->target]; > > DNPRINTF(MPII_D_IOCTL, "%s: mpii_scsi_ioctl\n", DEVNAME(sc)); > > - if (sc->sc_ioctl) > - return (sc->sc_ioctl(link->adapter_softc, cmd, addr)); > - else > - return (ENOTTY); > + switch (cmd) { > + case DIOCGCACHE: > + case DIOCSCACHE: > + if (dev != NULL && ISSET(dev->flags, MPII_DF_VOLUME)) { > + return (mpii_ioctl_cache(link, cmd, > + (struct dk_cache *)addr)); > + } > + break; > + > + default: > + if (sc->sc_ioctl) > + return (sc->sc_ioctl(link->adapter_softc, cmd, addr)); > + > + break; > + } > + > + return (ENOTTY); > +} > + > +int > +mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc) > +{ > + struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc; > + struct mpii_device *dev = sc->sc_devs[link->target]; > + struct mpii_cfg_raid_vol_pg0 *vpg; > + struct mpii_msg_raid_action_request *req; > + struct mpii_msg_raid_action_reply *rep; > + struct mpii_cfg_hdr hdr; > + struct mpii_ccb *ccb; > + u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle; > + size_t pagelen; > + int rv = 0; > + int enabled; > + > + if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, > + addr, MPII_PG_POLL, &hdr) != 0) > + return (EINVAL); > + > + pagelen = hdr.page_length * 4; > + vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO); > + if (vpg == NULL) > + return (ENOMEM); > + > + if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1, > + vpg, pagelen) != 0) { > + rv = EINVAL; > + goto done; > + free(vpg, M_TEMP); > + return (EINVAL); > + } > + > + enabled = ((letoh16(vpg->volume_settings) & > + MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) == > + MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0; > + > + if (cmd == DIOCGCACHE) { > + dc->wrcache = enabled; > + dc->rdcache = 0; > + goto done; > + } /* else DIOCSCACHE */ > + > + if (dc->rdcache) { > + rv = EOPNOTSUPP; > + goto done; > + } > + > + if (((dc->wrcache) ? 1 : 0) == enabled) > + goto done; > + > + ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); > + if (ccb == NULL) { > + rv = ENOMEM; > + goto done; > + } > + > + ccb->ccb_done = mpii_empty_done; > + > + req = ccb->ccb_cmd; > + bzero(req, sizeof(*req)); > + req->function = MPII_FUNCTION_RAID_ACTION; > + req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE; > + req->vol_dev_handle = htole16(dev->dev_handle); > + req->action_data = htole32(dc->wrcache ? > + MPII_RAID_VOL_WRITE_CACHE_ENABLE : > + MPII_RAID_VOL_WRITE_CACHE_DISABLE); > + > + if (mpii_poll(sc, ccb) != 0) { > + rv = EIO; > + goto done; > + } > + > + if (ccb->ccb_rcb != NULL) { > + rep = ccb->ccb_rcb->rcb_reply; > + if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) || > + ((rep->action_data[0] & > + MPII_RAID_VOL_WRITE_CACHE_MASK) != > + (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE : > + MPII_RAID_VOL_WRITE_CACHE_DISABLE))) > + rv = EINVAL; > + mpii_push_reply(sc, ccb->ccb_rcb); > + } > + > + scsi_io_put(&sc->sc_iopool, ccb); > + > +done: > + free(vpg, M_TEMP); > + return (rv); > } > > #if NBIO > 0