diff options
author | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2013-04-12 20:48:55 +0000 |
commit | 97d8b9495668afa398ab17c8c5f7e223b5fd2e89 (patch) | |
tree | 54038c9ac32a45f8741dcc23fb9a8ffc0e15ff89 /usr.sbin/mfiutil | |
parent | 5ee3bfdb338e7c80af29a67f4425c4be24c7b866 (diff) | |
parent | 086d73aef6d0ab7d21daa2076fdc8d25961f9b05 (diff) | |
download | FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.zip FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.tar.gz |
sync from head
Diffstat (limited to 'usr.sbin/mfiutil')
-rw-r--r-- | usr.sbin/mfiutil/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfi_bbu.c | 249 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfi_show.c | 29 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfi_volume.c | 3 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfiutil.8 | 33 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfiutil.c | 2 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfiutil.h | 7 |
7 files changed, 323 insertions, 4 deletions
diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile index e100358..c460b3f 100644 --- a/usr.sbin/mfiutil/Makefile +++ b/usr.sbin/mfiutil/Makefile @@ -1,8 +1,8 @@ # $FreeBSD$ PROG= mfiutil -SRCS= mfiutil.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c mfi_flash.c \ - mfi_patrol.c mfi_show.c mfi_volume.c +SRCS= mfiutil.c mfi_bbu.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c \ + mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c MAN8= mfiutil.8 CFLAGS+= -fno-builtin-strftime diff --git a/usr.sbin/mfiutil/mfi_bbu.c b/usr.sbin/mfiutil/mfi_bbu.c new file mode 100644 index 0000000..db16367 --- /dev/null +++ b/usr.sbin/mfiutil/mfi_bbu.c @@ -0,0 +1,249 @@ +/*- + * Copyright (c) 2013 Sandvine Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/stat.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "mfiutil.h" + +/* The autolearn period is given in seconds. */ +void +mfi_autolearn_period(uint32_t period, char *buf, size_t sz) +{ + unsigned int d, h; + char *tmp; + + d = period / (24 * 3600); + h = (period % (24 * 3600)) / 3600; + + tmp = buf; + if (d != 0) { + tmp += snprintf(buf, sz, "%u day%s", d, d == 1 ? "" : "s"); + sz -= tmp - buf; + if (h != 0) { + tmp += snprintf(tmp, sz, ", "); + sz -= 2; + } + } + if (h != 0) + snprintf(tmp, sz, "%u hour%s", h, h == 1 ? "" : "s"); + + if (d == 0 && h == 0) + snprintf(tmp, sz, "less than 1 hour"); +} + +/* The time to the next relearn is given in seconds since 1/1/2000. */ +void +mfi_next_learn_time(uint32_t next_learn_time, char *buf, size_t sz) +{ + time_t basetime; + struct tm tm; + size_t len; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = 100; + basetime = timegm(&tm); + basetime += (time_t)next_learn_time; + len = snprintf(buf, sz, "%s", ctime(&basetime)); + if (len > 0) + /* Get rid of the newline added by ctime(3). */ + buf[len - 1] = '\0'; +} + +void +mfi_autolearn_mode(uint8_t mode, char *buf, size_t sz) +{ + + switch (mode) { + case 0: + snprintf(buf, sz, "enabled"); + break; + case 1: + snprintf(buf, sz, "disabled"); + break; + case 2: + snprintf(buf, sz, "warn via event"); + break; + default: + snprintf(buf, sz, "mode 0x%02x", mode); + break; + } +} + +int +mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props, uint8_t *statusp) +{ + + return (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_PROP, props, + sizeof(*props), NULL, 0, statusp)); +} + +int +mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props, uint8_t *statusp) +{ + + return (mfi_dcmd_command(fd, MFI_DCMD_BBU_SET_PROP, props, + sizeof(*props), NULL, 0, statusp)); +} + +static int +start_bbu_learn(int ac, char **av __unused) +{ + uint8_t status; + int error, fd; + + status = MFI_STAT_OK; + error = 0; + + if (ac != 1) { + warnx("start learn: unexpected arguments"); + return (EINVAL); + } + + fd = mfi_open(mfi_unit, O_RDWR); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + if (mfi_dcmd_command(fd, MFI_DCMD_BBU_START_LEARN, NULL, 0, NULL, 0, + &status) < 0) { + error = errno; + warn("Failed to start BBU learn"); + } else if (status != MFI_STAT_OK) { + warnx("Failed to start BBU learn: %s", mfi_status(status)); + error = EIO; + } + + return (error); +} +MFI_COMMAND(start, learn, start_bbu_learn); + +static int +update_bbu_props(int ac, char **av) +{ + struct mfi_bbu_properties props; + unsigned long delay; + uint8_t status; + int error, fd; + char *mode, *endptr; + + status = MFI_STAT_OK; + error = 0; + + if (ac != 3) { + warnx("bbu: property and value required"); + return (EINVAL); + } + + fd = mfi_open(mfi_unit, O_RDWR); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + if (mfi_bbu_get_props(fd, &props, &status) < 0) { + error = errno; + warn("Failed to get BBU properties"); + goto done; + } else if (status != MFI_STAT_OK) { + warnx("Failed to get BBU properties: %s", mfi_status(status)); + error = EIO; + goto done; + } + + if (strcmp(av[1], "learn-delay") == 0) { + delay = strtoul(av[2], &endptr, 10); + if (strlen(av[2]) == 0 || *endptr != '\0' || delay > 255) { + warnx("Invalid learn delay '%s'", av[2]); + error = EINVAL; + goto done; + } + + props.learn_delay_interval = delay; + } else if (strcmp(av[1], "autolearn-mode") == 0) { + mode = av[2]; + + if (strcmp(av[2], "enable") == 0) + props.auto_learn_mode = 0; + else if (strcmp(av[2], "disable") == 0) + props.auto_learn_mode = 1; + else if (mode[0] >= '0' && mode[0] <= '2' && mode[1] == '\0') + props.auto_learn_mode = mode[0] - '0'; + else { + warnx("Invalid mode '%s'", mode); + error = EINVAL; + goto done; + } + } else if (strcmp(av[1], "bbu-mode") == 0) { + if (props.bbu_mode == 0) { + warnx("This BBU does not implement different modes"); + error = EINVAL; + goto done; + } + + /* The mode must be an integer between 1 and 5. */ + mode = av[2]; + if (mode[0] < '1' || mode[0] > '5' || mode[1] != '\0') { + warnx("Invalid mode '%s'", mode); + error = EINVAL; + goto done; + } + + props.bbu_mode = mode[0] - '0'; + } else { + warnx("bbu: Invalid command '%s'", av[1]); + error = EINVAL; + goto done; + } + + if (mfi_bbu_set_props(fd, &props, &status) < 0) { + error = errno; + warn("Failed to set BBU properties"); + goto done; + } else if (status != MFI_STAT_OK) { + warnx("Failed to set BBU properties: %s", mfi_status(status)); + error = EIO; + goto done; + } + +done: + close(fd); + + return (error); +} +MFI_COMMAND(top, bbu, update_bbu_props); diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c index be395bb..06721c2 100644 --- a/usr.sbin/mfiutil/mfi_show.c +++ b/usr.sbin/mfiutil/mfi_show.c @@ -140,9 +140,11 @@ show_battery(int ac, char **av __unused) { struct mfi_bbu_capacity_info cap; struct mfi_bbu_design_info design; + struct mfi_bbu_properties props; struct mfi_bbu_status stat; uint8_t status; - int comma, error, fd, show_capacity; + int comma, error, fd, show_capacity, show_props; + char buf[32]; if (ac != 1) { warnx("show battery: extra arguments"); @@ -186,6 +188,14 @@ show_battery(int ac, char **av __unused) return (error); } + if (mfi_bbu_get_props(fd, &props, &status) < 0) { + error = errno; + warn("Failed to get properties"); + close(fd); + return (error); + } + show_props = (status == MFI_STAT_OK); + printf("mfi%d: Battery State:\n", mfi_unit); printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); @@ -205,6 +215,23 @@ show_battery(int ac, char **av __unused) printf(" Design Voltage: %d mV\n", design.design_voltage); printf(" Current Voltage: %d mV\n", stat.voltage); printf(" Temperature: %d C\n", stat.temperature); + if (show_props) { + mfi_autolearn_period(props.auto_learn_period, buf, sizeof(buf)); + printf(" Autolearn period: %s\n", buf); + if (props.auto_learn_mode != 0) + snprintf(buf, sizeof(buf), "never"); + else + mfi_next_learn_time(props.next_learn_time, buf, + sizeof(buf)); + printf(" Next learn time: %s\n", buf); + printf(" Learn delay interval: %u hour%s\n", + props.learn_delay_interval, + props.learn_delay_interval != 1 ? "s" : ""); + mfi_autolearn_mode(props.auto_learn_mode, buf, sizeof(buf)); + printf(" Autolearn mode: %s\n", buf); + if (props.bbu_mode != 0) + printf(" BBU Mode: %d\n", props.bbu_mode); + } printf(" Status:"); comma = 0; if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) { diff --git a/usr.sbin/mfiutil/mfi_volume.c b/usr.sbin/mfiutil/mfi_volume.c index 49417d0..2306256 100644 --- a/usr.sbin/mfiutil/mfi_volume.c +++ b/usr.sbin/mfiutil/mfi_volume.c @@ -363,7 +363,8 @@ volume_cache(int ac, char **av) break; } if (props.default_cache_policy != props.current_cache_policy) - printf("Cache Disabled Due to Dead Battery\n"); + printf( + "Cache disabled due to dead battery or ongoing battery relearn\n"); error = 0; } else { new = props; diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8 index b1be5d9..5468617 100644 --- a/usr.sbin/mfiutil/mfiutil.8 +++ b/usr.sbin/mfiutil/mfiutil.8 @@ -141,6 +141,12 @@ .Nm .Op Fl u Ar unit .Cm flash Ar file +.Nm +.Op Fl u Ar unit +.Cm start learn +.Nm +.Op Fl u Ar unit +.Cm bbu Ar setting Ar value .Sh DESCRIPTION The .Nm @@ -565,6 +571,33 @@ Stop a currently running patrol read operation. Updates the flash on the controller with the firmware stored in .Ar file . A reboot is required for the new firmware to take effect. +.It Cm start learn +Start a battery relearn. +.It Cm bbu Ar setting Ar value +Update battery backup unit (BBU) properties related to battery relearning. +The following settings are configurable: +.Bl -tag -width indent +.It Cm learn-delay +Add a delay to the next scheduled battery relearn event. This setting is +given in hours and must lie in the range of 0 to 255. +.It Cm autolearn-mode +Enable or disable automatic periodic battery relearning. +The setting may be set to +.Dq enable +or +.Dq disable +to respectively enable or disable the relearn cycle. +Alternatively, a mode of 0, 1 or 2 may be given. +Mode 0 enables periodic relearning, mode 1 disables it, and mode 2 disables +it and logs a warning to the event log when it detects that a battery relearn +should be performed. +.It Cm bbu-mode +Set the BBU's mode of operation. This setting is not supported by all BBUs. +Where it is supported, the possible values are the integers between 1 and 5 +inclusive. +Modes 1, 2 and 3 enable a transparent learn cycle, whereas modes 4 and 5 do not. +The BBU's data retention time is greater when transparent learning is not used. +.El .El .Sh EXAMPLES Configure the cache for volume mfid0 to cache only writes: diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c index 79c6a4b..7488e24 100644 --- a/usr.sbin/mfiutil/mfiutil.c +++ b/usr.sbin/mfiutil/mfiutil.c @@ -84,6 +84,8 @@ usage(void) fprintf(stderr, " start patrol - start a patrol read\n"); fprintf(stderr, " stop patrol - stop a patrol read\n"); fprintf(stderr, " flash <firmware>\n"); + fprintf(stderr, " start learn - start a BBU relearn\n"); + fprintf(stderr, " bbu <setting> <value> - set BBU properties\n"); #ifdef DEBUG fprintf(stderr, " debug - debug 'show config'\n"); fprintf(stderr, " dump - display 'saved' config\n"); diff --git a/usr.sbin/mfiutil/mfiutil.h b/usr.sbin/mfiutil/mfiutil.h index 687bdd9..8a544c2 100644 --- a/usr.sbin/mfiutil/mfiutil.h +++ b/usr.sbin/mfiutil/mfiutil.h @@ -152,6 +152,13 @@ int mfi_reconfig_supported(void); const char *mfi_status(u_int status_code); const char *mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t device_id, uint32_t def); +int mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props, + uint8_t *statusp); +int mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props, + uint8_t *statusp); +void mfi_autolearn_period(uint32_t, char *, size_t); +void mfi_next_learn_time(uint32_t, char *, size_t); +void mfi_autolearn_mode(uint8_t, char *, size_t); void scan_firmware(struct mfi_info_component *comp); void display_firmware(struct mfi_info_component *comp, const char *tag); |