diff options
author | Ian Moffett <ian@osmora.org> | 2025-05-10 00:35:07 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-05-10 00:35:07 -0400 |
commit | c827321fb287e4c122a8986e8edd1d355838ca18 (patch) | |
tree | d9362a55acd88bbbbbb4f72c5eb0ede169725be6 | |
parent | 822b5927a5072283ef787ea13186038ec0f46524 (diff) |
kernel: ahci: Handle AHCI interface/HBA errors
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/dev/ic/ahci.c | 52 | ||||
-rw-r--r-- | sys/include/dev/ic/ahciregs.h | 20 |
2 files changed, 71 insertions, 1 deletions
diff --git a/sys/dev/ic/ahci.c b/sys/dev/ic/ahci.c index d6428c9..9482c77 100644 --- a/sys/dev/ic/ahci.c +++ b/sys/dev/ic/ahci.c @@ -251,6 +251,56 @@ hba_port_start(struct hba_port *port) } /* + * Check for interface errors, returns + * 0 on success (i.e., no errors), otherwise + * the "ERR" word of PxSERR. + */ +static int +hba_port_chkerr(struct hba_port *port) +{ + uint32_t serr; + uint16_t err; + uint8_t critical = 0; + + serr = mmio_read32(&port->serr); + err = serr & 0xFFFF; + if (err == 0) { + return 0; + } + + if (ISSET(err, AHCI_SERR_I)) { + pr_error("recovered data integrity error\n"); + } + if (ISSET(err, AHCI_SERR_M)) { + pr_error("recovered comms error\n"); + } + if (ISSET(err, AHCI_SERR_T)) { + pr_error("transient data integrity error\n"); + } + if (ISSET(err, AHCI_SERR_C)) { + pr_error("persistent comms error\n"); + critical = 1; + } + if (ISSET(err, AHCI_SERR_P)) { + pr_error("protocol error\n"); + critical = 1; + } + if (ISSET(err, AHCI_SERR_E)) { + pr_error("internal hba error\n"); + critical = 1; + } + if (critical) { + pr_error("CRITICAL - DISABLING PORT **\n"); + hba_port_stop(port); + return err; + } + + mmio_write32(&port->serr, 0xFFFFFFFF); + return err; + +} + +/* * Reset a port on the HBA * * XXX: This function stops the port once the @@ -352,7 +402,7 @@ ahci_submit_cmd(struct ahci_hba *hba, struct hba_port *port, uint8_t slot) return status; } - return 0; + return hba_port_chkerr(port); } /* diff --git a/sys/include/dev/ic/ahciregs.h b/sys/include/dev/ic/ahciregs.h index f73e587..f959a1e 100644 --- a/sys/include/dev/ic/ahciregs.h +++ b/sys/include/dev/ic/ahciregs.h @@ -139,6 +139,26 @@ struct hba_memspace { #define AHCI_IPM_ACTIVE 1 /* + * PxSERR bits + * See section 3.3.12 of the AHCI spec + */ +#define AHCI_SERR_I BIT(0) /* Recovered data integrity error */ +#define AHCI_SERR_M BIT(1) /* Recovered comms error */ +#define AHCI_SERR_T BIT(8) /* Transient data integrity error */ +#define AHCI_SERR_C BIT(9) /* Persistent comms error */ +#define AHCI_SERR_P BIT(10) /* Protocol error ("oh fuck!" bit) */ +#define AHCI_SERR_E BIT(11) /* Internal error (only God knows, just pray) */ +#define AHCI_DIAG_N BIT(16) /* PhyRdy change */ +#define AHCI_DIAG_I BIT(17) /* PHY internal error */ +#define AHCI_DIAG_W BIT(18) /* Comm wake */ +#define AHCI_DIAG_B BIT(19) /* 10B to 8B decode error */ +#define AHCI_DIAG_C BIT(21) /* CRC error */ +#define AHCI_DIAG_H BIT(22) /* Handshake error */ +#define AHCI_DIAG_S BIT(23) /* Link sequence error */ +#define AHCI_DIAG_T BIT(24) /* Transport state transition error */ +#define AHCI_DIAG_F BIT(25) /* Unknown FIS type */ + +/* * Device detection initialization values * See section 3.3.11 of the AHCI spec. */ |