Index: ahcisata_core.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/ahcisata_core.c,v retrieving revision 1.66 diff -u -p -r1.66 ahcisata_core.c --- ahcisata_core.c 2 Nov 2018 21:27:30 -0000 1.66 +++ ahcisata_core.c 4 Nov 2018 08:32:42 -0000 @@ -791,13 +791,12 @@ ahci_do_reset_drive(struct ata_channel * struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; struct ahci_cmd_tbl *cmd_tbl; struct ahci_cmd_header *cmd_h; - int i; + int i, error = 0; uint32_t sig; KASSERT((AHCI_READ(sc, AHCI_P_CMD(chp->ch_channel)) & AHCI_P_CMD_CR) == 0); ata_channel_lock_owned(chp); -again: /* clear port interrupt register */ AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); /* clear SErrors and start operations */ @@ -836,6 +835,7 @@ again: "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive); if (sigp) *sigp = 0xffffffff; + error = EBUSY; goto end; default: break; @@ -850,21 +850,11 @@ again: switch(ahci_exec_fis(chp, 310, flags, c_slot)) { case ERR_DF: case TIMEOUT: - if ((sc->sc_ahci_quirks & AHCI_QUIRK_BADPMPRESET) != 0 && - drive == PMP_PORT_CTL) { - /* - * some controllers fails to reset when - * targeting a PMP but a single drive is attached. - * try again with port 0 - */ - drive = 0; - ahci_channel_stop(sc, chp, flags); - goto again; - } aprint_error("%s channel %d: clearing WDCTL_RST failed " "for drive %d\n", AHCINAME(sc), chp->ch_channel, drive); if (sigp) *sigp = 0xffffffff; + error = EBUSY; goto end; default: break; @@ -904,7 +894,7 @@ end: AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); ahci_channel_start(sc, chp, flags, (sc->sc_ahci_cap & AHCI_CAP_CLO) ? 1 : 0); - return 0; + return error; } static void @@ -972,6 +962,7 @@ ahci_probe_drive(struct ata_channel *chp struct ahci_channel *achp = (struct ahci_channel *)chp; uint32_t sig; uint8_t c_slot; + int error; ata_channel_lock(chp); @@ -994,8 +985,19 @@ ahci_probe_drive(struct ata_channel *chp case SStatus_DET_DEV: ata_delay(chp, 500, "ahcidv", AT_WAIT); if (sc->sc_ahci_cap & AHCI_CAP_SPM) { - ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, &sig, - c_slot); + error = ahci_do_reset_drive(chp, PMP_PORT_CTL, AT_WAIT, + &sig, c_slot); + + /* If probe for PMP failed, just fallback to drive 0 */ + if (error) { + aprint_error_dev(sc->sc_atac.atac_dev, + "drive %d reset failing, disabling PMP\n", + PMP_PORT_CTL); + + sc->sc_ahci_cap &= ~AHCI_CAP_SPM; + ahci_do_reset_drive(chp, 0, AT_WAIT, &sig, + c_slot); + } } else { ahci_do_reset_drive(chp, 0, AT_WAIT, &sig, c_slot); }