--- a/sys/dev/disk/ahci/ahci_pm.c +++ b/sys/dev/disk/ahci/ahci_pm.c @@ -37,6 +37,7 @@ #include "ahci.h" static void ahci_pm_dummy_done(struct ata_xfer *xa); +static int ahci_pm_cmd(struct ata_xfer *xa); int ahci_pm_port_init(struct ahci_port *ap, struct ata_port *at) @@ -987,15 +988,14 @@ xa->flags = ATA_F_POLL | ATA_F_AUTOSENSE; xa->timeout = 1000; - if (ahci_ata_cmd(xa) == ATA_S_COMPLETE) { + error = ahci_pm_cmd(xa); + if (error == 0) { *datap = xa->rfis.sector_count | (xa->rfis.lba_low << 8) | (xa->rfis.lba_mid << 16) | (xa->rfis.lba_high << 24); - error = 0; } else { kprintf("%s.%d pm_read SCA[%d] failed\n", PORTNAME(ap), target, which); *datap = 0; - error = EIO; } ahci_ata_put_xfer(xa); return (error); @@ -1028,15 +1028,41 @@ xa->flags = ATA_F_POLL; xa->timeout = 1000; - if (ahci_ata_cmd(xa) == ATA_S_COMPLETE) - error = 0; - else - error = EIO; + error = ahci_pm_cmd(xa); ahci_ata_put_xfer(xa); return(error); } /* + * Run a PM register command to completion and return 0 on success, EIO + * on failure. + * + * A deferred timeout (ahci_ata_cmd_timeout(), "Deferred timeout until + * its safe") leaves the command ON THE CHIP with xa->state still + * ATA_S_ONCHIP while other commands on the port are active. The CCB + * must NOT be recycled in that state: the chip (or the deferred-expiry + * machinery) still owns the slot and would later operate on a CCB that + * is on the free list or has been re-issued. Drive the timeout + * machinery (bounded) until the command comes off the chip before the + * caller puts the xfer back. + */ +static int +ahci_pm_cmd(struct ata_xfer *xa) +{ + struct ahci_port *ap = ((struct ahci_ccb *)xa)->ccb_port; + int guard = 31000; /* ~31s worst case */ + int rc; + + rc = ahci_ata_cmd(xa); + while (rc != ATA_S_COMPLETE && xa->state == ATA_S_ONCHIP && --guard) { + ahci_ata_cmd_timeout((struct ahci_ccb *)xa); + ahci_port_intr(ap, 1); + ahci_os_softsleep(); + } + return (rc == ATA_S_COMPLETE ? 0 : EIO); +} + +/* * Dummy done callback for xa. */ static void