diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2010-05-19 07:26:03 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2010-05-19 07:26:03 +0000 |
commit | 77f46605b921b22444cdb100b2a89118ddef8bc8 (patch) | |
tree | 9eaf3b523b7abcb0fe7a35e8e6569920243cd6e3 | |
parent | 44d2ccb7f573e8d9ceff2c10422122357ebde9b1 (diff) |
the virtual scsi disks that mpi(4) presents dont grok modifications to the
mode pages that control the caches. this adds code that talks to the mpi
chip directly on behalf of those disks so you can enable write caching on
them.
-rw-r--r-- | sys/dev/ic/mpi.c | 124 | ||||
-rw-r--r-- | sys/dev/ic/mpireg.h | 103 |
2 files changed, 206 insertions, 21 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index 786eaf680e1..b5570fa1d0f 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.148 2010/05/16 20:33:59 nicm Exp $ */ +/* $OpenBSD: mpi.c,v 1.149 2010/05/19 07:26:01 dlg Exp $ */ /* * Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org> @@ -30,6 +30,7 @@ #include <sys/mutex.h> #include <sys/rwlock.h> #include <sys/sensors.h> +#include <sys/dkio.h> #include <machine/bus.h> @@ -152,6 +153,9 @@ int mpi_req_cfg_header(struct mpi_softc *, u_int8_t, int mpi_req_cfg_page(struct mpi_softc *, u_int32_t, int, void *, int, void *, size_t); +int mpi_ioctl_cache(struct scsi_link *, u_long, + struct dk_cache *); + #if NBIO > 0 int mpi_bio_get_pg0_raid(struct mpi_softc *, int); int mpi_ioctl(struct device *, u_long, caddr_t); @@ -2685,10 +2689,120 @@ mpi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag, DNPRINTF(MPI_D_IOCTL, "%s: mpi_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 (ISSET(link->flags, SDEV_VIRTUAL)) { + return (mpi_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 +mpi_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc) +{ + struct mpi_softc *sc = (struct mpi_softc *)link->adapter_softc; + struct mpi_ccb *ccb; + int len, rv; + u_int32_t address; + struct mpi_cfg_hdr hdr; + struct mpi_cfg_raid_vol_pg0 *rpg0; + int enabled; + struct mpi_msg_raid_action_request *req; + struct mpi_msg_raid_action_reply *rep; + struct mpi_raid_settings settings; + + address = link->target; + + rv = mpi_req_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, + address, 0, &hdr); + if (rv != 0) + return (EIO); + + len = sizeof *rpg0 + sc->sc_vol_page->max_physdisks * + sizeof(struct mpi_cfg_raid_vol_pg0_physdisk); + rpg0 = malloc(len, M_TEMP, M_WAITOK); + + if (mpi_req_cfg_page(sc, address, 0, &hdr, 1, rpg0, len) != 0) { + DNPRINTF(MPI_D_RAID, "%s: can't get RAID vol cfg page 0\n", + DEVNAME(sc)); + rv = EIO; + goto done; + } + + enabled = ISSET(letoh16(rpg0->settings.volume_settings), + MPI_CFG_RAID_VOL_0_SETTINGS_WRITE_CACHE_EN) ? 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; + + settings = rpg0->settings; + if (dc->wrcache) { + SET(settings.volume_settings, + htole16(MPI_CFG_RAID_VOL_0_SETTINGS_WRITE_CACHE_EN)); + } else { + CLR(settings.volume_settings, + htole16(MPI_CFG_RAID_VOL_0_SETTINGS_WRITE_CACHE_EN)); + } + + ccb = scsi_io_get(&sc->sc_iopool, 0); + if (ccb == NULL) { + rv = ENOMEM; + goto done; + } + + req = ccb->ccb_cmd; + req->function = MPI_FUNCTION_RAID_ACTION; + req->action = MPI_MSG_RAID_ACTION_CH_VOL_SETTINGS; + req->vol_id = rpg0->volume_id; + req->vol_bus = rpg0->volume_bus; + req->msg_context = htole32(ccb->ccb_id); + + memcpy(&req->data_word, &settings, sizeof(req->data_word)); + + ccb->ccb_done = mpi_empty_done; + mpi_wait(sc, ccb); + + rep = (struct mpi_msg_raid_action_reply *)ccb->ccb_rcb; + if (rep == NULL) + panic("%s: raid volume settings change failed", DEVNAME(sc)); + + switch (letoh16(rep->action_status)) { + case MPI_RAID_ACTION_STATUS_OK: + rv = 0; + break; + default: + rv = EIO; + break; + } + + mpi_push_reply(sc, ccb->ccb_rcb); + scsi_io_put(&sc->sc_iopool, ccb); + +done: + free(rpg0, M_TEMP); + return (rv); } #if NBIO > 0 diff --git a/sys/dev/ic/mpireg.h b/sys/dev/ic/mpireg.h index 7a46ab38043..383334feb91 100644 --- a/sys/dev/ic/mpireg.h +++ b/sys/dev/ic/mpireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpireg.h,v 1.37 2009/10/23 00:52:55 dlg Exp $ */ +/* $OpenBSD: mpireg.h,v 1.38 2010/05/19 07:26:02 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -934,6 +934,73 @@ struct mpi_msg_scsi_task_reply { u_int32_t termination_count; } __packed; +struct mpi_msg_raid_action_request { + u_int8_t action; +#define MPI_MSG_RAID_ACTION_STATUS (0x00) +#define MPI_MSG_RAID_ACTION_INDICATOR_STRUCT (0x01) +#define MPI_MSG_RAID_ACTION_CREATE_VOLUME (0x02) +#define MPI_MSG_RAID_ACTION_DELETE_VOLUME (0x03) +#define MPI_MSG_RAID_ACTION_DISABLE_VOLUME (0x04) +#define MPI_MSG_RAID_ACTION_ENABLE_VOLUME (0x05) +#define MPI_MSG_RAID_ACTION_QUIESCE_PHYSIO (0x06) +#define MPI_MSG_RAID_ACTION_ENABLE_PHYSIO (0x07) +#define MPI_MSG_RAID_ACTION_CH_VOL_SETTINGS (0x08) +#define MPI_MSG_RAID_ACTION_PHYSDISK_OFFLINE (0x0a) +#define MPI_MSG_RAID_ACTION_PHYSDISK_ONLINE (0x0b) +#define MPI_MSG_RAID_ACTION_CH_PHYSDISK_SETTINGS (0x0c) +#define MPI_MSG_RAID_ACTION_CREATE_PHYSDISK (0x0d) +#define MPI_MSG_RAID_ACTION_DELETE_PHYSDISK (0x0e) +#define MPI_MSG_RAID_ACTION_PHYSDISK_FAIL (0x0f) +#define MPI_MSG_RAID_ACTION_ACTIVATE_VOLUME (0x11) +#define MPI_MSG_RAID_ACTION_DEACTIVATE_VOLUME (0x12) +#define MPI_MSG_RAID_ACTION_SET_RESYNC_RATE (0x13) +#define MPI_MSG_RAID_ACTION_SET_SCRUB_RATE (0x14) +#define MPI_MSG_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) +#define MPI_MSG_RAID_ACTION_SET_VOL_NAME (0x16) + u_int8_t _reserved1; + u_int8_t chain_offset; + u_int8_t function; + + u_int8_t vol_id; + u_int8_t vol_bus; + u_int8_t phys_disk_num; + u_int8_t message_flags; + + u_int32_t msg_context; + + u_int32_t _reserved2; + + u_int32_t data_word; + u_int32_t data_sge; +} __packed; + +struct mpi_msg_raid_action_reply { + u_int8_t action; + u_int8_t _reserved1; + u_int8_t message_length; + u_int8_t function; + + u_int8_t vol_id; + u_int8_t vol_bus; + u_int8_t phys_disk_num; + u_int8_t message_flags; + + u_int32_t message_context; + + u_int16_t action_status; +#define MPI_RAID_ACTION_STATUS_OK (0x0000) +#define MPI_RAID_ACTION_STATUS_INVALID (0x0001) +#define MPI_RAID_ACTION_STATUS_FAILURE (0x0002) +#define MPI_RAID_ACTION_STATUS_IN_PROGRESS (0x0004) + u_int16_t ioc_status; + + u_int32_t ioc_log_info; + + u_int32_t volume_status; + + u_int32_t action_data; +} __packed; + struct mpi_cfg_hdr { u_int8_t page_version; u_int8_t page_length; @@ -1355,6 +1422,20 @@ struct mpi_cfg_fc_device_pg0 { u_int8_t current_bus; } __packed; +struct mpi_raid_settings { + u_int16_t volume_settings; +#define MPI_CFG_RAID_VOL_0_SETTINGS_WRITE_CACHE_EN (1<<0) +#define MPI_CFG_RAID_VOL_0_SETTINGS_OFFLINE_SMART_ERR (1<<1) +#define MPI_CFG_RAID_VOL_0_SETTINGS_OFFLINE_SMART (1<<2) +#define MPI_CFG_RAID_VOL_0_SETTINGS_AUTO_SWAP (1<<3) +#define MPI_CFG_RAID_VOL_0_SETTINGS_HI_PRI_RESYNC (1<<4) +#define MPI_CFG_RAID_VOL_0_SETTINGS_PROD_SUFFIX (1<<5) +#define MPI_CFG_RAID_VOL_0_SETTINGS_FAST_SCRUB (1<<6) /* obsolete */ +#define MPI_CFG_RAID_VOL_0_SETTINGS_DEFAULTS (1<<15) + u_int8_t hot_spare_pool; + u_int8_t reserved2; +} __packed; + struct mpi_cfg_raid_vol_pg0 { struct mpi_cfg_hdr config_header; @@ -1374,29 +1455,19 @@ struct mpi_cfg_raid_vol_pg0 { #define MPI_CFG_RAID_VOL_0_STATE_DEGRADED (0x01) #define MPI_CFG_RAID_VOL_0_STATE_FAILED (0x02) #define MPI_CFG_RAID_VOL_0_STATE_MISSING (0x03) - u_int16_t reserved1; + u_int16_t _reserved1; - u_int16_t volume_settings; -#define MPI_CFG_RAID_VOL_0_SETTINGS_WRITE_CACHE_EN (1<<0) -#define MPI_CFG_RAID_VOL_0_SETTINGS_OFFLINE_SMART_ERR (1<<1) -#define MPI_CFG_RAID_VOL_0_SETTINGS_OFFLINE_SMART (1<<2) -#define MPI_CFG_RAID_VOL_0_SETTINGS_AUTO_SWAP (1<<3) -#define MPI_CFG_RAID_VOL_0_SETTINGS_HI_PRI_RESYNC (1<<4) -#define MPI_CFG_RAID_VOL_0_SETTINGS_PROD_SUFFIX (1<<5) -#define MPI_CFG_RAID_VOL_0_SETTINGS_FAST_SCRUB (1<<6) /* obsolete */ -#define MPI_CFG_RAID_VOL_0_SETTINGS_DEFAULTS (1<<15) - u_int8_t hot_spare_pool; - u_int8_t reserved2; + struct mpi_raid_settings settings; u_int32_t max_lba; - u_int32_t reserved3; + u_int32_t _reserved2; u_int32_t stripe_size; - u_int32_t reserved4; + u_int32_t _reserved3; - u_int32_t reserved5; + u_int32_t _reserved4; u_int8_t num_phys_disks; u_int8_t data_scrub_rate; |