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)
|
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,
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue