mfi(4) & mfiutil(8): Sync with FreeBSD.
authorSascha Wildner <saw@online.de>
Fri, 6 Jan 2012 03:37:51 +0000 (04:37 +0100)
committerSascha Wildner <saw@online.de>
Fri, 6 Jan 2012 03:37:51 +0000 (04:37 +0100)
sys/dev/raid/mfi/mfi.c
sys/dev/raid/mfi/mfi_cam.c
sys/dev/raid/mfi/mfivar.h
usr.sbin/mfiutil/mfi_config.c
usr.sbin/mfiutil/mfi_evt.c
usr.sbin/mfiutil/mfi_show.c
usr.sbin/mfiutil/mfi_volume.c
usr.sbin/mfiutil/mfiutil.8

index 03e435f..a60268c 100644 (file)
@@ -79,7 +79,7 @@
  * are those of the authors and should not be interpreted as representing
  * official policies,either expressed or implied, of the FreeBSD Project.
  *
- * $FreeBSD: src/sys/dev/mfi/mfi.c,v 1.57 2011/07/14 20:20:33 jhb Exp $
+ * $FreeBSD: src/sys/dev/mfi/mfi.c,v 1.62 2011/11/09 21:53:49 delphij Exp $
  */
 
 #include "opt_mfi.h"
@@ -1058,6 +1058,12 @@ mfi_intr(void *arg)
        if (sc->mfi_check_clear_intr(sc))
                return;
 
+       /*
+        * Do a dummy read to flush the interrupt ACK that we just performed,
+        * ensuring that everything is really, truly consistent.
+        */
+       (void)sc->mfi_read_fw_status(sc);
+
        pi = sc->mfi_comms->hw_pi;
        ci = sc->mfi_comms->hw_ci;
        lockmgr(&sc->mfi_io_lock, LK_EXCLUSIVE);
@@ -1876,7 +1882,7 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
        struct mfi_command *cm;
        union mfi_sgl *sgl;
        struct mfi_softc *sc;
-       int i, dir;
+       int i, j, first, dir;
        int sgl_mapped = 0;
        int sge_size = 0;
 
@@ -1912,22 +1918,37 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                sge_size = sizeof(struct mfi_sg_skinny);
        }
        if (!sgl_mapped) {
+               j = 0;
+               if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+                       first = cm->cm_stp_len;
+                       if ((sc->mfi_flags & MFI_FLAGS_SG64) == 0) {
+                               sgl->sg32[j].addr = segs[0].ds_addr;
+                               sgl->sg32[j++].len = first;
+                       } else {
+                               sgl->sg64[j].addr = segs[0].ds_addr;
+                               sgl->sg64[j++].len = first;
+                       }
+               } else
+                       first = 0;
                if ((sc->mfi_flags & MFI_FLAGS_SG64) == 0) {
                        for (i = 0; i < nsegs; i++) {
-                               sgl->sg32[i].addr = segs[i].ds_addr;
-                               sgl->sg32[i].len = segs[i].ds_len;
+                               sgl->sg32[j].addr = segs[i].ds_addr + first;
+                               sgl->sg32[j++].len = segs[i].ds_len - first;
+                               first = 0;
                        }
                        sge_size = sizeof(struct mfi_sg32);
                } else {
                        for (i = 0; i < nsegs; i++) {
-                               sgl->sg64[i].addr = segs[i].ds_addr;
-                               sgl->sg64[i].len = segs[i].ds_len;
+                               sgl->sg64[j].addr = segs[i].ds_addr + first;
+                               sgl->sg64[j++].len = segs[i].ds_len - first;
+                               first = 0;
                        }
                        hdr->flags |= MFI_FRAME_SGL64;
                        sge_size = sizeof(struct mfi_sg64);
                }
-       }
-       hdr->sg_count = nsegs;
+               hdr->sg_count = j;
+       } else
+               hdr->sg_count = nsegs;
 
        dir = 0;
        if (cm->cm_flags & MFI_CMD_DATAIN) {
@@ -1938,6 +1959,8 @@ mfi_data_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
                dir |= BUS_DMASYNC_PREWRITE;
                hdr->flags |= MFI_FRAME_DIR_WRITE;
        }
