summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2016-03-13 11:57:16 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2016-03-13 11:57:16 +0000
commita86f634604dfde15881604ce5782d2b2586e3452 (patch)
tree7f256de139a66e07d76c9c48a80649505ef2ab20
parenta398403efbc57267a8f5db0c8a5cc16412d6a7ad (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.c12
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;