Commit e602878f authored by Asai Thambi S P's avatar Asai Thambi S P Committed by Jens Axboe

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: default avatarAsai Thambi S P <asamymuthupa@micron.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 0a07ab22
...@@ -1890,13 +1890,33 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, ...@@ -1890,13 +1890,33 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
void __user *user_buffer) void __user *user_buffer)
{ {
struct host_to_dev_fis fis; struct host_to_dev_fis fis;
struct host_to_dev_fis *reply = (port->rxfis + RX_FIS_D2H_REG); struct host_to_dev_fis *reply;
u8 *buf = NULL;
dma_addr_t dma_addr = 0;
int rv = 0, xfer_sz = command[3];
if (xfer_sz) {
if (user_buffer)
return -EFAULT;
buf = dmam_alloc_coherent(&port->dd->pdev->dev,
ATA_SECT_SIZE * xfer_sz,
&dma_addr,
GFP_KERNEL);
if (!buf) {
dev_err(&port->dd->pdev->dev,
"Memory allocation failed (%d bytes)\n",
ATA_SECT_SIZE * xfer_sz);
return -ENOMEM;
}
memset(buf, 0, ATA_SECT_SIZE * xfer_sz);
}
/* Build the FIS. */ /* Build the FIS. */
memset(&fis, 0, sizeof(struct host_to_dev_fis)); memset(&fis, 0, sizeof(struct host_to_dev_fis));
fis.type = 0x27; fis.type = 0x27;
fis.opts = 1 << 7; fis.opts = 1 << 7;
fis.command = command[0]; fis.command = command[0];
fis.features = command[2]; fis.features = command[2];
fis.sect_count = command[3]; fis.sect_count = command[3];
if (fis.command == ATA_CMD_SMART) { if (fis.command == ATA_CMD_SMART) {
...@@ -1905,6 +1925,11 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, ...@@ -1905,6 +1925,11 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
fis.cyl_hi = 0xC2; fis.cyl_hi = 0xC2;
} }
if (xfer_sz)
reply = (port->rxfis + RX_FIS_PIO_SETUP);
else
reply = (port->rxfis + RX_FIS_D2H_REG);
dbg_printk(MTIP_DRV_NAME dbg_printk(MTIP_DRV_NAME
" %s: User Command: cmd %x, sect %x, " " %s: User Command: cmd %x, sect %x, "
"feat %x, sectcnt %x\n", "feat %x, sectcnt %x\n",
...@@ -1914,43 +1939,46 @@ static int exec_drive_command(struct mtip_port *port, u8 *command, ...@@ -1914,43 +1939,46 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
command[2], command[2],
command[3]); command[3]);
memset(port->sector_buffer, 0x00, ATA_SECT_SIZE);
/* Execute the command. */ /* Execute the command. */
if (mtip_exec_internal_command(port, if (mtip_exec_internal_command(port,
&fis, &fis,
5, 5,
port->sector_buffer_dma, (xfer_sz ? dma_addr : 0),
(command[3] != 0) ? ATA_SECT_SIZE : 0, (xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0),
0, 0,
GFP_KERNEL, GFP_KERNEL,
MTIP_IOCTL_COMMAND_TIMEOUT_MS) MTIP_IOCTL_COMMAND_TIMEOUT_MS)
< 0) { < 0) {
return -1; rv = -EFAULT;
goto exit_drive_command;
} }
/* Collect the completion status. */ /* Collect the completion status. */
command[0] = reply->command; /* Status*/ command[0] = reply->command; /* Status*/
command[1] = reply->features; /* Error*/ command[1] = reply->features; /* Error*/
command[2] = command[3]; command[2] = reply->sect_count;
dbg_printk(MTIP_DRV_NAME dbg_printk(MTIP_DRV_NAME
" %s: Completion Status: stat %x, " " %s: Completion Status: stat %x, "
"err %x, cmd %x\n", "err %x, nsect %x\n",
__func__, __func__,
command[0], command[0],
command[1], command[1],
command[2]); command[2]);
if (user_buffer && command[3]) { if (xfer_sz) {
if (copy_to_user(user_buffer, if (copy_to_user(user_buffer,
port->sector_buffer, buf,
ATA_SECT_SIZE * command[3])) { ATA_SECT_SIZE * command[3])) {
return -EFAULT; rv = -EFAULT;
goto exit_drive_command;
} }
} }
exit_drive_command:
return 0; if (buf)
dmam_free_coherent(&port->dd->pdev->dev,
ATA_SECT_SIZE * xfer_sz, buf, dma_addr);
return rv;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment