aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ahci.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-10-05 07:13:30 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-05 07:13:30 -0400
commitcedc9a478d8c6265879dc3839ef3d4849a709184 (patch)
tree0c8e0fbffdb6081381c01b8cfd93c95b168acb44 /drivers/scsi/ahci.c
parented39f731ab2e77e58122232f6e27333331d7793d (diff)
libata: fix ATAPI DMA alignment issues
ATAPI needs to be padded to next 4 byte boundary, if misaligned. Original work by me, many fixes from Tejun Heo.
Diffstat (limited to 'drivers/scsi/ahci.c')
-rw-r--r--drivers/scsi/ahci.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index c2c8fa828e24..6e4bb36f8d7c 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -314,8 +314,15 @@ static int ahci_port_start(struct ata_port *ap)
314 return -ENOMEM; 314 return -ENOMEM;
315 memset(pp, 0, sizeof(*pp)); 315 memset(pp, 0, sizeof(*pp));
316 316
317 ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL);
318 if (!ap->pad) {
319 kfree(pp);
320 return -ENOMEM;
321 }
322
317 mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); 323 mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
318 if (!mem) { 324 if (!mem) {
325 dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
319 kfree(pp); 326 kfree(pp);
320 return -ENOMEM; 327 return -ENOMEM;
321 } 328 }
@@ -391,6 +398,7 @@ static void ahci_port_stop(struct ata_port *ap)
391 ap->private_data = NULL; 398 ap->private_data = NULL;
392 dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, 399 dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
393 pp->cmd_slot, pp->cmd_slot_dma); 400 pp->cmd_slot, pp->cmd_slot_dma);
401 dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
394 kfree(pp); 402 kfree(pp);
395} 403}
396 404
@@ -476,23 +484,23 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
476static void ahci_fill_sg(struct ata_queued_cmd *qc) 484static void ahci_fill_sg(struct ata_queued_cmd *qc)
477{ 485{
478 struct ahci_port_priv *pp = qc->ap->private_data; 486 struct ahci_port_priv *pp = qc->ap->private_data;
479 unsigned int i; 487 struct scatterlist *sg;
488 struct ahci_sg *ahci_sg;
480 489
481 VPRINTK("ENTER\n"); 490 VPRINTK("ENTER\n");
482 491
483 /* 492 /*
484 * Next, the S/G list. 493 * Next, the S/G list.
485 */ 494 */
486 for (i = 0; i < qc->n_elem; i++) { 495 ahci_sg = pp->cmd_tbl_sg;
487 u32 sg_len; 496 ata_for_each_sg(sg, qc) {
488 dma_addr_t addr; 497 dma_addr_t addr = sg_dma_address(sg);
489 498 u32 sg_len = sg_dma_len(sg);
490 addr = sg_dma_address(&qc->sg[i]); 499
491 sg_len = sg_dma_len(&qc->sg[i]); 500 ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
492 501 ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
493 pp->cmd_tbl_sg[i].addr = cpu_to_le32(addr & 0xffffffff); 502 ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
494 pp->cmd_tbl_sg[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); 503 ahci_sg++;
495 pp->cmd_tbl_sg[i].flags_size = cpu_to_le32(sg_len - 1);
496 } 504 }
497} 505}
498 506