diff options
author | Tejun Heo <htejun@gmail.com> | 2006-12-12 02:15:31 +0900 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-16 10:13:22 -0500 |
commit | 33480a0ede8dcc7e6483054279008f972bd56fd3 (patch) | |
tree | db0f1ad9f3e7ba78a7f12d3a2ed3dc0e7534ac67 /drivers/ata | |
parent | c10340aca270abb141154cd93dcf1be0b92143fc (diff) | |
download | linux-3.10-33480a0ede8dcc7e6483054279008f972bd56fd3.tar.gz linux-3.10-33480a0ede8dcc7e6483054279008f972bd56fd3.tar.bz2 linux-3.10-33480a0ede8dcc7e6483054279008f972bd56fd3.zip |
[PATCH] libata: don't initialize sg in ata_exec_internal() if DMA_NONE (take #2)
Calling sg_init_one() with NULL buf causes oops on certain
configurations. Don't initialize sg in ata_exec_internal() if
DMA_NONE and make the function complain if @buf is NULL when dma_dir
isn't DMA_NONE. While at it, fix comment.
The problem is discovered and initial patch was submitted by Arnd
Bergmann.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 011c0a8a2dc..0d51d13b16b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1332,7 +1332,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, } /** - * ata_exec_internal_sg - execute libata internal command + * ata_exec_internal - execute libata internal command * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command @@ -1353,11 +1353,17 @@ unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { - struct scatterlist sg; + struct scatterlist *psg = NULL, sg; + unsigned int n_elem = 0; - sg_init_one(&sg, buf, buflen); + if (dma_dir != DMA_NONE) { + WARN_ON(!buf); + sg_init_one(&sg, buf, buflen); + psg = &sg; + n_elem++; + } - return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1); + return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem); } /** |