Module Name: src Committed By: msaitoh Date: Thu Apr 27 04:44:02 UTC 2017
Modified Files: src/sys/dev/pci: ppb.c Log Message: Make ppb(4) interrupt support stable: - Disable all interrupts in the beginning of attach. Without this, interrupt storm occurs while cold == 1 on some environment. - Disable command complete interrput for a while to prevent hangup on some enviroment. I'm sorry, I don't know what this bit is :-| - Check all status bits and return 0 if an interrupt is not for me. It's required for INTx. Tested on XEN3_DOM0 because it doesn't support MSI yet. - Return 1 when a interrupt is processed. To generate a diff of this commit: cvs rdiff -u -r1.60 -r1.61 src/sys/dev/pci/ppb.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/ppb.c diff -u src/sys/dev/pci/ppb.c:1.60 src/sys/dev/pci/ppb.c:1.61 --- src/sys/dev/pci/ppb.c:1.60 Wed Apr 26 08:00:03 2017 +++ src/sys/dev/pci/ppb.c Thu Apr 27 04:44:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ppb.c,v 1.60 2017/04/26 08:00:03 msaitoh Exp $ */ +/* $NetBSD: ppb.c,v 1.61 2017/04/27 04:44:02 msaitoh Exp $ */ /* * Copyright (c) 1996, 1998 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.60 2017/04/26 08:00:03 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.61 2017/04/27 04:44:02 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -45,11 +45,15 @@ __KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.60 #include <dev/pci/ppbvar.h> #include <dev/pci/pcidevs.h> -#define PCIE_SLCSR_NOTIFY_MASK \ +#define PCIE_SLCSR_ENABLE_MASK \ (PCIE_SLCSR_ABE | PCIE_SLCSR_PFE | PCIE_SLCSR_MSE | \ PCIE_SLCSR_PDE | PCIE_SLCSR_CCE | PCIE_SLCSR_HPE | \ PCIE_SLCSR_DLLSCE) +#define PCIE_SLCSR_STATCHG_MASK \ + (PCIE_SLCSR_ABP | PCIE_SLCSR_PFD | PCIE_SLCSR_MSC | \ + PCIE_SLCSR_PDC | PCIE_SLCSR_CC | PCIE_SLCSR_LACS) + static const char pcie_linkspeed_strings[4][5] = { "1.25", "2.5", "5.0", "8.0", }; @@ -241,14 +245,24 @@ ppbattach(device_t parent, device_t self /* Check for PCI Express capabilities and setup hotplug support. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, &sc->sc_pciecapoff, ®) && (reg & PCIE_XCAP_SI)) { + /* + * First, disable all interrupts because BIOS might + * enable them. + */ + reg = pci_conf_read(sc->sc_pc, sc->sc_tag, + sc->sc_pciecapoff + PCIE_SLCSR); + if (reg & PCIE_SLCSR_ENABLE_MASK) { + reg &= ~PCIE_SLCSR_ENABLE_MASK; + pci_conf_write(sc->sc_pc, sc->sc_tag, + sc->sc_pciecapoff + PCIE_SLCSR, reg); + } #ifdef PPB_USEINTR #if 0 /* * XXX Initialize workqueue or something else for * HotPlug support. */ -#endif - +#endif if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0) == 0) sc->sc_intrhand = pci_intr_establish_xname(pc, sc->sc_pihp[0], IPL_BIO, ppb_intr, sc, @@ -268,17 +282,24 @@ ppbattach(device_t parent, device_t self sc->sc_pciecapoff + PCIE_SLCSR, slcsr); /* Enable interrupt. */ + val = 0; slcap = pci_conf_read(pc, pa->pa_tag, sc->sc_pciecapoff + PCIE_SLCAP); - val = 0; if (slcap & PCIE_SLCAP_ABP) val |= PCIE_SLCSR_ABE; if (slcap & PCIE_SLCAP_PCP) val |= PCIE_SLCSR_PFE; if (slcap & PCIE_SLCAP_MSP) val |= PCIE_SLCSR_MSE; +#if 0 + /* + * XXX Disable for a while because setting + * PCIE_SLCSR_CCE makes break device access on + * some environment. + */ if ((slcap & PCIE_SLCAP_NCCS) == 0) val |= PCIE_SLCSR_CCE; +#endif /* Attention indicator off by default */ if (slcap & PCIE_SLCAP_AIP) { val |= __SHIFTIN(PCIE_SLCSR_IND_OFF, @@ -309,16 +330,6 @@ ppbattach(device_t parent, device_t self pci_conf_write(pc, pa->pa_tag, sc->sc_pciecapoff + PCIE_SLCSR, slcsr); } -#else - reg = pci_conf_read(sc->sc_pc, sc->sc_tag, - sc->sc_pciecapoff + PCIE_SLCSR); - if (reg & PCIE_SLCSR_NOTIFY_MASK) { - aprint_debug_dev(self, - "disabling notification events\n"); - reg &= ~PCIE_SLCSR_NOTIFY_MASK; - pci_conf_write(sc->sc_pc, sc->sc_tag, - sc->sc_pciecapoff + PCIE_SLCSR, reg); - } #endif /* PPB_USEINTR */ } @@ -389,7 +400,7 @@ ppbdetach(device_t self, int flags) /* Clear any pending events and disable interrupt */ slcsr = pci_conf_read(sc->sc_pc, sc->sc_tag, sc->sc_pciecapoff + PCIE_SLCSR); - slcsr &= ~PCIE_SLCSR_NOTIFY_MASK; + slcsr &= ~PCIE_SLCSR_ENABLE_MASK; pci_conf_write(sc->sc_pc, sc->sc_tag, sc->sc_pciecapoff + PCIE_SLCSR, slcsr); @@ -448,14 +459,22 @@ ppb_intr(void *arg) device_t dev = sc->sc_dev; pcireg_t reg; - sc->sc_ev_intr.ev_count++; reg = pci_conf_read(sc->sc_pc, sc->sc_tag, sc->sc_pciecapoff + PCIE_SLCSR); + /* + * Not me. This check is only required for INTx. + * ppb_intr() would be spilted int ppb_intr_legacy() and ppb_intr_msi() + */ + if ((reg & PCIE_SLCSR_STATCHG_MASK) == 0) + return 0; + /* Clear interrupts. */ pci_conf_write(sc->sc_pc, sc->sc_tag, sc->sc_pciecapoff + PCIE_SLCSR, reg); + sc->sc_ev_intr.ev_count++; + /* Attention Button Pressed */ if (reg & PCIE_SLCSR_ABP) { sc->sc_ev_abp.ev_count++; @@ -503,6 +522,6 @@ ppb_intr(void *arg) device_printf(dev, "Data Link Layer State Changed\n"); } - return 0; + return 1; } #endif /* PPB_USEINTR */