From 95e852e1ef165560e85d3012127068c8f08b19a1 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Tue, 8 Jan 2008 12:01:07 -0800 Subject: [PATCH] [SCSI] aacraid: add parameter to control FUA and SYNCHRONIZE_CACHE policy aacraid.cache parameter, Disable Queue Flush commands: bit 0 - Disable FUA in WRITE SCSI commands bit 1 - Disable SYNCHRONIZE_CACHE SCSI command bit 2 - Disable only if Battery not protecting adapter supplied Cache e.g.: aacraid.cache=7 will disable the FUA and SYNCHRONIZE_CACHE commands if the adapter has reported that it's cache is battery backed up. This parameter permits experimentation with tradeoffs between performance and caching policy. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 36 ++++++++++++++++++++++------------ drivers/scsi/aacraid/aacraid.h | 2 ++ drivers/scsi/aacraid/commsup.c | 4 ++++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index cef764eba307..43d6aff460d2 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -144,6 +144,7 @@ static char *aac_get_status_string(u32 status); */ static int nondasd = -1; +static int aac_cache = 0; static int dacmode = -1; int aac_commit = -1; @@ -152,6 +153,8 @@ int aif_timeout = 120; module_param(nondasd, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); +module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n\tbit 0 - Disable FUA in WRITE SCSI commands\n\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n\tbit 2 - Disable only if Battery not protecting Cache"); module_param(dacmode, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on"); module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR); @@ -1013,7 +1016,8 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); writecmd->count = cpu_to_le32(count<<9); writecmd->cid = cpu_to_le16(scmd_id(cmd)); - writecmd->flags = fua ? + writecmd->flags = (fua && ((aac_cache & 5) != 1) && + (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) : cpu_to_le16(IO_TYPE_WRITE); writecmd->bpTotal = 0; @@ -1325,11 +1329,11 @@ int aac_get_adapter_info(struct aac_dev* dev) } } + dev->cache_protected = 0; dev->nondasd_support = 0; dev->raid_scsi_mode = 0; - if(dev->adapter_info.options & AAC_OPT_NONDASD){ + if(dev->adapter_info.options & AAC_OPT_NONDASD) dev->nondasd_support = 1; - } /* * If the firmware supports ROMB RAID/SCSI mode and we are currently @@ -1351,10 +1355,9 @@ int aac_get_adapter_info(struct aac_dev* dev) printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled\n", dev->name, dev->id); - if(nondasd != -1) { + if (nondasd != -1) dev->nondasd_support = (nondasd!=0); - } - if(dev->nondasd_support != 0){ + if(dev->nondasd_support != 0) { printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id); } @@ -2106,7 +2109,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected bit 4: 0/1 = FUA enabled */ - if (dev->raw_io_interface) + if (dev->raw_io_interface && ((aac_cache & 5) != 1)) mode_buf[2] = 0x10; mode_buf[3] = 0; /* Block descriptor length */ if (((scsicmd->cmnd[2] & 0x3f) == 8) || @@ -2114,7 +2117,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[0] = 6; mode_buf[4] = 8; mode_buf[5] = 1; - mode_buf[6] = 0x04; /* WCE */ + mode_buf[6] = ((aac_cache & 6) == 2) + ? 0 : 0x04; /* WCE */ mode_buf_length = 7; if (mode_buf_length > scsicmd->cmnd[4]) mode_buf_length = scsicmd->cmnd[4]; @@ -2137,7 +2141,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected bit 4: 0/1 = FUA enabled */ - if (dev->raw_io_interface) + if (dev->raw_io_interface && ((aac_cache & 5) != 1)) mode_buf[3] = 0x10; mode_buf[4] = 0; /* reserved */ mode_buf[5] = 0; /* reserved */ @@ -2148,7 +2152,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) mode_buf[1] = 9; mode_buf[8] = 8; mode_buf[9] = 1; - mode_buf[10] = 0x04; /* WCE */ + mode_buf[10] = ((aac_cache & 6) == 2) + ? 0 : 0x04; /* WCE */ mode_buf_length = 11; if (mode_buf_length > scsicmd->cmnd[8]) mode_buf_length = scsicmd->cmnd[8]; @@ -2224,9 +2229,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) return aac_write(scsicmd); case SYNCHRONIZE_CACHE: + if (((aac_cache & 6) == 6) && dev->cache_protected) { + scsicmd->result = DID_OK << 16 | + COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + scsicmd->scsi_done(scsicmd); + return 0; + } /* Issue FIB to tell Firmware to flush it's cache */ - return aac_synchronize(scsicmd); - + if ((aac_cache & 6) != 2) + return aac_synchronize(scsicmd); + /* FALLTHRU */ default: /* * Unhandled commands diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 734623af9c45..7bb3d9fde713 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1016,6 +1016,7 @@ struct aac_dev * lets break them out so we don't have to do an AND to check them */ u8 nondasd_support; + u8 cache_protected; u8 dac_support; u8 raid_scsi_mode; u8 comm_interface; @@ -1770,6 +1771,7 @@ extern struct aac_common aac_config; #define AifEnConfigChange 3 /* Adapter configuration change */ #define AifEnContainerChange 4 /* Container configuration change */ #define AifEnDeviceFailure 5 /* SCSI device failed */ +#define AifEnBatteryEvent 14 /* Change in Battery State */ #define AifEnAddContainer 15 /* A new array was created */ #define AifEnDeleteContainer 16 /* A container was deleted */ #define AifEnExpEvent 23 /* Firmware Event Log */ diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 53d415e812ee..81cdac166d4b 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -849,6 +849,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) case AifCmdEventNotify: switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { + case AifEnBatteryEvent: + dev->cache_protected = + (((__le32 *)aifcmd->data)[1] == cpu_to_le32(3)); + break; /* * Add an Array. */ -- 2.20.1