i believe the diff below should work out of the box. it pulls in
all mikeb's fixes.

On Fri, Feb 18, 2011 at 07:54:09PM +0100, ??ukasz Czarniecki wrote:
> With following Mike's suggestions it worked.
> 
> 
> # scsi -f /dev/rsd0c -m 8
> IC:  0
> ABPF:  0
> CAP:  0
> DISC:  0
> SIZE:  0
> WCE:  1
> MF:  0
> RCD:  0
> Demand Retention Priority:  0
> Write Retention Priority:  0
> Disable Pre-fetch Transfer Length:  65535
> Minimum Pre-fetch:  0
> Maximum Pre-fetch:  65280
> Maximum Pre-fetch Ceiling:  65535
> FSW:  0
> LBCSS:  0
> DRA:  0
> Vendor-specific:  0
> NV_DIS:  0
> Number of Cache Segments:  15
> Cache Segment Size:  0
> 
> 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.

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);
-}
+}        
 
 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

Reply via email to