diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4753a18..acaa8b8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4537,6 +4537,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) * Note h/w doesn't support 64-bit, so we unconditionally * truncate dma_addr_t to u32. */ + if (sg_dma_address(sg) & ~DMA_BIT_MASK(32)) + ata_dev_printk(qc->dev, KERN_WARNING, + "XXX DMA address %llx is above 32bit\n", + sg_dma_address(sg)); addr = (u32) sg_dma_address(sg); sg_len = sg_dma_len(sg); @@ -6628,6 +6632,10 @@ int ata_port_start(struct ata_port *ap) if (rc) return rc; + ata_port_printk(ap, KERN_INFO, "XXX: prd %p/%llx pad %p/%llx\n", + ap->prd, (unsigned long long)ap->prd_dma, + ap->pad, (unsigned long long)ap->pad_dma); + DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long)ap->prd_dma); return 0; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index ed5dc7c..c55d2ae 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -247,6 +247,7 @@ struct nv_adma_port_priv { void __iomem *ctl_block; void __iomem *gen_block; void __iomem *notifier_clear_block; + u64 adma_dma_mask; u8 flags; int last_issue_ncq; }; @@ -748,7 +749,7 @@ static int nv_adma_slave_config(struct scsi_device *sdev) adma_enable = 0; nv_adma_register_mode(ap); } else { - bounce_limit = *ap->dev->dma_mask; + bounce_limit = pp->adma_dma_mask; segment_boundary = NV_ADMA_DMA_BOUNDARY; sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; adma_enable = 1; @@ -1134,10 +1135,20 @@ static int nv_adma_port_start(struct ata_port *ap) void *mem; dma_addr_t mem_dma; void __iomem *mmio; + struct pci_dev *pdev = to_pci_dev(dev); u16 tmp; VPRINTK("ENTER\n"); + /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and + pad buffers */ + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) + return rc; + rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + if (rc) + return rc; + rc = ata_port_start(ap); if (rc) return rc; @@ -1153,6 +1164,15 @@ static int nv_adma_port_start(struct ata_port *ap) pp->notifier_clear_block = pp->gen_block + NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); + /* Now that the legacy PRD and padding buffer are allocated we can + safely raise the DMA mask to allocate the CPB/APRD table. + These are allowed to fail since we store the value that ends up + being used to set as the bounce limit in slave_config later if + needed. */ + pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + pp->adma_dma_mask = *dev->dma_mask; + mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) @@ -2418,12 +2438,6 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) hpriv->type = type; host->private_data = hpriv; - /* set 64bit dma masks, may fail */ - if (type == ADMA) { - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) - pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - } - /* request and iomap NV_MMIO_BAR */ rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME); if (rc) diff --git a/include/linux/libata.h b/include/linux/libata.h