aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid/aachba.c
diff options
context:
space:
mode:
authorSalyzyn, Mark <mark_salyzyn@adaptec.com>2007-05-18 14:51:34 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-22 11:52:21 -0400
commit9d399cc7feac3faf66768566e04e16c750aad25f (patch)
tree52e4102a2f4fe12f4f730873525f07c1e00e86f4 /drivers/scsi/aacraid/aachba.c
parent0f06bb34f2dcd0c72aac7777995ef7cb733496e8 (diff)
[SCSI] aacraid: add support for FUA
Back in the beginning of last year we disabled mode page 8 and mode page 3f requests through device quirk bits instead of enhancing the driver to respond to these mode pages because there was no apparent added value. The Firmware that supports the new communication commands supports the ability to force a write around of the adapter cache on a command by command basis. In the attached patch we enable mode page 8 and 3f and spoof the results as needed in order to *convince* the layers above to submit writes with the FUA (Force Unit Attention) bit set if the file system or application requires it, if the Firmware supports the write through, or instead to submit a SYNCHRONIZE_CACHE if the Firmware does not. The added value here is for file systems that benefit from this functionality and for clustering or redundancy scenarios. Caveats: By convince, we are responding with a minimal short 3 byte content mode page 8, with only the data the SCSI layer needs and that we can fill confidently. Applications that require the customarily larger mode page 8 results may be confused by this(?). The FUA, or the SYNCHRONIZE_CACHE only affect the cache on the controller. Our firmware by default ensure that the underlying physical drives of the array have their cache turned off so normally this is not a problem. This attached patch is against current scsi-misc-2.6 and was unit tested on RHEL5. Since this is a feature enhancement, it should not be considered for any current stabilization efforts. Signed-off-by: Mark Salyzyn <aacraid@adaptec.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r--drivers/scsi/aacraid/aachba.c62
1 files changed, 49 insertions, 13 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 1e82c69b36b0..a333e62fc487 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -822,7 +822,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
822 readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); 822 readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
823 readcmd->count = cpu_to_le32(count<<9); 823 readcmd->count = cpu_to_le32(count<<9);
824 readcmd->cid = cpu_to_le16(scmd_id(cmd)); 824 readcmd->cid = cpu_to_le16(scmd_id(cmd));
825 readcmd->flags = cpu_to_le16(1); 825 readcmd->flags = cpu_to_le16(IO_TYPE_READ);
826 readcmd->bpTotal = 0; 826 readcmd->bpTotal = 0;
827 readcmd->bpComplete = 0; 827 readcmd->bpComplete = 0;
828 828
@@ -901,7 +901,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32
901 (void *) cmd); 901 (void *) cmd);
902} 902}
903 903
904static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) 904static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
905{ 905{
906 u16 fibsize; 906 u16 fibsize;
907 struct aac_raw_io *writecmd; 907 struct aac_raw_io *writecmd;
@@ -911,7 +911,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
911 writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); 911 writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
912 writecmd->count = cpu_to_le32(count<<9); 912 writecmd->count = cpu_to_le32(count<<9);
913 writecmd->cid = cpu_to_le16(scmd_id(cmd)); 913 writecmd->cid = cpu_to_le16(scmd_id(cmd));
914 writecmd->flags = 0; 914 writecmd->flags = fua ?
915 cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
916 cpu_to_le16(IO_TYPE_WRITE);
915 writecmd->bpTotal = 0; 917 writecmd->bpTotal = 0;
916 writecmd->bpComplete = 0; 918 writecmd->bpComplete = 0;
917 919
@@ -930,7 +932,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u
930 (void *) cmd); 932 (void *) cmd);
931} 933}
932 934
933static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) 935static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
934{ 936{
935 u16 fibsize; 937 u16 fibsize;
936 struct aac_write64 *writecmd; 938 struct aac_write64 *writecmd;
@@ -961,7 +963,7 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba,
961 (void *) cmd); 963 (void *) cmd);
962} 964}
963 965
964static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) 966static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
965{ 967{
966 u16 fibsize; 968 u16 fibsize;
967 struct aac_write *writecmd; 969 struct aac_write *writecmd;
@@ -1495,6 +1497,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
1495{ 1497{
1496 u64 lba; 1498 u64 lba;
1497 u32 count; 1499 u32 count;
1500 int fua;
1498 int status; 1501 int status;
1499 struct aac_dev *dev; 1502 struct aac_dev *dev;
1500 struct fib * cmd_fibcontext; 1503 struct fib * cmd_fibcontext;
@@ -1509,6 +1512,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
1509 count = scsicmd->cmnd[4]; 1512 count = scsicmd->cmnd[4];
1510 if (count == 0) 1513 if (count == 0)
1511 count = 256; 1514 count = 256;
1515 fua = 0;
1512 } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ 1516 } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
1513 dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); 1517 dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd)));
1514 1518
@@ -1521,6 +1525,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
1521 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; 1525 (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
1522 count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | 1526 count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
1523 (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; 1527 (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
1528 fua = scsicmd->cmnd[1] & 0x8;
1524 } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ 1529 } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
1525 dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); 1530 dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd)));
1526 1531
@@ -1528,10 +1533,12 @@ static int aac_write(struct scsi_cmnd * scsicmd)
1528 | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; 1533 | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
1529 count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) 1534 count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
1530 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; 1535 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
1536 fua = scsicmd->cmnd[1] & 0x8;
1531 } else { 1537 } else {
1532 dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); 1538 dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd)));
1533 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; 1539 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
1534 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; 1540 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
1541 fua = scsicmd->cmnd[1] & 0x8;
1535 } 1542 }
1536 dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", 1543 dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
1537 smp_processor_id(), (unsigned long long)lba, jiffies)); 1544 smp_processor_id(), (unsigned long long)lba, jiffies));
@@ -1546,7 +1553,7 @@ static int aac_write(struct scsi_cmnd * scsicmd)
1546 return 0; 1553 return 0;
1547 } 1554 }
1548 1555
1549 status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count); 1556 status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
1550 1557
1551 /* 1558 /*
1552 * Check that the command queued to the controller 1559 * Check that the command queued to the controller
@@ -1883,15 +1890,29 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
1883 1890
1884 case MODE_SENSE: 1891 case MODE_SENSE:
1885 { 1892 {
1886 char mode_buf[4]; 1893 char mode_buf[7];
1894 int mode_buf_length = 4;
1887 1895
1888 dprintk((KERN_DEBUG "MODE SENSE command.\n")); 1896 dprintk((KERN_DEBUG "MODE SENSE command.\n"));
1889 mode_buf[0] = 3; /* Mode data length */ 1897 mode_buf[0] = 3; /* Mode data length */
1890 mode_buf[1] = 0; /* Medium type - default */ 1898 mode_buf[1] = 0; /* Medium type - default */
1891 mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ 1899 mode_buf[2] = 0; /* Device-specific param,
1900 bit 8: 0/1 = write enabled/protected
1901 bit 4: 0/1 = FUA enabled */
1902 if (dev->raw_io_interface)
1903 mode_buf[2] = 0x10;
1892 mode_buf[3] = 0; /* Block descriptor length */ 1904 mode_buf[3] = 0; /* Block descriptor length */
1893 1905 if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
1894 aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); 1906 ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
1907 mode_buf[0] = 6;
1908 mode_buf[4] = 8;
1909 mode_buf[5] = 1;
1910 mode_buf[6] = 0x04; /* WCE */
1911 mode_buf_length = 7;
1912 if (mode_buf_length > scsicmd->cmnd[4])
1913 mode_buf_length = scsicmd->cmnd[4];
1914 }
1915 aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
1895 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; 1916 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1896 scsicmd->scsi_done(scsicmd); 1917 scsicmd->scsi_done(scsicmd);
1897 1918
@@ -1899,18 +1920,33 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
1899 } 1920 }
1900 case MODE_SENSE_10: 1921 case MODE_SENSE_10:
1901 { 1922 {
1902 char mode_buf[8]; 1923 char mode_buf[11];
1924 int mode_buf_length = 8;
1903 1925
1904 dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); 1926 dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n"));
1905 mode_buf[0] = 0; /* Mode data length (MSB) */ 1927 mode_buf[0] = 0; /* Mode data length (MSB) */
1906 mode_buf[1] = 6; /* Mode data length (LSB) */ 1928 mode_buf[1] = 6; /* Mode data length (LSB) */
1907 mode_buf[2] = 0; /* Medium type - default */ 1929 mode_buf[2] = 0; /* Medium type - default */
1908 mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ 1930 mode_buf[3] = 0; /* Device-specific param,
1931 bit 8: 0/1 = write enabled/protected
1932 bit 4: 0/1 = FUA enabled */
1933 if (dev->raw_io_interface)
1934 mode_buf[3] = 0x10;
1909 mode_buf[4] = 0; /* reserved */ 1935 mode_buf[4] = 0; /* reserved */
1910 mode_buf[5] = 0; /* reserved */ 1936 mode_buf[5] = 0; /* reserved */
1911 mode_buf[6] = 0; /* Block descriptor length (MSB) */ 1937 mode_buf[6] = 0; /* Block descriptor length (MSB) */
1912 mode_buf[7] = 0; /* Block descriptor length (LSB) */ 1938 mode_buf[7] = 0; /* Block descriptor length (LSB) */
1913 aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); 1939 if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
1940 ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
1941 mode_buf[1] = 9;
1942 mode_buf[8] = 8;
1943 mode_buf[9] = 1;
1944 mode_buf[10] = 0x04; /* WCE */
1945 mode_buf_length = 11;
1946 if (mode_buf_length > scsicmd->cmnd[8])
1947 mode_buf_length = scsicmd->cmnd[8];
1948 }
1949 aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length);
1914 1950
1915 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; 1951 scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
1916 scsicmd->scsi_done(scsicmd); 1952 scsicmd->scsi_done(scsicmd);