summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-02-21 09:36:16 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-02-21 09:36:16 +0000
commit590f5dcb7b1dbc0d15d4529aecd26762d29442d6 (patch)
tree6d70b0ae74da503253557139149e55548974b860 /sys/dev/pci
parent8bc9dac2d41c48fe6bad2aa64c9127f6e7f6239e (diff)
usage: mt [-f device] command [count]
most of the work and bug fixes were done by mikeb@, i put it in ioctl form. ok mikeb@ and miod@ tested by me an earlier revision was tested by Łukasz Czarniecki who also reported the problem in the first place.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/mpii.c169
1 files changed, 163 insertions, 6 deletions
diff --git a/sys/dev/pci/mpii.c b/sys/dev/pci/mpii.c
index c313a5bdbee..44f37ab1f85 100644
--- a/sys/dev/pci/mpii.c
+++ b/sys/dev/pci/mpii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpii.c,v 1.37 2010/12/29 03:55:09 dlg Exp $ */
+/* $OpenBSD: mpii.c,v 1.38 2011/02/21 09:36:15 dlg Exp $ */
/*
* Copyright (c) 2010 Mike Belopuhov <mkb@crypt.org.ru>
* Copyright (c) 2009 James Giannoules
@@ -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 *, u_int32_t, int,
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