From owner-freebsd-scsi@FreeBSD.ORG Mon Mar 4 03:38:53 2013 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id F0C39C06 for ; Mon, 4 Mar 2013 03:38:53 +0000 (UTC) (envelope-from markjdb@gmail.com) Received: from mail-ia0-x229.google.com (mail-ia0-x229.google.com [IPv6:2607:f8b0:4001:c02::229]) by mx1.freebsd.org (Postfix) with ESMTP id B477B921 for ; Mon, 4 Mar 2013 03:38:53 +0000 (UTC) Received: by mail-ia0-f169.google.com with SMTP id j5so4402818iaf.14 for ; Sun, 03 Mar 2013 19:38:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:date:from:to:subject:message-id:mime-version :content-type:content-disposition:user-agent; bh=ZBMtZkbmWWFQdJZDC4tEfMULA07DYcYrQbeHWMyE7po=; b=sqDWLqMn5UqzYKsLLDTqi9tcVHXNZgkNACMGLKhB8kHBON8dE8se+CAt31/csW1v1R SzVnLTQ7jQR2EK8E8ulVKYcQsCd02r6uIjqQNLJSx8x3Odt5CSEa64QHlN0gCcFDLMRF iXxWvZW+iJXtDQt7dfcKy+wX99kUBmsioiMXQ1+kB94QGcSco2FXWvUmhoXi5TbnfKgH Nk1QBuOyvOqQ7WhQYxiyYNkjEGrgpZx732EYhB1MGUn6Gy38JMe4DcaurD6SUAAckMsa keLBHsx2NMWksES7I+Uo4R8y3KGRbi8Pn6QFb1yRQj84MfqXnOfdKUIBYpOwXVFRlx+g X6VA== X-Received: by 10.50.13.175 with SMTP id i15mr1347706igc.75.1362368333416; Sun, 03 Mar 2013 19:38:53 -0800 (PST) Received: from oddish ([66.11.160.25]) by mx.google.com with ESMTPS id vb15sm9262362igb.9.2013.03.03.19.38.51 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 03 Mar 2013 19:38:52 -0800 (PST) Sender: Mark Johnston Date: Sun, 3 Mar 2013 22:38:36 -0500 From: Mark Johnston To: freebsd-scsi@freebsd.org Subject: adding BBU relearn support to mfiutil Message-ID: <20130304033836.GA33631@oddish> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Mar 2013 03:38:54 -0000 Hi Everyone, I recently needed to add a couple of features to mfiutil related to BBU relearning. I've pasted a patch below which 1. adds extra fields to the output of "mfiutil show battery" showing BBU properties. This is essentially the output of # MegaCli -AdpBbuInfo -GetBbuProperties -aLL and consists of info about battery learning: the learn period, the time at which the controller will start the next relearn, and the BBU mode (which indicates whether the battery supports transparent relearning). 2. adds a couple of subcommands under "mfiutil bbu" which lets users set the BBU properties which can be set by MegaCli. 3. adds a command "mfiutil start learn" which immediately kicks off a battery relearn. These changes grew out of concern about the fact that the controller write cache is set to write-through mode during a relearn period (which usually lasts for several hours). This ended up causing some mysterious and intermittent performance issues, so I needed a way of getting more info about what was going on (using MegaCli isn't really an option for several reasons). Some BBUs support transparent relearning, which basically means that the controller write cache doesn't get turned off during a relearn. However, LSI's default config doesn't enable it, and now mfiutil can be used to do that (through "mfiutil bbu bbu-mode"). I was hoping someone would be able to review the patch. If anyone's able and willing to test it, I'd very much appreciate feedback from that. Thanks! -Mark diff --git a/sys/dev/mfi/mfi_debug.c b/sys/dev/mfi/mfi_debug.c index 4aec4f7..be42ec0 100644 --- a/sys/dev/mfi/mfi_debug.c +++ b/sys/dev/mfi/mfi_debug.c @@ -168,6 +168,15 @@ mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) case MFI_DCMD_LD_MAP_GET_INFO: opcode = "LD_MAP_GET_INFO"; break; + case MFI_DCMD_BBU_START_LEARN: + opcode = "BBU_START_LEARN"; + break; + case MFI_DCMD_BBU_GET_PROP: + opcode = "BBU_GET_PROP"; + break; + case MFI_DCMD_BBU_SET_PROP: + opcode = "BBU_SET_PROP"; + break; default: opcode = "UNKNOWN"; break; diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h index 52ddafe..8f88f10 100644 --- a/sys/dev/mfi/mfireg.h +++ b/sys/dev/mfi/mfireg.h @@ -234,6 +234,9 @@ typedef enum { MFI_DCMD_BBU_GET_STATUS = 0x05010000, MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000, MFI_DCMD_BBU_GET_DESIGN_INFO = 0x05030000, + MFI_DCMD_BBU_START_LEARN = 0x05040000, + MFI_DCMD_BBU_GET_PROP = 0x05050100, + MFI_DCMD_BBU_SET_PROP = 0x05050200, MFI_DCMD_CLUSTER = 0x08000000, MFI_DCMD_CLUSTER_RESET_ALL = 0x08010100, MFI_DCMD_CLUSTER_RESET_LD = 0x08010200 @@ -1367,6 +1370,15 @@ struct mfi_bbu_state { uint8_t reserved[21]; } __packed; +struct mfi_bbu_properties { + uint32_t auto_learn_period; + uint32_t next_learn_time; + uint8_t learn_delay_interval; + uint8_t auto_learn_mode; + uint8_t bbu_mode; + uint8_t reserved[21]; +} __packed; + union mfi_bbu_status_detail { struct mfi_ibbu_state ibbu; struct mfi_bbu_state bbu; 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..86a9722 --- /dev/null +++ b/usr.sbin/mfiutil/mfi_bbu.c @@ -0,0 +1,252 @@ +/*- + * 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. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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)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..cb160fc 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,32 @@ 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 .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 \n"); + fprintf(stderr, " start learn - start a BBU relearn\n"); + fprintf(stderr, " bbu - 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); From owner-freebsd-scsi@FreeBSD.ORG Mon Mar 4 11:06:49 2013 Return-Path: Delivered-To: freebsd-scsi@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 5100FF28 for ; Mon, 4 Mar 2013 11:06:49 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 41283E62 for ; Mon, 4 Mar 2013 11:06:49 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.6/8.14.6) with ESMTP id r24B6nGP038896 for ; Mon, 4 Mar 2013 11:06:49 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.6/8.14.6/Submit) id r24B6m29038894 for freebsd-scsi@FreeBSD.org; Mon, 4 Mar 2013 11:06:48 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 4 Mar 2013 11:06:48 GMT Message-Id: <201303041106.r24B6m29038894@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-scsi@FreeBSD.org Subject: Current problem reports assigned to freebsd-scsi@FreeBSD.org X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Mar 2013 11:06:49 -0000 Note: to view an individual PR, use: http://www.freebsd.org/cgi/query-pr.cgi?pr=(number). The following is a listing of current problems submitted by FreeBSD users. These represent problem reports covering all versions including experimental development code and obsolete releases. S Tracker Resp. Description -------------------------------------------------------------------------------- o kern/171650 scsi [da] da(4) driver does not recognize end of cciss (Sma o kern/169403 scsi [cam] [patch] CAM layer, I/O starvation, no fairness o kern/165982 scsi [mpt] mpt instability, drive resets, and losses on Fre o kern/165740 scsi [cam] SCSI code must drain callbacks before free o kern/163713 scsi [aic7xxx] [patch] Add Adaptec29329LPE to aic79xx_pci.c o kern/162256 scsi [mpt] QUEUE FULL EVENT and 'mpt_cam_event: 0x0' o kern/161809 scsi [cam] [patch] set kern.cam.boot_delay via build option o kern/157770 scsi [iscsi] [panic] iscsi_initiator panic o kern/154432 scsi [xpt] run_interrupt_driven_hooks: still waiting after o kern/153514 scsi [cam] [panic] CAM related panic o docs/151336 scsi Missing documentation of scsi_ and ata_ functions in c s kern/149927 scsi [cam] hard drive not stopped before removing power dur o kern/148083 scsi [aac] Strange device reporting o kern/147704 scsi [mpt] sys/dev/mpt: new chip revision, partially unsupp o kern/145768 scsi [mpt] can't perform I/O on SAS based SAN disk in freeb o kern/144648 scsi [aac] Strange values of speed and bus width in dmesg o kern/142351 scsi [mpt] LSILogic driver performance problems o kern/134488 scsi [mpt] MPT SCSI driver probes max. 8 LUNs per device o kern/132206 scsi [mpt] system panics on boot when mirroring and 2nd dri o kern/130621 scsi [mpt] tranfer rate is inscrutable slow when use lsi213 o kern/129602 scsi [ahd] ahd(4) gets confused and wedges SCSI bus o kern/128452 scsi [sa] [panic] Accessing SCSI tape drive randomly crashe o kern/128245 scsi [scsi] "inquiry data fails comparison at DV1 step" [re o kern/127927 scsi [isp] isp(4) target driver crashes kernel when set up o kern/127717 scsi [ata] [patch] [request] - support write cache toggling o kern/123674 scsi [ahc] ahc driver dumping o kern/123520 scsi [ahd] unable to boot from net while using ahd o sparc/121676 scsi [iscsi] iscontrol do not connect iscsi-target on sparc o kern/120487 scsi [sg] scsi_sg incompatible with scanners o kern/120247 scsi [mpt] FreeBSD 6.3 and LSI Logic 1030 = only 3.300MB/s o kern/114597 scsi [sym] System hangs at SCSI bus reset with dual HBAs o kern/110847 scsi [ahd] Tyan U320 onboard problem with more than 3 disks o kern/99954 scsi [ahc] reading from DVD failes on 6.x [regression] o kern/92798 scsi [ahc] SCSI problem with timeouts o kern/90282 scsi [sym] SCSI bus resets cause loss of ch device o kern/76178 scsi [ahd] Problem with ahd and large SCSI Raid system o kern/74627 scsi [ahc] [hang] Adaptec 2940U2W Can't boot 5.3 s kern/61165 scsi [panic] kernel page fault after calling cam_send_ccb o kern/60641 scsi [sym] Sporadic SCSI bus resets with 53C810 under load o kern/60598 scsi wire down of scsi devices conflicts with config s kern/57398 scsi [mly] Current fails to install on mly(4) based RAID di o kern/52638 scsi [panic] SCSI U320 on SMP server won't run faster than o kern/44587 scsi dev/dpt/dpt.h is missing defines required for DPT_HAND o kern/39388 scsi ncr/sym drivers fail with 53c810 and more than 256MB m o kern/35234 scsi World access to /dev/pass? (for scanner) requires acce 45 problems total. From owner-freebsd-scsi@FreeBSD.ORG Fri Mar 8 00:07:11 2013 Return-Path: Delivered-To: freebsd-scsi@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 96DA0DDF; Fri, 8 Mar 2013 00:07:11 +0000 (UTC) (envelope-from seanwbruno@gmail.com) Received: from mail-pa0-f45.google.com (mail-pa0-f45.google.com [209.85.220.45]) by mx1.freebsd.org (Postfix) with ESMTP id 5AA4FC2E; Fri, 8 Mar 2013 00:07:11 +0000 (UTC) Received: by mail-pa0-f45.google.com with SMTP id kl14so852354pab.4 for ; Thu, 07 Mar 2013 16:07:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:subject:from:to:cc:in-reply-to:references:content-type :date:message-id:mime-version:x-mailer:content-transfer-encoding; bh=QQ4t7JdR0BFU4ZFzC+C7ZJFzoHgxEYvFSCOkFyQlmLo=; b=TNu1QdhhIGIJc2l8l51Ni1OHbPj10Q1G9yaEbhaSHSWqmP4fh5b/4//zTURdRGetAZ eNUEQHvaj/J77QpHNXRsv6LUZ0kL7fteSNw7VZ3y4A7R/QSWFtL9U82M2kY1KN+bTPFe 5q519+TPAfx61HU+6ZDgLhMt+7zQ/7YvUg8ACzMR4iUv6A1t1hJhctaTEDnaOWL9w3gw /XsT+cmd/bWnYMU5akUeDe9MsdvuFMms+aFO5IsV/ZhhqSsCEwh9YqLskIxeJNZdYIZK imPt47g+tivAOy0mqwqZOKz8xXl6MkcH68O8Pn2JfdCsc+1qmlL4gJeupSBV0b+yQWa8 L37A== X-Received: by 10.68.134.201 with SMTP id pm9mr197858pbb.182.1362701230672; Thu, 07 Mar 2013 16:07:10 -0800 (PST) Received: from [10.73.160.242] (nat-dip7.cfw-a-gci.corp.yahoo.com. [209.131.62.116]) by mx.google.com with ESMTPS id kb3sm3298112pbc.21.2013.03.07.16.07.07 (version=SSLv3 cipher=RC4-SHA bits=128/128); Thu, 07 Mar 2013 16:07:08 -0800 (PST) Subject: Re: adding BBU relearn support to mfiutil From: Sean Bruno To: Mark Johnston In-Reply-To: <20130304033836.GA33631@oddish> References: <20130304033836.GA33631@oddish> Content-Type: text/plain; charset="us-ascii" Date: Thu, 07 Mar 2013 16:07:05 +0000 Message-ID: <1362672425.84238.14.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.32.1 FreeBSD GNOME Team Port Content-Transfer-Encoding: 7bit Cc: freebsd-scsi@freebsd.org X-BeenThere: freebsd-scsi@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SCSI subsystem List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Mar 2013 00:07:11 -0000 Hey, I saw this. :-) Trying to get through the pile of things to take a look at it. Sean On Sun, 2013-03-03 at 22:38 -0500, Mark Johnston wrote: > Hi Everyone, > > I recently needed to add a couple of features to mfiutil related to BBU > relearning. I've pasted a patch below which > > 1. adds extra fields to the output of "mfiutil show battery" showing BBU > properties. This is essentially the output of > > # MegaCli -AdpBbuInfo -GetBbuProperties -aLL > > and consists of info about battery learning: the learn period, the > time at which the controller will start the next relearn, and the BBU > mode (which indicates whether the battery supports transparent > relearning). > > 2. adds a couple of subcommands under "mfiutil bbu" which lets users set > the BBU properties which can be set by MegaCli. > > 3. adds a command "mfiutil start learn" which immediately kicks off a > battery relearn. > > These changes grew out of concern about the fact that the controller > write cache is set to write-through mode during a relearn period (which > usually lasts for several hours). This ended up causing some mysterious > and intermittent performance issues, so I needed a way of getting more > info about what was going on (using MegaCli isn't really an option for > several reasons). Some BBUs support transparent relearning, which > basically means that the controller write cache doesn't get turned off > during a relearn. However, LSI's default config doesn't enable it, and > now mfiutil can be used to do that (through "mfiutil bbu bbu-mode"). > > I was hoping someone would be able to review the patch. If anyone's able > and willing to test it, I'd very much appreciate feedback from that. > > Thanks! > -Mark > > diff --git a/sys/dev/mfi/mfi_debug.c b/sys/dev/mfi/mfi_debug.c > index 4aec4f7..be42ec0 100644 > --- a/sys/dev/mfi/mfi_debug.c > +++ b/sys/dev/mfi/mfi_debug.c > @@ -168,6 +168,15 @@ mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) > case MFI_DCMD_LD_MAP_GET_INFO: > opcode = "LD_MAP_GET_INFO"; > break; > + case MFI_DCMD_BBU_START_LEARN: > + opcode = "BBU_START_LEARN"; > + break; > + case MFI_DCMD_BBU_GET_PROP: > + opcode = "BBU_GET_PROP"; > + break; > + case MFI_DCMD_BBU_SET_PROP: > + opcode = "BBU_SET_PROP"; > + break; > default: > opcode = "UNKNOWN"; > break; > diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h > index 52ddafe..8f88f10 100644 > --- a/sys/dev/mfi/mfireg.h > +++ b/sys/dev/mfi/mfireg.h > @@ -234,6 +234,9 @@ typedef enum { > MFI_DCMD_BBU_GET_STATUS = 0x05010000, > MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000, > MFI_DCMD_BBU_GET_DESIGN_INFO = 0x05030000, > + MFI_DCMD_BBU_START_LEARN = 0x05040000, > + MFI_DCMD_BBU_GET_PROP = 0x05050100, > + MFI_DCMD_BBU_SET_PROP = 0x05050200, > MFI_DCMD_CLUSTER = 0x08000000, > MFI_DCMD_CLUSTER_RESET_ALL = 0x08010100, > MFI_DCMD_CLUSTER_RESET_LD = 0x08010200 > @@ -1367,6 +1370,15 @@ struct mfi_bbu_state { > uint8_t reserved[21]; > } __packed; > > +struct mfi_bbu_properties { > + uint32_t auto_learn_period; > + uint32_t next_learn_time; > + uint8_t learn_delay_interval; > + uint8_t auto_learn_mode; > + uint8_t bbu_mode; > + uint8_t reserved[21]; > +} __packed; > + > union mfi_bbu_status_detail { > struct mfi_ibbu_state ibbu; > struct mfi_bbu_state bbu; > 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..86a9722 > --- /dev/null > +++ b/usr.sbin/mfiutil/mfi_bbu.c > @@ -0,0 +1,252 @@ > +/*- > + * 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. > + * 3. The names of the authors may not be used to endorse or promote > + * products derived from this software without specific prior written > + * permission. > + * > + * 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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#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 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)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..cb160fc 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,32 @@ 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 > .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 \n"); > + fprintf(stderr, " start learn - start a BBU relearn\n"); > + fprintf(stderr, " bbu - 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); > _______________________________________________ > freebsd-scsi@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-scsi > To unsubscribe, send any mail to "freebsd-scsi-unsubscribe@freebsd.org"