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.
This commit is contained in:
@@ -314,8 +314,15 @@ static int ahci_port_start(struct ata_port *ap)
|
||||
return -ENOMEM;
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL);
|
||||
if (!ap->pad) {
|
||||
kfree(pp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
|
||||
if (!mem) {
|
||||
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
|
||||
kfree(pp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -391,6 +398,7 @@ static void ahci_port_stop(struct ata_port *ap)
|
||||
ap->private_data = NULL;
|
||||
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
|
||||
pp->cmd_slot, pp->cmd_slot_dma);
|
||||
dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
|
||||
kfree(pp);
|
||||
}
|
||||
|
||||
@@ -476,23 +484,23 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
||||
static void ahci_fill_sg(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ahci_port_priv *pp = qc->ap->private_data;
|
||||
unsigned int i;
|
||||
struct scatterlist *sg;
|
||||
struct ahci_sg *ahci_sg;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
/*
|
||||
* Next, the S/G list.
|
||||
*/
|
||||
for (i = 0; i < qc->n_elem; i++) {
|
||||
u32 sg_len;
|
||||
dma_addr_t addr;
|
||||
ahci_sg = pp->cmd_tbl_sg;
|
||||
ata_for_each_sg(sg, qc) {
|
||||
dma_addr_t addr = sg_dma_address(sg);
|
||||
u32 sg_len = sg_dma_len(sg);
|
||||
|
||||
addr = sg_dma_address(&qc->sg[i]);
|
||||
sg_len = sg_dma_len(&qc->sg[i]);
|
||||
|
||||
pp->cmd_tbl_sg[i].addr = cpu_to_le32(addr & 0xffffffff);
|
||||
pp->cmd_tbl_sg[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
|
||||
pp->cmd_tbl_sg[i].flags_size = cpu_to_le32(sg_len - 1);
|
||||
ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
|
||||
ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
|
||||
ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
|
||||
ahci_sg++;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user