diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2016-03-13 11:57:16 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2016-03-13 11:57:16 +0000 |
commit | a86f634604dfde15881604ce5782d2b2586e3452 (patch) | |
tree | 7f256de139a66e07d76c9c48a80649505ef2ab20 | |
parent | a398403efbc57267a8f5db0c8a5cc16412d6a7ad (diff) |
In ichiic(4), ignore the SMBALERT# interrupt. This interrupt has been
observed to fire for spurious reasons with buggy hardware/bios.
It is being ignored by both FreeBSD and Linux as well.
Fixes GENERIC kernel boot on ADI RCC-VE with buggy bios versions, where
ichiic(4) ended up stealing interrupts from ehci(4), rendering the internal
eMMC flash unusable.
Also, always ackknowledge all interrupts by writing status bits back
to avoid a potential SMBALERT# interrupt storm.
with and ok deraadt@ kettenis@ mpi@
-rw-r--r-- | sys/dev/pci/ichiic.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/sys/dev/pci/ichiic.c b/sys/dev/pci/ichiic.c index 87b9f0afcc9..2ca778ed1f7 100644 --- a/sys/dev/pci/ichiic.c +++ b/sys/dev/pci/ichiic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ichiic.c,v 1.37 2015/12/07 02:56:36 jsg Exp $ */ +/* $OpenBSD: ichiic.c,v 1.38 2016/03/13 11:57:15 stsp Exp $ */ /* * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org> @@ -340,18 +340,20 @@ ichiic_intr(void *arg) /* Read status */ st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS); + + /* Clear status bits */ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS, st); + + /* XXX Ignore SMBALERT# for now */ if ((st & ICH_SMB_HS_BUSY) != 0 || (st & (ICH_SMB_HS_INTR | ICH_SMB_HS_DEVERR | ICH_SMB_HS_BUSERR | ICH_SMB_HS_FAILED | - ICH_SMB_HS_SMBAL | ICH_SMB_HS_BDONE)) == 0) + ICH_SMB_HS_BDONE)) == 0) /* Interrupt was not for us */ return (0); DPRINTF(("%s: intr st 0x%b\n", sc->sc_dev.dv_xname, st, ICH_SMB_HS_BITS)); - /* Clear status bits */ - bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS, st); - /* Check for errors */ if (st & (ICH_SMB_HS_DEVERR | ICH_SMB_HS_BUSERR | ICH_SMB_HS_FAILED)) { sc->sc_i2c_xfer.error = 1; |