Re: ASMedia ASM1062 (AHCI) hang after "ahci 0000:28:00.0: Using 64-bit DMA addresses"

Niklas Cassel
2024-01-24T10:41:25Z

Hello ASMedia guys,

It seems like ASMedia ASM1061 does not work with recent Linux kernel versions:
https://lore.kernel.org/linux-ide/ZbAo_LqpbiGMfTtW@wantstofly.org/T/#m2e12f7f0060f0f6cbf3fcb9ec8eecc2c1d1b5799

Lennert on the linux-ide mailing list has done some detective work that
strongly suggests that ASMedia ASM1061 ignores the upper 21 bits of all
DMA addresses.

See full analysis here:
https://lore.kernel.org/linux-ide/ZbAo_LqpbiGMfTtW@wantstofly.org/T/#m02d07243492868085b56c6173efe42e814359017

Basically he modifies libahci.c:

--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1667,6 +1667,12 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
dma_addr_t addr = sg_dma_address(sg);
u32 sg_len = sg_dma_len(sg);

+ printk(KERN_INFO "mapping dma_address=%.16lx sg_len=%.8lx dma_dir=%d\n",
+ (unsigned long)addr, (unsigned long)sg_len, qc->dma_dir);
+
+ if (qc->dma_dir == DMA_TO_DEVICE)
+ addr |= 0xfffff80000000000;
+
ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);

So he force sets all the upper 21 bits in the address sent to the device,
but can still mkfs.btrfs, mount and scrub the filesystem.
This should of course not have worked, and should have resulted in a bunch
of IOMMU page fault errors in the log, but it doesn't.

Can you guys verify that ASMedia ASM1061 only supports 43-bit DMA addresses,
even though it sets AHCI CAP.S64A, which says "Indicates whether the HBA can
access 64-bit data structures." ?

Kind regards,
Niklas