+       if (cm->cm_frame->header.cmd == MFI_CMD_STP)
+               dir |= BUS_DMASYNC_PREWRITE;
        bus_dmamap_sync(sc->mfi_buffer_dmat, cm->cm_dmamap, dir);
        cm->cm_flags |= MFI_CMD_MAPPED;
 
@@ -2013,7 +2036,8 @@ mfi_complete(struct mfi_softc *sc, struct mfi_command *cm)
 
        if ((cm->cm_flags & MFI_CMD_MAPPED) != 0) {
                dir = 0;
-               if (cm->cm_flags & MFI_CMD_DATAIN)
+               if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP))
                        dir |= BUS_DMASYNC_POSTREAD;
                if (cm->cm_flags & MFI_CMD_DATAOUT)
                        dir |= BUS_DMASYNC_POSTWRITE;
@@ -2504,7 +2528,8 @@ mfi_ioctl(struct dev_ioctl_args *ap)
        struct mfi_command *cm = NULL;
        uint32_t context;
        union mfi_sense_ptr sense_ptr;
-       uint8_t *data = NULL, *temp, skip_pre_post = 0;
+       uint8_t *data = NULL, *temp, *addr, skip_pre_post = 0;
+       size_t len;
        int i;
        struct mfi_ioc_passthru *iop = (struct mfi_ioc_passthru *)arg;
 #ifdef __x86_64__
@@ -2603,6 +2628,21 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                if (cm->cm_flags == 0)
                        cm->cm_flags |= MFI_CMD_DATAIN | MFI_CMD_DATAOUT;
                cm->cm_len = cm->cm_frame->header.data_len;
