mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
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>
This commit is contained in:
parent
0a07ab224a
commit
e602878fd8
1 changed files with 44 additions and 16 deletions
|
@ -1890,13 +1890,33 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
|
|||
void __user *user_buffer)
|
||||
{
|
||||
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. */
|
||||
memset(&fis, 0, sizeof(struct host_to_dev_fis));
|
||||
fis.type = 0x27;
|
||||
fis.opts = 1 << 7;
|
||||
fis.command = command[0];
|
||||
fis.type = 0x27;
|
||||
fis.opts = 1 << 7;
|
||||
fis.command = command[0];
|
||||
fis.features = command[2];
|
||||
fis.sect_count = command[3];
|
||||
if (fis.command == ATA_CMD_SMART) {
|
||||
|
@ -1905,6 +1925,11 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
|
|||
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
|
||||
" %s: User Command: cmd %x, sect %x, "
|
||||
"feat %x, sectcnt %x\n",
|
||||
|
@ -1914,43 +1939,46 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
|
|||
command[2],
|
||||
command[3]);
|
||||
|
||||
memset(port->sector_buffer, 0x00, ATA_SECT_SIZE);
|
||||
|
||||
/* Execute the command. */
|
||||
if (mtip_exec_internal_command(port,
|
||||
&fis,
|
||||
5,
|
||||
port->sector_buffer_dma,
|
||||
(command[3] != 0) ? ATA_SECT_SIZE : 0,
|
||||
(xfer_sz ? dma_addr : 0),
|
||||
(xfer_sz ? ATA_SECT_SIZE * xfer_sz : 0),
|
||||
0,
|
||||
GFP_KERNEL,
|
||||
MTIP_IOCTL_COMMAND_TIMEOUT_MS)
|
||||
< 0) {
|
||||
return -1;
|
||||
rv = -EFAULT;
|
||||
goto exit_drive_command;
|
||||
}
|
||||
|
||||
/* Collect the completion status. */
|
||||
command[0] = reply->command; /* Status*/
|
||||
command[1] = reply->features; /* Error*/
|
||||
command[2] = command[3];
|
||||
command[2] = reply->sect_count;
|
||||
|
||||
dbg_printk(MTIP_DRV_NAME
|
||||
" %s: Completion Status: stat %x, "
|
||||
"err %x, cmd %x\n",
|
||||
"err %x, nsect %x\n",
|
||||
__func__,
|
||||
command[0],
|
||||
command[1],
|
||||
command[2]);
|
||||
|
||||
if (user_buffer && command[3]) {
|
||||
if (xfer_sz) {
|
||||
if (copy_to_user(user_buffer,
|
||||
port->sector_buffer,
|
||||
buf,
|
||||
ATA_SECT_SIZE * command[3])) {
|
||||
return -EFAULT;
|
||||
rv = -EFAULT;
|
||||
goto exit_drive_command;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
exit_drive_command:
|
||||
if (buf)
|
||||
dmam_free_coherent(&port->dd->pdev->dev,
|
||||
ATA_SECT_SIZE * xfer_sz, buf, dma_addr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue