summaryrefslogtreecommitdiff
path: root/drivers/block/ahci.c
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2014-04-01 17:26:40 +0300
committerTom Rini <trini@ti.com>2014-04-02 15:44:40 -0400
commit3f62971162370213271dc1e7a396b6b3a6d5b6c6 (patch)
treea2702d6abcf36219d1688aa5313af5fe07b42f6d /drivers/block/ahci.c
parent1336e2d343f088b71ec71907855caccd1053d166 (diff)
downloadu-boot-imx-3f62971162370213271dc1e7a396b6b3a6d5b6c6.zip
u-boot-imx-3f62971162370213271dc1e7a396b6b3a6d5b6c6.tar.gz
u-boot-imx-3f62971162370213271dc1e7a396b6b3a6d5b6c6.tar.bz2
ahci: Fix data abort on multiple scsi resets.
Commit 2faf5fb82ed6 introduced a regression that causes a data abort when running scsi init followed by scsi reset. There are 2 problems with the original commit 1) ALLOC_CACHE_ALIGN_BUFFER() allocates memory on the stack but is assigned to ataid[port] and used by other functions. 2) The function ata_scsiop_inquiry() tries to free memory which was never allocated on the heap. Fix these problems by using tmpid as a temporary cache aligned buffer. Allocate memory separately for ataid[port] and re-use it if required. Fixes: 2faf5fb82ed6 (ahci: Fix cache align error messages) Reported-by: Eli Nidam <elini@marvell.com> Signed-off-by: Roger Quadros <rogerq@ti.com>
Diffstat (limited to 'drivers/block/ahci.c')
-rw-r--r--drivers/block/ahci.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index a409f63..c8f6573 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -623,6 +623,7 @@ static int ata_scsiop_inquiry(ccb *pccb)
95 - 4,
};
u8 fis[20];
+ u16 *idbuf;
ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS);
u8 port;
@@ -649,17 +650,25 @@ static int ata_scsiop_inquiry(ccb *pccb)
return -EIO;
}
- if (ataid[port])
- free(ataid[port]);
- ataid[port] = tmpid;
- ata_swap_buf_le16(tmpid, ATA_ID_WORDS);
+ if (!ataid[port]) {
+ ataid[port] = malloc(ATA_ID_WORDS * 2);
+ if (!ataid[port]) {
+ printf("%s: No memory for ataid[port]\n", __func__);
+ return -ENOMEM;
+ }
+ }
+
+ idbuf = ataid[port];
+
+ memcpy(idbuf, tmpid, ATA_ID_WORDS * 2);
+ ata_swap_buf_le16(idbuf, ATA_ID_WORDS);
memcpy(&pccb->pdata[8], "ATA ", 8);
- ata_id_strcpy((u16 *) &pccb->pdata[16], &tmpid[ATA_ID_PROD], 16);
- ata_id_strcpy((u16 *) &pccb->pdata[32], &tmpid[ATA_ID_FW_REV], 4);
+ ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16);
+ ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4);
#ifdef DEBUG
- ata_dump_id(tmpid);
+ ata_dump_id(idbuf);
#endif
return 0;
}