+               if (cm->cm_frame->header.cmd == MFI_CMD_STP) {
+#ifdef __x86_64__
+                       if (cmd == MFI_CMD) {
+#endif
+                               /* Native */
+                               cm->cm_stp_len = ioc->mfi_sgl[0].iov_len;
+#ifdef __x86_64__
+                       } else {
+                               /* 32bit on 64bit */
+                               ioc32 = (struct mfi_ioc_packet32 *)ioc;
+                               cm->cm_stp_len = ioc32->mfi_sgl[0].iov_len;
+                       }
+#endif
+                       cm->cm_len += cm->cm_stp_len;
+               }
                if (cm->cm_len &&
                    (cm->cm_flags & (MFI_CMD_DATAIN | MFI_CMD_DATAOUT))) {
                        cm->cm_data = data = kmalloc(cm->cm_len, M_MFIBUF,
@@ -2619,35 +2659,30 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                cm->cm_frame->header.context = context;
 
                temp = data;
-               if (cm->cm_flags & MFI_CMD_DATAOUT) {
+               if ((cm->cm_flags & MFI_CMD_DATAOUT) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
                        for (i = 0; i < ioc->mfi_sge_count; i++) {
 #ifdef __x86_64__
                                if (cmd == MFI_CMD) {
+#endif
                                        /* Native */
-                                       error = copyin(ioc->mfi_sgl[i].iov_base,
-                                              temp,
-                                              ioc->mfi_sgl[i].iov_len);
+                                       addr = ioc->mfi_sgl[i].iov_base;
+                                       len = ioc->mfi_sgl[i].iov_len;
+#ifdef __x86_64__
                                } else {
-                                       void *temp_convert;
-                                       /* 32bit */
+                                       /* 32bit on 64bit */
                                        ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       temp_convert =
-                                           PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       error = copyin(temp_convert,
-                                              temp,
-                                              ioc32->mfi_sgl[i].iov_len);
+                                       addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
+                                       len = ioc32->mfi_sgl[i].iov_len;
                                }
-#else
-                               error = copyin(ioc->mfi_sgl[i].iov_base,
-                                      temp,
-                                      ioc->mfi_sgl[i].iov_len);
 #endif
+                               error = copyin(addr, temp, len);
                                if (error != 0) {
                                        device_printf(sc->mfi_dev,
                                            "Copy in failed\n");
                                        goto out;
                                }
-                               temp = &temp[ioc->mfi_sgl[i].iov_len];
+                               temp = &temp[len];
                        }
                }
 
@@ -2688,42 +2723,36 @@ mfi_ioctl(struct dev_ioctl_args *ap)
                lockmgr(&sc->mfi_io_lock, LK_RELEASE);
 
                temp = data;
-               if (cm->cm_flags & MFI_CMD_DATAIN) {
+               if ((cm->cm_flags & MFI_CMD_DATAIN) ||
+                   (cm->cm_frame->header.cmd == MFI_CMD_STP)) {
                        for (i = 0; i < ioc->mfi_sge_count; i++) {
 #ifdef __x86_64__
                                if (cmd == MFI_CMD) {
+#endif
                                        /* Native */
-                                       error = copyout(temp,
-                                               ioc->mfi_sgl[i].iov_base,
-                                               ioc->mfi_sgl[i].iov_len);
+                                       addr = ioc->mfi_sgl[i].iov_base;
+                                       len = ioc->mfi_sgl[i].iov_len;
+#ifdef __x86_64__
                                } else {
-                                       void *temp_convert;
-                                       /* 32bit */
+                                       /* 32bit on 64bit */
                                        ioc32 = (struct mfi_ioc_packet32 *)ioc;
-                                       temp_convert =
-                                           PTRIN(ioc32->mfi_sgl[i].iov_base);
-                                       error = copyout(temp,
-                                               temp_convert,
-                                               ioc32->mfi_sgl[i].iov_len);
+                                       addr = PTRIN(ioc32->mfi_sgl[i].iov_base);
+                                       len = ioc32->mfi_sgl[i].iov_len;
                                }
-#else
-                               error = copyout(temp,
-                                       ioc->mfi_sgl[i].iov_base,
-                                       ioc->mfi_sgl[i].iov_len);
 #endif
+                               error = copyout(temp, addr, len);
                                if (error != 0) {
                                        device_printf(sc->mfi_dev,
                                            "Copy out failed\n");
                                        goto out;
                                }
-                               temp = &temp[ioc->mfi_sgl[i].iov_len];
+                               temp = &temp[len];
                        }
                }
 
                if (ioc->mfi_sense_len) {
                        /* get user-space sense ptr then copy out sense */
-                       bcopy(&((struct mfi_ioc_packet*)arg)
-                           ->mfi_frame.raw[ioc->mfi_sense_off],
+                       bcopy(&ioc->mfi_frame.raw[ioc->mfi_sense_off],
                            &sense_ptr.sense_ptr_data[0],
                            sizeof(sense_ptr.sense_ptr_data));
 #ifdef __x86_64__
index 4d3933a..f7e43a7 100644 (file)
@@ -53,7 +53,7 @@
  * are those of the authors and should not be interpreted as representing
  * official policies,either expressed or implied, of the FreeBSD Project.
  *
- * $FreeBSD: src/sys/dev/mfi/mfi_cam.c,v 1.6 2011/06/28 08:36:48 kevlo Exp $
+ * $FreeBSD: src/sys/dev/mfi/mfi_cam.c,v 1.7 2011/10/13 20:06:19 marius Exp $
  */
 
 #include "opt_mfi.h"
@@ -379,7 +379,13 @@ mfip_done(struct mfi_command *cm)
 
                ccbh->status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
                csio->scsi_status = pt->header.scsi_status;
-               sense_len = min(pt->header.sense_len, sizeof(struct scsi_sense_data));
+               if (pt->header.sense_len < csio->sense_len)
+                       csio->sense_resid = csio->sense_len -
+                           pt->header.sense_len;
+               else
+                       csio->sense_resid = 0;
+               sense_len = min(pt->header.sense_len,
+                   sizeof(struct scsi_sense_data));
                bzero(&csio->sense_data, sizeof(struct scsi_sense_data));
                bcopy(&cm->cm_sense->data[0], &csio->sense_data, sense_len);
                break;
index 478700b..56518a8 100644 (file)
@@ -79,7 +79,7 @@
  * are those of the authors and should not be interpreted as representing
  * official policies,either expressed or implied, of the FreeBSD Project.
  *
- * $FreeBSD: src/sys/dev/mfi/mfivar.h,v 1.13 2009/07/10 08:18:08 scottl Exp $
+ * $FreeBSD: src/sys/dev/mfi/mfivar.h,v 1.14 2011/09/29 08:37:53 mav Exp $
  */
 
 #ifndef _MFIVAR_H
@@ -127,6 +127,7 @@ struct mfi_command {
        union mfi_sgl           *cm_sg;
        void                    *cm_data;
        int                     cm_len;
+       int                     cm_stp_len;
        int                     cm_total_frame_size;
        int                     cm_extra_frames;
        int                     cm_flags;
index 7b8621e..f0dcb15 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/mfiutil/mfi_config.c,v 1.6 2011/06/20 21:28:50 bz Exp $
+ * $FreeBSD: src/usr.sbin/mfiutil/mfi_config.c,v 1.8 2011/11/29 08:16:14 delphij Exp $
  */
 
 #include <sys/param.h>
@@ -348,6 +348,7 @@ parse_array(int fd, int raid_type, char *array_str, struct array_info *info)
                error = mfi_lookup_drive(fd, cp, &device_id);
                if (error) {
                        free(info->drives);
+                       info->drives = NULL;
                        return (error);
                }
 
@@ -355,12 +356,14 @@ parse_array(int fd, int raid_type, char *array_str, struct array_info *info)
                        error = errno;
                        warn("Failed to fetch drive info for drive %s", cp);
                        free(info->drives);
+                       info->drives = NULL;
                        return (error);
                }
 
                if (pinfo->fw_state != MFI_PD_STATE_UNCONFIGURED_GOOD) {
                        warnx("Drive %u is not available", device_id);
                        free(info->drives);
+                       info->drives = NULL;
                        return (EINVAL);
                }
        }
@@ -817,9 +820,11 @@ error:
        free(config);
        free(state.volumes);
        free(state.arrays);
-       for (i = 0; i < narrays; i++)
-               free(arrays[i].drives);
-       free(arrays);
+       if (arrays != NULL) {
+               for (i = 0; i < narrays; i++)
+                       free(arrays[i].drives);
+               free(arrays);
+       }
        close(fd);
 
        return (error);
index 6696d8d..6b1cc79 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/mfiutil/mfi_evt.c,v 1.5 2011/06/09 19:52:28 bz Exp $
+ * $FreeBSD: src/usr.sbin/mfiutil/mfi_evt.c,v 1.6 2011/12/05 15:11:35 jhb Exp $
  */
 
 #include <sys/types.h>
@@ -438,7 +438,7 @@ mfi_decode_evt(int fd, struct mfi_evt_detail *detail, int verbose)
                printf(": ");
                break;
        case MR_EVT_ARGS_LD_STRIP:
-               printf("VOL %s", volume_name(fd, &detail->args.ld_prog.ld));
+               printf("VOL %s", volume_name(fd, &detail->args.ld_strip.ld));
                if (verbose) {
                        printf(" strip %lld",
                            (long long)detail->args.ld_strip.strip);
index 0818514..64db06d 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/mfiutil/mfi_show.c,v 1.8 2011/07/29 20:24:04 jhb Exp $
+ * $FreeBSD: src/usr.sbin/mfiutil/mfi_show.c,v 1.10 2011/09/27 14:28:07 emaste Exp $
  */
 
 #include <sys/types.h>
@@ -141,7 +141,7 @@ show_battery(int ac, char **av)
        struct mfi_bbu_design_info design;
        struct mfi_bbu_status stat;
        uint8_t status;
-       int comma, error, fd;
+       int comma, error, fd, show_capacity;
 
        if (ac != 1) {
                warnx("show battery: extra arguments");
@@ -157,16 +157,17 @@ show_battery(int ac, char **av)
 
        if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_CAPACITY_INFO, &cap,
            sizeof(cap), NULL, 0, &status) < 0) {
-               if (status == MFI_STAT_NO_HW_PRESENT) {
-                       printf("mfi%d: No battery present\n", mfi_unit);
-                       close(fd);
-                       return (0);
-               }
                error = errno;
                warn("Failed to get capacity info");
                close(fd);
                return (error);
        }
+       if (status == MFI_STAT_NO_HW_PRESENT) {
+               printf("mfi%d: No battery present\n", mfi_unit);
+               close(fd);
+               return (0);
+       }
+       show_capacity = (status == MFI_STAT_OK);
 
        if (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_DESIGN_INFO, &design,
            sizeof(design), NULL, 0, NULL) < 0) {
@@ -192,10 +193,14 @@ show_battery(int ac, char **av)
        printf("                Model: %s\n", design.device_name);
        printf("            Chemistry: %s\n", design.device_chemistry);
        printf("      Design Capacity: %d mAh\n", design.design_capacity);
-       printf(" Full Charge Capacity: %d mAh\n", cap.full_charge_capacity);
-       printf("     Current Capacity: %d mAh\n", cap.remaining_capacity);
-       printf("        Charge Cycles: %d\n", cap.cycle_count);
-       printf("       Current Charge: %d%%\n", cap.relative_charge);
+       if (show_capacity) {
+               printf(" Full Charge Capacity: %d mAh\n",
+                   cap.full_charge_capacity);
+               printf("     Current Capacity: %d mAh\n",
+                   cap.remaining_capacity);
+               printf("        Charge Cycles: %d\n", cap.cycle_count);
+               printf("       Current Charge: %d%%\n", cap.relative_charge);
+       }
        printf("       Design Voltage: %d mV\n", design.design_voltage);
        printf("      Current Voltage: %d mV\n", stat.voltage);
        printf("          Temperature: %d C\n", stat.temperature);
@@ -330,8 +335,8 @@ show_config(int ac, char **av)
                                            mfi_pdstate(ar->pd[j].fw_state));
                                else
                                        print_pd(&pinfo, -1);
-                               printf("\n");
                        }
+                       printf("\n");
                }
                p += config->array_size;
        }
index b9ea2cc..3c99265 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.sbin/mfiutil/mfi_volume.c,v 1.4 2011/06/09 19:52:28 bz Exp $
+ * $FreeBSD: src/usr.sbin/mfiutil/mfi_volume.c,v 1.5 2011/09/02 16:00:51 jhb Exp $
  */
 
 #include <sys/types.h>
@@ -111,16 +111,16 @@ mfi_ld_set_props(int fd, struct mfi_ld_props *props)
 }
 
 static int
