diff options
author | Mike Miller (OS Dev) <mikem@beardog.cca.cpqcorp.net> | 2006-10-01 02:27:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-01 03:39:20 -0400 |
commit | 00988a3514bbc0cce781c067cf52559741d88b80 (patch) | |
tree | e0a844ecd9351c67dd9e73e8e6aafd064fa43137 | |
parent | 82b0547cfae1fb2ee26cad588f6d49a347d24740 (diff) |
[PATCH] cciss: support for >2TB logical volumes
Add support for logical volumes >2TB. All SAS/SATA controllers support
large volumes.
Signed-off-by: Mike Miller <mike.miller@hp.com>
Cc: Jens Axboe <axboe@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/block/cciss.c | 229 | ||||
-rw-r--r-- | drivers/block/cciss.h | 3 | ||||
-rw-r--r-- | drivers/block/cciss_cmd.h | 33 |
3 files changed, 192 insertions, 73 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c211065ad829..e707f39e990c 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -144,13 +144,13 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); | |||
144 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | 144 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, |
145 | int clear_all); | 145 | int clear_all); |
146 | 146 | ||
147 | static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, | 147 | static void cciss_read_capacity(int ctlr, int logvol, int withirq, |
148 | int withirq, unsigned int *total_size, | 148 | sector_t *total_size, unsigned int *block_size); |
149 | unsigned int *block_size); | 149 | static void cciss_read_capacity_16(int ctlr, int logvol, int withirq, |
150 | static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq, | 150 | sector_t *total_size, unsigned int *block_size); |
151 | unsigned int total_size, | 151 | static void cciss_geometry_inquiry(int ctlr, int logvol, |
152 | unsigned int block_size, | 152 | int withirq, sector_t total_size, |
153 | InquiryData_struct *inq_buff, | 153 | unsigned int block_size, InquiryData_struct *inq_buff, |
154 | drive_info_struct *drv); | 154 | drive_info_struct *drv); |
155 | static void cciss_getgeometry(int cntl_num); | 155 | static void cciss_getgeometry(int cntl_num); |
156 | static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, | 156 | static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, |
@@ -1325,10 +1325,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1325 | { | 1325 | { |
1326 | ctlr_info_t *h = hba[ctlr]; | 1326 | ctlr_info_t *h = hba[ctlr]; |
1327 | struct gendisk *disk; | 1327 | struct gendisk *disk; |
1328 | ReadCapdata_struct *size_buff = NULL; | ||
1329 | InquiryData_struct *inq_buff = NULL; | 1328 | InquiryData_struct *inq_buff = NULL; |
1330 | unsigned int block_size; | 1329 | unsigned int block_size; |
1331 | unsigned int total_size; | 1330 | sector_t total_size; |
1332 | unsigned long flags = 0; | 1331 | unsigned long flags = 0; |
1333 | int ret = 0; | 1332 | int ret = 0; |
1334 | 1333 | ||
@@ -1347,15 +1346,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1347 | return; | 1346 | return; |
1348 | 1347 | ||
1349 | /* Get information about the disk and modify the driver structure */ | 1348 | /* Get information about the disk and modify the driver structure */ |
1350 | size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); | ||
1351 | if (size_buff == NULL) | ||
1352 | goto mem_msg; | ||
1353 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 1349 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); |
1354 | if (inq_buff == NULL) | 1350 | if (inq_buff == NULL) |
1355 | goto mem_msg; | 1351 | goto mem_msg; |
1356 | 1352 | ||
1357 | cciss_read_capacity(ctlr, drv_index, size_buff, 1, | 1353 | cciss_read_capacity(ctlr, drv_index, 1, |
1358 | &total_size, &block_size); | 1354 | &total_size, &block_size); |
1355 | |||
1356 | /* total size = last LBA + 1 */ | ||
1357 | /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */ | ||
1358 | /* so we assume this volume this must be >2TB in size */ | ||
1359 | if (total_size == (__u32) 0) { | ||
1360 | cciss_read_capacity_16(ctlr, drv_index, 1, | ||
1361 | &total_size, &block_size); | ||
1362 | h->cciss_read = CCISS_READ_16; | ||
1363 | h->cciss_write = CCISS_WRITE_16; | ||
1364 | } else { | ||
1365 | h->cciss_read = CCISS_READ_10; | ||
1366 | h->cciss_write = CCISS_WRITE_10; | ||
1367 | } | ||
1359 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | 1368 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, |
1360 | inq_buff, &h->drv[drv_index]); | 1369 | inq_buff, &h->drv[drv_index]); |
1361 | 1370 | ||
@@ -1391,7 +1400,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index) | |||
1391 | } | 1400 | } |
1392 | 1401 | ||
1393 | freeret: | 1402 | freeret: |
1394 | kfree(size_buff); | ||
1395 | kfree(inq_buff); | 1403 | kfree(inq_buff); |
1396 | return; | 1404 | return; |
1397 | mem_msg: | 1405 | mem_msg: |
@@ -1716,6 +1724,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
1716 | c->Request.Timeout = 0; | 1724 | c->Request.Timeout = 0; |
1717 | c->Request.CDB[0] = cmd; | 1725 | c->Request.CDB[0] = cmd; |
1718 | break; | 1726 | break; |
1727 | case CCISS_READ_CAPACITY_16: | ||
1728 | c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID; | ||
1729 | c->Header.LUN.LogDev.Mode = 1; | ||
1730 | c->Request.CDBLen = 16; | ||
1731 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
1732 | c->Request.Type.Direction = XFER_READ; | ||
1733 | c->Request.Timeout = 0; | ||
1734 | c->Request.CDB[0] = cmd; | ||
1735 | c->Request.CDB[1] = 0x10; | ||
1736 | c->Request.CDB[10] = (size >> 24) & 0xFF; | ||
1737 | c->Request.CDB[11] = (size >> 16) & 0xFF; | ||
1738 | c->Request.CDB[12] = (size >> 8) & 0xFF; | ||
1739 | c->Request.CDB[13] = size & 0xFF; | ||
1740 | c->Request.Timeout = 0; | ||
1741 | c->Request.CDB[0] = cmd; | ||
1742 | break; | ||
1719 | case CCISS_CACHE_FLUSH: | 1743 | case CCISS_CACHE_FLUSH: |
1720 | c->Request.CDBLen = 12; | 1744 | c->Request.CDBLen = 12; |
1721 | c->Request.Type.Attribute = ATTR_SIMPLE; | 1745 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -1749,6 +1773,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
1749 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | 1773 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); |
1750 | c->Request.CDB[0] = cmd; /* reset */ | 1774 | c->Request.CDB[0] = cmd; /* reset */ |
1751 | c->Request.CDB[1] = 0x04; /* reset a LUN */ | 1775 | c->Request.CDB[1] = 0x04; /* reset a LUN */ |
1776 | break; | ||
1752 | case 3: /* No-Op message */ | 1777 | case 3: /* No-Op message */ |
1753 | c->Request.CDBLen = 1; | 1778 | c->Request.CDBLen = 1; |
1754 | c->Request.Type.Attribute = ATTR_SIMPLE; | 1779 | c->Request.Type.Attribute = ATTR_SIMPLE; |
@@ -1892,12 +1917,15 @@ static int sendcmd_withirq(__u8 cmd, | |||
1892 | } | 1917 | } |
1893 | 1918 | ||
1894 | static void cciss_geometry_inquiry(int ctlr, int logvol, | 1919 | static void cciss_geometry_inquiry(int ctlr, int logvol, |
1895 | int withirq, unsigned int total_size, | 1920 | int withirq, sector_t total_size, |
1896 | unsigned int block_size, | 1921 | unsigned int block_size, |
1897 | InquiryData_struct *inq_buff, | 1922 | InquiryData_struct *inq_buff, |
1898 | drive_info_struct *drv) | 1923 | drive_info_struct *drv) |
1899 | { | 1924 | { |
1900 | int return_code; | 1925 | int return_code; |
1926 | unsigned long t; | ||
1927 | unsigned long rem; | ||
1928 | |||
1901 | memset(inq_buff, 0, sizeof(InquiryData_struct)); | 1929 | memset(inq_buff, 0, sizeof(InquiryData_struct)); |
1902 | if (withirq) | 1930 | if (withirq) |
1903 | return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, | 1931 | return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, |
@@ -1916,10 +1944,10 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
1916 | drv->nr_blocks = total_size; | 1944 | drv->nr_blocks = total_size; |
1917 | drv->heads = 255; | 1945 | drv->heads = 255; |
1918 | drv->sectors = 32; // Sectors per track | 1946 | drv->sectors = 32; // Sectors per track |
1919 | drv->cylinders = total_size / 255 / 32; | 1947 | t = drv->heads * drv->sectors; |
1948 | drv->cylinders = total_size; | ||
1949 | rem = do_div(drv->cylinders, t); | ||
1920 | } else { | 1950 | } else { |
1921 | unsigned int t; | ||
1922 | |||
1923 | drv->block_size = block_size; | 1951 | drv->block_size = block_size; |
1924 | drv->nr_blocks = total_size; | 1952 | drv->nr_blocks = total_size; |
1925 | drv->heads = inq_buff->data_byte[6]; | 1953 | drv->heads = inq_buff->data_byte[6]; |
@@ -1929,7 +1957,8 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
1929 | drv->raid_level = inq_buff->data_byte[8]; | 1957 | drv->raid_level = inq_buff->data_byte[8]; |
1930 | t = drv->heads * drv->sectors; | 1958 | t = drv->heads * drv->sectors; |
1931 | if (t > 1) { | 1959 | if (t > 1) { |
1932 | drv->cylinders = total_size / t; | 1960 | drv->cylinders = total_size; |
1961 | rem = do_div(drv->cylinders, t); | ||
1933 | } | 1962 | } |
1934 | } | 1963 | } |
1935 | } else { /* Get geometry failed */ | 1964 | } else { /* Get geometry failed */ |
@@ -1940,31 +1969,72 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
1940 | } | 1969 | } |
1941 | 1970 | ||
1942 | static void | 1971 | static void |
1943 | cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, | 1972 | cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, |
1944 | int withirq, unsigned int *total_size, | ||
1945 | unsigned int *block_size) | 1973 | unsigned int *block_size) |
1946 | { | 1974 | { |
1975 | ReadCapdata_struct *buf; | ||
1947 | int return_code; | 1976 | int return_code; |
1948 | memset(buf, 0, sizeof(*buf)); | 1977 | buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); |
1978 | if (buf == NULL) { | ||
1979 | printk(KERN_WARNING "cciss: out of memory\n"); | ||
1980 | return; | ||
1981 | } | ||
1982 | memset(buf, 0, sizeof(ReadCapdata_struct)); | ||
1949 | if (withirq) | 1983 | if (withirq) |
1950 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY, | 1984 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY, |
1951 | ctlr, buf, sizeof(*buf), 1, | 1985 | ctlr, buf, sizeof(ReadCapdata_struct), |
1952 | logvol, 0, TYPE_CMD); | 1986 | 1, logvol, 0, TYPE_CMD); |
1953 | else | 1987 | else |
1954 | return_code = sendcmd(CCISS_READ_CAPACITY, | 1988 | return_code = sendcmd(CCISS_READ_CAPACITY, |
1955 | ctlr, buf, sizeof(*buf), 1, logvol, 0, | 1989 | ctlr, buf, sizeof(ReadCapdata_struct), |
1956 | NULL, TYPE_CMD); | 1990 | 1, logvol, 0, NULL, TYPE_CMD); |
1957 | if (return_code == IO_OK) { | 1991 | if (return_code == IO_OK) { |
1958 | *total_size = | 1992 | *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1; |
1959 | be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1; | 1993 | *block_size = be32_to_cpu(*(__u32 *) buf->block_size); |
1960 | *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0])); | ||
1961 | } else { /* read capacity command failed */ | 1994 | } else { /* read capacity command failed */ |
1962 | printk(KERN_WARNING "cciss: read capacity failed\n"); | 1995 | printk(KERN_WARNING "cciss: read capacity failed\n"); |
1963 | *total_size = 0; | 1996 | *total_size = 0; |
1964 | *block_size = BLOCK_SIZE; | 1997 | *block_size = BLOCK_SIZE; |
1965 | } | 1998 | } |
1966 | printk(KERN_INFO " blocks= %u block_size= %d\n", | 1999 | if (*total_size != (__u32) 0) |
2000 | printk(KERN_INFO " blocks= %lld block_size= %d\n", | ||
2001 | *total_size, *block_size); | ||
2002 | kfree(buf); | ||
2003 | return; | ||
2004 | } | ||
2005 | |||
2006 | static void | ||
2007 | cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size) | ||
2008 | { | ||
2009 | ReadCapdata_struct_16 *buf; | ||
2010 | int return_code; | ||
2011 | buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL); | ||
2012 | if (buf == NULL) { | ||
2013 | printk(KERN_WARNING "cciss: out of memory\n"); | ||
2014 | return; | ||
2015 | } | ||
2016 | memset(buf, 0, sizeof(ReadCapdata_struct_16)); | ||
2017 | if (withirq) { | ||
2018 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16, | ||
2019 | ctlr, buf, sizeof(ReadCapdata_struct_16), | ||
2020 | 1, logvol, 0, TYPE_CMD); | ||
2021 | } | ||
2022 | else { | ||
2023 | return_code = sendcmd(CCISS_READ_CAPACITY_16, | ||
2024 | ctlr, buf, sizeof(ReadCapdata_struct_16), | ||
2025 | 1, logvol, 0, NULL, TYPE_CMD); | ||
2026 | } | ||
2027 | if (return_code == IO_OK) { | ||
2028 | *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1; | ||
2029 | *block_size = be32_to_cpu(*(__u32 *) buf->block_size); | ||
2030 | } else { /* read capacity command failed */ | ||
2031 | printk(KERN_WARNING "cciss: read capacity failed\n"); | ||
2032 | *total_size = 0; | ||
2033 | *block_size = BLOCK_SIZE; | ||
2034 | } | ||
2035 | printk(KERN_INFO " blocks= %lld block_size= %d\n", | ||
1967 | *total_size, *block_size); | 2036 | *total_size, *block_size); |
2037 | kfree(buf); | ||
1968 | return; | 2038 | return; |
1969 | } | 2039 | } |
1970 | 2040 | ||
@@ -1975,8 +2045,7 @@ static int cciss_revalidate(struct gendisk *disk) | |||
1975 | int logvol; | 2045 | int logvol; |
1976 | int FOUND = 0; | 2046 | int FOUND = 0; |
1977 | unsigned int block_size; | 2047 | unsigned int block_size; |
1978 | unsigned int total_size; | 2048 | sector_t total_size; |
1979 | ReadCapdata_struct *size_buff = NULL; | ||
1980 | InquiryData_struct *inq_buff = NULL; | 2049 | InquiryData_struct *inq_buff = NULL; |
1981 | 2050 | ||
1982 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { | 2051 | for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) { |
@@ -1989,27 +2058,24 @@ static int cciss_revalidate(struct gendisk *disk) | |||
1989 | if (!FOUND) | 2058 | if (!FOUND) |
1990 | return 1; | 2059 | return 1; |
1991 | 2060 | ||
1992 | size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); | ||
1993 | if (size_buff == NULL) { | ||
1994 | printk(KERN_WARNING "cciss: out of memory\n"); | ||
1995 | return 1; | ||
1996 | } | ||
1997 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 2061 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); |
1998 | if (inq_buff == NULL) { | 2062 | if (inq_buff == NULL) { |
1999 | printk(KERN_WARNING "cciss: out of memory\n"); | 2063 | printk(KERN_WARNING "cciss: out of memory\n"); |
2000 | kfree(size_buff); | ||
2001 | return 1; | 2064 | return 1; |
2002 | } | 2065 | } |
2003 | 2066 | if (h->cciss_read == CCISS_READ_10) { | |
2004 | cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, | 2067 | cciss_read_capacity(h->ctlr, logvol, 1, |
2005 | &block_size); | 2068 | &total_size, &block_size); |
2069 | } else { | ||
2070 | cciss_read_capacity_16(h->ctlr, logvol, 1, | ||
2071 | &total_size, &block_size); | ||
2072 | } | ||
2006 | cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, | 2073 | cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, |
2007 | inq_buff, drv); | 2074 | inq_buff, drv); |
2008 | 2075 | ||
2009 | blk_queue_hardsect_size(drv->queue, drv->block_size); | 2076 | blk_queue_hardsect_size(drv->queue, drv->block_size); |
2010 | set_capacity(disk, drv->nr_blocks); | 2077 | set_capacity(disk, drv->nr_blocks); |
2011 | 2078 | ||
2012 | kfree(size_buff); | ||
2013 | kfree(inq_buff); | 2079 | kfree(inq_buff); |
2014 | return 0; | 2080 | return 0; |
2015 | } | 2081 | } |
@@ -2418,7 +2484,8 @@ static void do_cciss_request(request_queue_t *q) | |||
2418 | { | 2484 | { |
2419 | ctlr_info_t *h = q->queuedata; | 2485 | ctlr_info_t *h = q->queuedata; |
2420 | CommandList_struct *c; | 2486 | CommandList_struct *c; |
2421 | int start_blk, seg; | 2487 | sector_t start_blk; |
2488 | int seg; | ||
2422 | struct request *creq; | 2489 | struct request *creq; |
2423 | u64bit temp64; | 2490 | u64bit temp64; |
2424 | struct scatterlist tmp_sg[MAXSGENTRIES]; | 2491 | struct scatterlist tmp_sg[MAXSGENTRIES]; |
@@ -2462,10 +2529,10 @@ static void do_cciss_request(request_queue_t *q) | |||
2462 | c->Request.Type.Type = TYPE_CMD; // It is a command. | 2529 | c->Request.Type.Type = TYPE_CMD; // It is a command. |
2463 | c->Request.Type.Attribute = ATTR_SIMPLE; | 2530 | c->Request.Type.Attribute = ATTR_SIMPLE; |
2464 | c->Request.Type.Direction = | 2531 | c->Request.Type.Direction = |
2465 | (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE; | 2532 | (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; |
2466 | c->Request.Timeout = 0; // Don't time out | 2533 | c->Request.Timeout = 0; // Don't time out |
2467 | c->Request.CDB[0] = | 2534 | c->Request.CDB[0] = |
2468 | (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE; | 2535 | (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; |
2469 | start_blk = creq->sector; | 2536 | start_blk = creq->sector; |
2470 | #ifdef CCISS_DEBUG | 2537 | #ifdef CCISS_DEBUG |
2471 | printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, | 2538 | printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, |
@@ -2499,15 +2566,33 @@ static void do_cciss_request(request_queue_t *q) | |||
2499 | #endif /* CCISS_DEBUG */ | 2566 | #endif /* CCISS_DEBUG */ |
2500 | 2567 | ||
2501 | c->Header.SGList = c->Header.SGTotal = seg; | 2568 | c->Header.SGList = c->Header.SGTotal = seg; |
2502 | c->Request.CDB[1] = 0; | 2569 | if(h->cciss_read == CCISS_READ_10) { |
2503 | c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB | 2570 | c->Request.CDB[1] = 0; |
2504 | c->Request.CDB[3] = (start_blk >> 16) & 0xff; | 2571 | c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB |
2505 | c->Request.CDB[4] = (start_blk >> 8) & 0xff; | 2572 | c->Request.CDB[3] = (start_blk >> 16) & 0xff; |
2506 | c->Request.CDB[5] = start_blk & 0xff; | 2573 | c->Request.CDB[4] = (start_blk >> 8) & 0xff; |
2507 | c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB | 2574 | c->Request.CDB[5] = start_blk & 0xff; |
2508 | c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; | 2575 | c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB |
2509 | c->Request.CDB[8] = creq->nr_sectors & 0xff; | 2576 | c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; |
2510 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; | 2577 | c->Request.CDB[8] = creq->nr_sectors & 0xff; |
2578 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; | ||
2579 | } else { | ||
2580 | c->Request.CDBLen = 16; | ||
2581 | c->Request.CDB[1]= 0; | ||
2582 | c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB | ||
2583 | c->Request.CDB[3]= (start_blk >> 48) & 0xff; | ||
2584 | c->Request.CDB[4]= (start_blk >> 40) & 0xff; | ||
2585 | c->Request.CDB[5]= (start_blk >> 32) & 0xff; | ||
2586 | c->Request.CDB[6]= (start_blk >> 24) & 0xff; | ||
2587 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; | ||
2588 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; | ||
2589 | c->Request.CDB[9]= start_blk & 0xff; | ||
2590 | c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff; | ||
2591 | c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff; | ||
2592 | c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff; | ||
2593 | c->Request.CDB[13]= creq->nr_sectors & 0xff; | ||
2594 | c->Request.CDB[14] = c->Request.CDB[15] = 0; | ||
2595 | } | ||
2511 | 2596 | ||
2512 | spin_lock_irq(q->queue_lock); | 2597 | spin_lock_irq(q->queue_lock); |
2513 | 2598 | ||
@@ -2517,9 +2602,9 @@ static void do_cciss_request(request_queue_t *q) | |||
2517 | h->maxQsinceinit = h->Qdepth; | 2602 | h->maxQsinceinit = h->Qdepth; |
2518 | 2603 | ||
2519 | goto queue; | 2604 | goto queue; |
2520 | full: | 2605 | full: |
2521 | blk_stop_queue(q); | 2606 | blk_stop_queue(q); |
2522 | startio: | 2607 | startio: |
2523 | /* We will already have the driver lock here so not need | 2608 | /* We will already have the driver lock here so not need |
2524 | * to lock it. | 2609 | * to lock it. |
2525 | */ | 2610 | */ |
@@ -2947,31 +3032,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
2947 | static void cciss_getgeometry(int cntl_num) | 3032 | static void cciss_getgeometry(int cntl_num) |
2948 | { | 3033 | { |
2949 | ReportLunData_struct *ld_buff; | 3034 | ReportLunData_struct *ld_buff; |
2950 | ReadCapdata_struct *size_buff; | ||
2951 | InquiryData_struct *inq_buff; | 3035 | InquiryData_struct *inq_buff; |
2952 | int return_code; | 3036 | int return_code; |
2953 | int i; | 3037 | int i; |
2954 | int listlength = 0; | 3038 | int listlength = 0; |
2955 | __u32 lunid = 0; | 3039 | __u32 lunid = 0; |
2956 | int block_size; | 3040 | int block_size; |
2957 | int total_size; | 3041 | sector_t total_size; |
2958 | 3042 | ||
2959 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | 3043 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); |
2960 | if (ld_buff == NULL) { | 3044 | if (ld_buff == NULL) { |
2961 | printk(KERN_ERR "cciss: out of memory\n"); | 3045 | printk(KERN_ERR "cciss: out of memory\n"); |
2962 | return; | 3046 | return; |
2963 | } | 3047 | } |
2964 | size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); | ||
2965 | if (size_buff == NULL) { | ||
2966 | printk(KERN_ERR "cciss: out of memory\n"); | ||
2967 | kfree(ld_buff); | ||
2968 | return; | ||
2969 | } | ||
2970 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); | 3048 | inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL); |
2971 | if (inq_buff == NULL) { | 3049 | if (inq_buff == NULL) { |
2972 | printk(KERN_ERR "cciss: out of memory\n"); | 3050 | printk(KERN_ERR "cciss: out of memory\n"); |
2973 | kfree(ld_buff); | 3051 | kfree(ld_buff); |
2974 | kfree(size_buff); | ||
2975 | return; | 3052 | return; |
2976 | } | 3053 | } |
2977 | /* Get the firmware version */ | 3054 | /* Get the firmware version */ |
@@ -3026,7 +3103,6 @@ static void cciss_getgeometry(int cntl_num) | |||
3026 | #endif /* CCISS_DEBUG */ | 3103 | #endif /* CCISS_DEBUG */ |
3027 | 3104 | ||
3028 | hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1; | 3105 | hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1; |
3029 | // for(i=0; i< hba[cntl_num]->num_luns; i++) | ||
3030 | for (i = 0; i < CISS_MAX_LUN; i++) { | 3106 | for (i = 0; i < CISS_MAX_LUN; i++) { |
3031 | if (i < hba[cntl_num]->num_luns) { | 3107 | if (i < hba[cntl_num]->num_luns) { |
3032 | lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) | 3108 | lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) |
@@ -3045,8 +3121,26 @@ static void cciss_getgeometry(int cntl_num) | |||
3045 | ld_buff->LUN[i][2], ld_buff->LUN[i][3], | 3121 | ld_buff->LUN[i][2], ld_buff->LUN[i][3], |
3046 | hba[cntl_num]->drv[i].LunID); | 3122 | hba[cntl_num]->drv[i].LunID); |
3047 | #endif /* CCISS_DEBUG */ | 3123 | #endif /* CCISS_DEBUG */ |
3048 | cciss_read_capacity(cntl_num, i, size_buff, 0, | 3124 | |
3125 | /* testing to see if 16-byte CDBs are already being used */ | ||
3126 | if(hba[cntl_num]->cciss_read == CCISS_READ_16) { | ||
3127 | cciss_read_capacity_16(cntl_num, i, 0, | ||
3049 | &total_size, &block_size); | 3128 | &total_size, &block_size); |
3129 | goto geo_inq; | ||
3130 | } | ||
3131 | cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size); | ||
3132 | |||
3133 | /* total_size = last LBA + 1 */ | ||
3134 | if(total_size == (__u32) 0) { | ||
3135 | cciss_read_capacity_16(cntl_num, i, 0, | ||
3136 | &total_size, &block_size); | ||
3137 | hba[cntl_num]->cciss_read = CCISS_READ_16; | ||
3138 | hba[cntl_num]->cciss_write = CCISS_WRITE_16; | ||
3139 | } else { | ||
3140 | hba[cntl_num]->cciss_read = CCISS_READ_10; | ||
3141 | hba[cntl_num]->cciss_write = CCISS_WRITE_10; | ||
3142 | } | ||
3143 | geo_inq: | ||
3050 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, | 3144 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, |
3051 | block_size, inq_buff, | 3145 | block_size, inq_buff, |
3052 | &hba[cntl_num]->drv[i]); | 3146 | &hba[cntl_num]->drv[i]); |
@@ -3056,7 +3150,6 @@ static void cciss_getgeometry(int cntl_num) | |||
3056 | } | 3150 | } |
3057 | } | 3151 | } |
3058 | kfree(ld_buff); | 3152 | kfree(ld_buff); |
3059 | kfree(size_buff); | ||
3060 | kfree(inq_buff); | 3153 | kfree(inq_buff); |
3061 | } | 3154 | } |
3062 | 3155 | ||
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 868e0d862b0d..562235c1445a 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -76,6 +76,9 @@ struct ctlr_info | |||
76 | unsigned int intr[4]; | 76 | unsigned int intr[4]; |
77 | unsigned int msix_vector; | 77 | unsigned int msix_vector; |
78 | unsigned int msi_vector; | 78 | unsigned int msi_vector; |
79 | BYTE cciss_read; | ||
80 | BYTE cciss_write; | ||
81 | BYTE cciss_read_capacity; | ||
79 | 82 | ||
80 | // information about each logical volume | 83 | // information about each logical volume |
81 | drive_info_struct drv[CISS_MAX_LUN]; | 84 | drive_info_struct drv[CISS_MAX_LUN]; |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 53fea549ba8b..4af7c4c0c7af 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -118,11 +118,34 @@ typedef struct _ReadCapdata_struct | |||
118 | BYTE block_size[4]; // Size of blocks in bytes | 118 | BYTE block_size[4]; // Size of blocks in bytes |
119 | } ReadCapdata_struct; | 119 | } ReadCapdata_struct; |
120 | 120 | ||
121 | // 12 byte commands not implemented in firmware yet. | 121 | #define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */ |
122 | // #define CCISS_READ 0xa8 // Read(12) | 122 | |
123 | // #define CCISS_WRITE 0xaa // Write(12) | 123 | /* service action to differentiate a 16 byte read capacity from |
124 | #define CCISS_READ 0x28 // Read(10) | 124 | other commands that use the 0x9e SCSI op code */ |
125 | #define CCISS_WRITE 0x2a // Write(10) | 125 | |
126 | #define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10 | ||
127 | |||
128 | typedef struct _ReadCapdata_struct_16 | ||
129 | { | ||
130 | BYTE total_size[8]; /* Total size in blocks */ | ||
131 | BYTE block_size[4]; /* Size of blocks in bytes */ | ||
132 | BYTE prot_en:1; /* protection enable bit */ | ||
133 | BYTE rto_en:1; /* reference tag own enable bit */ | ||
134 | BYTE reserved:6; /* reserved bits */ | ||
135 | BYTE reserved2[18]; /* reserved bytes per spec */ | ||
136 | } ReadCapdata_struct_16; | ||
137 | |||
138 | /* Define the supported read/write commands for cciss based controllers */ | ||
139 | |||
140 | #define CCISS_READ_10 0x28 /* Read(10) */ | ||
141 | #define CCISS_WRITE_10 0x2a /* Write(10) */ | ||
142 | #define CCISS_READ_16 0x88 /* Read(16) */ | ||
143 | #define CCISS_WRITE_16 0x8a /* Write(16) */ | ||
144 | |||
145 | /* Define the CDB lengths supported by cciss based controllers */ | ||
146 | |||
147 | #define CDB_LEN10 10 | ||
148 | #define CDB_LEN16 16 | ||
126 | 149 | ||
127 | // BMIC commands | 150 | // BMIC commands |
128 | #define BMIC_READ 0x26 | 151 | #define BMIC_READ 0x26 |