diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 7e512c222af..7fe3da88057 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -483,6 +483,7 @@ ahci_intr(void *data) /* AHCI declares level triggered IS. */ if (!(ctlr->quirks & AHCI_Q_EDGEIS)) ATA_OUTL(ctlr->r_mem, AHCI_IS, is); + ATA_RBL(ctlr->r_mem, AHCI_IS); } /* @@ -501,6 +502,7 @@ ahci_intr_one(void *data) ctlr->interrupt[unit].function(arg); /* AHCI declares level triggered IS. */ ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + ATA_RBL(ctlr->r_mem, AHCI_IS); } static void @@ -516,6 +518,7 @@ ahci_intr_one_edge(void *data) ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); if ((arg = ctlr->interrupt[unit].argument)) ctlr->interrupt[unit].function(arg); + ATA_RBL(ctlr->r_mem, AHCI_IS); } struct resource * diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h index 0461953940f..5953425e2d9 100644 --- a/sys/dev/ahci/ahci.h +++ b/sys/dev/ahci/ahci.h @@ -562,6 +562,20 @@ enum ahci_err_type { #define ATA_OUTSL_STRM(res, offset, addr, count) \ bus_write_multi_stream_4((res), (offset), (addr), (count)) +/* + * On some platforms, we must ensure proper interdevice write ordering. + * The AHCI interrupt status register must be updated in HW before + * registers in interrupt controller. + * Unfortunately, only way how we can do it is readback. + * + * Currently, only ARM is known to have this issue. + */ +#if defined(__arm__) +#define ATA_RBL(res, offset) \ + bus_read_4((res), (offset)) +#else +#define ATA_RBL(res, offset) +#endif #define AHCI_Q_NOFORCE 0x00000001 #define AHCI_Q_NOPMP 0x00000002