this diff implements the disk cache ioctl handling in mpii so sd(4)
can drive the change rather than have mpii(4) whack everything.
modelled on the same functionality in mpi(4) and mikeb's code...

could someone test this please?

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      18 Feb 2011 06:54: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,52 @@ 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_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];
+
+       struct mpii_sge action_sge;
+} __packed;
+
 struct mpii_cfg_hdr {
        u_int8_t                page_version;
        u_int8_t                page_length;
@@ -1256,6 +1303,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 +2024,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 +4704,113 @@ mpii_scsi_cmd_done(struct mpii_ccb *ccb)
 
        mpii_push_reply(sc, ccb->ccb_rcb);
        scsi_done(xs);
-}
+}        
 
 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_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, 0, &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, 0, &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, 0);
+       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)
+               mpii_push_reply(sc, ccb->ccb_rcb);
+
+       scsi_io_put(&sc->sc_iopool, ccb);
+
+done:
+       free(vpg, M_TEMP);
+       return (rv);
 }
 
 #if NBIO > 0

Reply via email to