DF-4693 / fix.diff
--- a/sys/dev/disk/sili/sili_pm.c +++ b/sys/dev/disk/sili/sili_pm.c @@ -654,8 +654,23 @@ sili_pm_read(struct sili_port *ap, int target, int which, u_int32_t *datap) xa->flags = ATA_F_POLL | ATA_F_AUTOSENSE; xa->timeout = 1000; - if (sili_ata_cmd(xa) == ATA_S_COMPLETE) { - *datap = xa->rfis->sector_count | (xa->rfis->lba_low << 8) | + switch (sili_ata_cmd(xa)) { + case ATA_S_COMPLETE: + *datap = xa->rfis->sector_count | (xa->rfis->lba_low << 8) | (xa->rfis->lba_mid << 16) | (xa->rfis->lba_high << 24); error = 0; + break; + case ATA_S_ONCHIP: + /* + * Deferred timeout: the slot is still programmed on the + * chip and ap_expired processing is pending. We must NOT + * recycle the xa until the expiry processing (triggered by + * the remaining commands' completions -> sili_port_reinit) + * has completed this xa. + */ + while (xa->state == ATA_S_ONCHIP) { + sili_port_intr(ap, 1); + sili_os_softsleep(); + } + /* FALL THROUGH */ + default: kprintf("%s.%d pm_read SCA[%d] failed\n", PORTNAME(ap), target, which); *datap = 0; @@ -695,8 +710,21 @@ sili_pm_write(struct sili_port *ap, int target, int which, u_int32_t data) xa->flags = ATA_F_POLL | ATA_F_EXCLUSIVE; xa->timeout = 1000; - if (sili_ata_cmd(xa) == ATA_S_COMPLETE) + switch (sili_ata_cmd(xa)) { + case ATA_S_COMPLETE: error = 0; - else + break; + case ATA_S_ONCHIP: + /* same deferred-timeout hazard as sili_pm_read() */ + while (xa->state == ATA_S_ONCHIP) { + sili_port_intr(ap, 1); + sili_os_softsleep(); + } + /* FALL THROUGH */ + default: error = EIO; + break; + } sili_ata_put_xfer(xa); return(error); } |