-update_cache_policy(int fd, struct mfi_ld_props *props, uint8_t new_policy,
-    uint8_t mask)
+update_cache_policy(int fd, struct mfi_ld_props *old, struct mfi_ld_props *new)
 {
        int error;
        uint8_t changes, policy;
 
-       policy = (props->default_cache_policy & ~mask) | new_policy;
-       if (policy == props->default_cache_policy)
+       if (old->default_cache_policy == new->default_cache_policy &&
+           old->disk_cache_policy == new->disk_cache_policy)
                return (0);
-       changes = policy ^ props->default_cache_policy;
+       policy = new->default_cache_policy;
+       changes = policy ^ old->default_cache_policy;
        if (changes & MR_LD_CACHE_ALLOW_WRITE_CACHE)
                printf("%s caching of I/O writes\n",
                    policy & MR_LD_CACHE_ALLOW_WRITE_CACHE ? "Enabling" :
@@ -142,9 +142,21 @@ update_cache_policy(int fd, struct mfi_ld_props *props, uint8_t new_policy,
                printf("%s write caching with bad BBU\n",
                    policy & MR_LD_CACHE_WRITE_CACHE_BAD_BBU ? "Enabling" :
                    "Disabling");
+       if (old->disk_cache_policy != new->disk_cache_policy) {
+               switch (new->disk_cache_policy) {
+               case MR_PD_CACHE_ENABLE:
+                       printf("Enabling write-cache on physical drives\n");
+                       break;
+               case MR_PD_CACHE_DISABLE:
+                       printf("Disabling write-cache on physical drives\n");
+                       break;
+               case MR_PD_CACHE_UNCHANGED:
+                       printf("Using default write-cache setting on physical drives\n");
+                       break;
+               }
+       }
 
-       props->default_cache_policy = policy;
-       if (mfi_ld_set_props(fd, props) < 0) {
+       if (mfi_ld_set_props(fd, new) < 0) {
                error = errno;
                warn("Failed to set volume properties");
                return (error);
@@ -152,12 +164,130 @@ update_cache_policy(int fd, struct mfi_ld_props *props, uint8_t new_policy,
        return (0);
 }
 
+static void
+stage_cache_setting(struct mfi_ld_props *props, uint8_t new_policy,
+    uint8_t mask)
+{
+
+       props->default_cache_policy &= ~mask;
+       props->default_cache_policy |= new_policy;
+}
+
+/*
+ * Parse a single cache directive modifying the passed in policy.
+ * Returns -1 on a parse error and the number of arguments consumed
+ * on success.
+ */
+static int
+process_cache_command(int ac, char **av, struct mfi_ld_props *props)
+{
+       uint8_t policy;
+
+       /* I/O cache settings. */
+       if (strcmp(av[0], "all") == 0 || strcmp(av[0], "enable") == 0) {
+               stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE |
+                   MR_LD_CACHE_ALLOW_WRITE_CACHE,
+                   MR_LD_CACHE_ALLOW_READ_CACHE |
+                   MR_LD_CACHE_ALLOW_WRITE_CACHE);
+               return (1);
+       }
+       if (strcmp(av[0], "none") == 0 || strcmp(av[0], "disable") == 0) {
+               stage_cache_setting(props, 0, MR_LD_CACHE_ALLOW_READ_CACHE |
+                   MR_LD_CACHE_ALLOW_WRITE_CACHE);
+               return (1);
+       }
+       if (strcmp(av[0], "reads") == 0) {
+               stage_cache_setting(props, MR_LD_CACHE_ALLOW_READ_CACHE,
+                   MR_LD_CACHE_ALLOW_READ_CACHE |
+                   MR_LD_CACHE_ALLOW_WRITE_CACHE);
+               return (1);
+       }
+       if (strcmp(av[0], "writes") == 0) {
+               stage_cache_setting(props, MR_LD_CACHE_ALLOW_WRITE_CACHE,
+                   MR_LD_CACHE_ALLOW_READ_CACHE |
+                   MR_LD_CACHE_ALLOW_WRITE_CACHE);
+               return (1);
+       }
+
+       /* Write cache behavior. */
+       if (strcmp(av[0], "write-back") == 0) {
+               stage_cache_setting(props, MR_LD_CACHE_WRITE_BACK,
+                   MR_LD_CACHE_WRITE_BACK);
+               return (1);
+       }
+       if (strcmp(av[0], "write-through") == 0) {
+               stage_cache_setting(props, 0, MR_LD_CACHE_WRITE_BACK);
+               return (1);
+       }
+       if (strcmp(av[0], "bad-bbu-write-cache") == 0) {
+               if (ac < 2) {
+                       warnx("cache: bad BBU setting required");
+                       return (-1);
+               }
+               if (strcmp(av[1], "enable") == 0)
+                       policy = MR_LD_CACHE_WRITE_CACHE_BAD_BBU;
+               else if (strcmp(av[1], "disable") == 0)
+                       policy = 0;
+               else {
+                       warnx("cache: invalid bad BBU setting");
+                       return (-1);
+               }
+               stage_cache_setting(props, policy,
+                   MR_LD_CACHE_WRITE_CACHE_BAD_BBU);
+               return (2);
+       }
+
+       /* Read cache behavior. */
+       if (strcmp(av[0], "read-ahead") == 0) {
+               if (ac < 2) {
+                       warnx("cache: read-ahead setting required");
+                       return (-1);
+               }
+               if (strcmp(av[1], "none") == 0)
+                       policy = 0;
+               else if (strcmp(av[1], "always") == 0)
+                       policy = MR_LD_CACHE_READ_AHEAD;
+               else if (strcmp(av[1], "adaptive") == 0)
+                       policy = MR_LD_CACHE_READ_AHEAD |
+                           MR_LD_CACHE_READ_ADAPTIVE;
+               else {
+                       warnx("cache: invalid read-ahead setting");
+                       return (-1);
+               }
+               stage_cache_setting(props, policy, MR_LD_CACHE_READ_AHEAD |
+                           MR_LD_CACHE_READ_ADAPTIVE);
+               return (2);
+       }
+
+       /* Drive write-cache behavior. */
+       if (strcmp(av[0], "write-cache") == 0) {
+               if (ac < 2) {
+                       warnx("cache: write-cache setting required");
+                       return (-1);
+               }
+               if (strcmp(av[1], "enable") == 0)
+                       props->disk_cache_policy = MR_PD_CACHE_ENABLE;
+               else if (strcmp(av[1], "disable") == 0)
+                       props->disk_cache_policy = MR_PD_CACHE_DISABLE;
+               else if (strcmp(av[1], "default") == 0)
+                       props->disk_cache_policy = MR_PD_CACHE_UNCHANGED;
+               else {
+                       warnx("cache: invalid write-cache setting");
+                       return (-1);
+               }
+               return (2);
+       }
+
+       warnx("cache: Invalid command");
+       return (-1);
+}
+
 static int
 volume_cache(int ac, char **av)
 {
-       struct mfi_ld_props props;
-       int error, fd;
-       uint8_t target_id, policy;
+       struct mfi_ld_props props, new;
+       int error, fd, consumed;
+       uint8_t target_id;
 
        if (ac < 2) {
                warnx("cache: volume required");
@@ -235,113 +365,19 @@ volume_cache(int ac, char **av)
                        printf("Cache Disabled Due to Dead Battery\n");
                error = 0;
        } else {
-               if (strcmp(av[2], "all") == 0 || strcmp(av[2], "enable") == 0)
-                       error = update_cache_policy(fd, &props,
-                           MR_LD_CACHE_ALLOW_READ_CACHE |
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE,
-                           MR_LD_CACHE_ALLOW_READ_CACHE |
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE);
-               else if (strcmp(av[2], "none") == 0 ||
-                   strcmp(av[2], "disable") == 0)
-                       error = update_cache_policy(fd, &props, 0,
-                           MR_LD_CACHE_ALLOW_READ_CACHE |
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE);
-               else if (strcmp(av[2], "reads") == 0)
-                       error = update_cache_policy(fd, &props,
-                           MR_LD_CACHE_ALLOW_READ_CACHE,
-                           MR_LD_CACHE_ALLOW_READ_CACHE |
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE);
-               else if (strcmp(av[2], "writes") == 0)
-                       error = update_cache_policy(fd, &props,
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE,
-                           MR_LD_CACHE_ALLOW_READ_CACHE |
-                           MR_LD_CACHE_ALLOW_WRITE_CACHE);
-               else if (strcmp(av[2], "write-back") == 0)
-                       error = update_cache_policy(fd, &props,
-                           MR_LD_CACHE_WRITE_BACK,
-                           MR_LD_CACHE_WRITE_BACK);
-               else if (strcmp(av[2], "write-through") == 0)
-                       error = update_cache_policy(fd, &props, 0,
-                           MR_LD_CACHE_WRITE_BACK);
-               else if (strcmp(av[2], "read-ahead") == 0) {
-                       if (ac < 4) {
-                               warnx("cache: read-ahead setting required");
-                               close(fd);
-                               return (EINVAL);
-                       }
-                       if (strcmp(av[3], "none") == 0)
-                               policy = 0;
-                       else if (strcmp(av[3], "always") == 0)
-                               policy = MR_LD_CACHE_READ_AHEAD;
-                       else if (strcmp(av[3], "adaptive") == 0)
-                               policy = MR_LD_CACHE_READ_AHEAD |
-                                   MR_LD_CACHE_READ_ADAPTIVE;
-                       else {
-                               warnx("cache: invalid read-ahead setting");
+               new = props;
+               av += 2;
+               ac -= 2;
+               while (ac > 0) {
+                       consumed = process_cache_command(ac, av, &new);
+                       if (consumed < 0) {
                                close(fd);
                                return (EINVAL);
                        }
-                       error = update_cache_policy(fd, &props, policy,
-                           MR_LD_CACHE_READ_AHEAD |
-                           MR_LD_CACHE_READ_ADAPTIVE);
-               } else if (strcmp(av[2], "bad-bbu-write-cache") == 0) {
-                       if (ac < 4) {
-                               warnx("cache: bad BBU setting required");
-                               close(fd);
-                               return (EINVAL);
-                       }
-                       if (strcmp(av[3], "enable") == 0)
-                               policy = MR_LD_CACHE_WRITE_CACHE_BAD_BBU;
-                       else if (strcmp(av[3], "disable") == 0)
-                               policy = 0;
-                       else {
-                               warnx("cache: invalid bad BBU setting");
-                               close(fd);
-                               return (EINVAL);
-                       }
-                       error = update_cache_policy(fd, &props, policy,
-                           MR_LD_CACHE_WRITE_CACHE_BAD_BBU);
-               } else if (strcmp(av[2], "write-cache") == 0) {
-                       if (ac < 4) {
-                               warnx("cache: write-cache setting required");
-                               close(fd);
-                               return (EINVAL);
-                       }
-                       if (strcmp(av[3], "enable") == 0)
-                               policy = MR_PD_CACHE_ENABLE;
-                       else if (strcmp(av[3], "disable") == 0)
-                               policy = MR_PD_CACHE_DISABLE;
-                       else if (strcmp(av[3], "default") == 0)
-                               policy = MR_PD_CACHE_UNCHANGED;
-                       else {
-                               warnx("cache: invalid write-cache setting");
-                               close(fd);
-                               return (EINVAL);
-                       }
-                       error = 0;
-                       if (policy != props.disk_cache_policy) {
-                               switch (policy) {
-                               case MR_PD_CACHE_ENABLE:
-                                       printf("Enabling write-cache on physical drives\n");
-                                       break;
-                               case MR_PD_CACHE_DISABLE:
-                                       printf("Disabling write-cache on physical drives\n");
-                                       break;
-                               case MR_PD_CACHE_UNCHANGED:
-                                       printf("Using default write-cache setting on physical drives\n");
-                                       break;
-                               }
-                               props.disk_cache_policy = policy;
-                               if (mfi_ld_set_props(fd, &props) < 0) {
-                                       error = errno;
-                                       warn("Failed to set volume properties");
-                               }
-                       }
-               } else {
-                       warnx("cache: Invalid command");
-                       close(fd);
-                       return (EINVAL);
+                       av += consumed;
+                       ac -= consumed;
                }
+               error = update_cache_policy(fd, &props, &new);
        }
        close(fd);
 
index 75134c9..d665845 100644 (file)
@@ -25,9 +25,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.sbin/mfiutil/mfiutil.8,v 1.8 2011/06/20 21:28:50 bz Exp $
+.\" $FreeBSD: src/usr.sbin/mfiutil/mfiutil.8,v 1.9 2011/09/02 16:00:51 jhb Exp $
 .\"
-.Dd August 1, 2011
+.Dd January 6, 2012
 .Dt MFIUTIL 8
 .Os
 .Sh NAME
 .Cm locate Ar drive Brq "on | off"
 .Nm
 .Op Fl u Ar unit
-.Cm cache Ar volume Op Ar setting Op Ar value
+.Cm cache Ar volume Op Ar setting Oo Ar value Oc Op ...
 .Nm
 .Op Fl u Ar unit
 .Cm name Ar volume Ar name
@@ -367,19 +367,23 @@ Change the state of the external LED associated with
 .Pp
 The logical volume management commands include:
 .Bl -tag -width indent
-.It Cm cache Ar volume Op Ar setting Op Ar value
+.It Cm cache Ar volume Op Ar setting Oo Ar value Oc Op ...
 If no
 .Ar setting
-argument is supplied, then the current cache policy for
+arguments are supplied, then the current cache policy for
 .Ar volume
 is displayed;
 otherwise,
 the cache policy for
 .Ar volume
 is modified.
-The optional
+One or more
 .Ar setting
-argument can be one of the following values:
+arguments may be given.
+Some settings take an additional
+.Ar value
+argument as noted below.
+The valid settings are:
 .Bl -tag -width indent
 .It Cm enable
 Enable caching for both read and write I/O operations.