diff options
author | Asai Thambi S P <asamymuthupa@micron.com> | 2012-05-29 21:43:31 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-05-31 02:46:50 -0400 |
commit | e602878fd89dab0af2af995a6bef0fbe97b20dc8 (patch) | |
tree | 26890181c7f897d0e1751f6c12c8204c7e23cde4 /drivers/block | |
parent | 0a07ab224afc56c497e2f1c48e853dbdf964d549 (diff) |
mtip32xx: Fix to support more than one sector in exec_drive_command()
Fix to support more than one sector in exec_drive_command().
Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index bfee50d1b319..cd271d5e1b73 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -1890,13 +1890,33 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
1890 | void __user *user_buffer) | 1890 | void __user *user_buffer) |
1891 | { | 1891 | { |
1892 | struct host_to_dev_fis fis; | 1892 | struct host_to_dev_fis fis; |
1893 | struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); | 1893 | struct host_to_dev_fis *reply; |
1894 | u8 *buf = NULL; | ||
1895 | dma_addr_t dma_addr = 0; | ||
1896 | int rv = 0, xfer_sz = command[3]; | ||
1897 | |||
1898 | if (xfer_sz) { | ||
1899 | if (user_buffer) | ||
1900 | return -EFAULT; | ||
1901 | |||
1902 | buf = dmam_alloc_coherent(&port->dd->pdev->dev, | ||
1903 | ATA_SECT_SIZE * xfer_sz, | ||
1904 | &dma_addr, | ||
1905 | GFP_KERNEL); | ||
1906 | if (!buf) { | ||
1907 | dev_err(&port->dd->pdev->dev, | ||
1908 | "Memory allocation failed (%d bytes)\n", | ||
1909 | ATA_SECT_SIZE * xfer_sz); | ||
1910 | return -ENOMEM; | ||
1911 | } | ||
1912 | memset(buf, 0, ATA_SECT_SIZE * xfer_sz); | ||
1913 | } | ||
1894 | 1914 | ||
1895 | /* Build the FIS. */ | 1915 | /* Build the FIS. */ |
1896 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); | 1916 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); |
1897 | fis.type = 0x27; | 1917 | fis.type = 0x27; |
1898 | fis.opts = 1 << 7; | 1918 | fis.opts = 1 << 7; |
1899 | fis.command = command[0]; | 1919 | fis.command = command[0]; |
1900 | fis.features = command[2]; | 1920 | fis.features = command[2]; |
1901 | fis.sect_count = command[3]; | 1921 | fis.sect_count = command[3]; |
1902 | if (fis.command == ATA_CMD_SMART) { | 1922 | if (fis.command == ATA_CMD_SMART) { |
@@ -1905,6 +1925,11 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
1905 | fis.cyl_hi = 0xC2; | 1925 | fis.cyl_hi = 0xC2; |
1906 | } | 1926 | } |
1907 | 1927 | ||
1928 | if (xfer_sz) | ||
1929 | reply = (port->rxfis + RX_FIS_PIO_SETUP); | ||
1930 | else | ||
1931 | reply = (port->rxfis + RX_FIS_D2H_REG); | ||
1932 | |||
1908 | dbg_printk(MTIP_DRV_NAME | 1933 | dbg_printk(MTIP_DRV_NAME |
1909 | " %s: User Command: cmd %x, sect %x, " | 1934 | " %s: User Command: cmd %x, sect %x, " |
1910 | "feat %x, sectcnt %x\n", | 1935 | "feat %x, sectcnt %x\n", |
@@ -1914,43 +1939,46 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, | |||
1914 | command[2], | 1939 | command[2], |
1915 | command[3]); | 1940 | command[3]); |
1916 | 1941 | ||
1917 | memset(port->sector_buffer, 0x00, ATA_SECT_SIZE); | ||
1918 | |||
1919 | /* Execute the command. */ | 1942 | /* Execute the command. */ |
1920 | if (mtip_exec_internal_command(port, | 1943 | if (mtip_exec_internal_command(port, |
1921 | &fis, | 1944 | &fis, |
1922 | 5, | 1945 | 5, |
1923 | port->sector_buffer_dma, | 1946 | (xfer_sz ? dma_addr : 0), |
1924 | (command[3] != 0) ? ATA_SECT_SIZE : 0, | 1947 | (xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0), |
1925 | 0, | 1948 | 0, |
1926 | GFP_KERNEL, | 1949 | GFP_KERNEL, |
1927 | MTIP_IOCTL_COMMAND_TIMEOUT_MS) | 1950 | MTIP_IOCTL_COMMAND_TIMEOUT_MS) |
1928 | < 0) { | 1951 | < 0) { |
1929 | return -1; | 1952 | rv = -EFAULT; |
1953 | goto exit_drive_command; | ||
1930 | } | 1954 | } |
1931 | 1955 | ||
1932 | /* Collect the completion status. */ | 1956 | /* Collect the completion status. */ |
1933 | command[0] = reply->command; /* Status*/ | 1957 | command[0] = reply->command; /* Status*/ |
1934 | command[1] = reply->features; /* Error*/ | 1958 | command[1] = reply->features; /* Error*/ |
1935 | command[2] = command[3]; | 1959 | command[2] = reply->sect_count; |
1936 | 1960 | ||
1937 | dbg_printk(MTIP_DRV_NAME | 1961 | dbg_printk(MTIP_DRV_NAME |
1938 | " %s: Completion Status: stat %x, " | 1962 | " %s: Completion Status: stat %x, " |
1939 | "err %x, cmd %x\n", | 1963 | "err %x, nsect %x\n", |
1940 | __func__, | 1964 | __func__, |
1941 | command[0], | 1965 | command[0], |
1942 | command[1], | 1966 | command[1], |
1943 | command[2]); | 1967 | command[2]); |
1944 | 1968 | ||
1945 | if (user_buffer && command[3]) { | 1969 | if (xfer_sz) { |
1946 | if (copy_to_user(user_buffer, | 1970 | if (copy_to_user(user_buffer, |
1947 | port->sector_buffer, | 1971 | buf, |
1948 | ATA_SECT_SIZE * command[3])) { | 1972 | ATA_SECT_SIZE * command[3])) { |
1949 | return -EFAULT; | 1973 | rv = -EFAULT; |
1974 | goto exit_drive_command; | ||
1950 | } | 1975 | } |
1951 | } | 1976 | } |
1952 | 1977 | exit_drive_command: | |
1953 | return 0; | 1978 | if (buf) |
1979 | dmam_free_coherent(&port->dd->pdev->dev, | ||
1980 | ATA_SECT_SIZE * xfer_sz, buf, dma_addr); | ||
1981 | return rv; | ||
1954 | } | 1982 | } |
1955 | 1983 | ||
1956 | /* | 1984 | /* |