Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Enable PCIe's interrupt as much as possilbe in p...
details: https://anonhg.NetBSD.org/src/rev/7b0eee966e72
branches: trunk
changeset: 823282:7b0eee966e72
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Tue Apr 18 05:21:34 2017 +0000
description:
Enable PCIe's interrupt as much as possilbe in ppb(4) to detect and count
status change event. HotPlug function itself have not implemented yet.
- Interrupt and each event are counted by evcnt(9). Example:
ppb0 Interrupt 0 0 intr
ppb0 Attention Button Pressed 0 0 misc
ppb0 Power Fault Detected 0 0 misc
ppb0 MRL Sensor Changed 0 0 misc
ppb0 Presence Detect Changed 0 0 misc
ppb0 Command Completed 0 0 misc
ppb0 Data Link Layer State Changed 0 0 misc
- Print message if ppb_printevent is not zero. The default vaule is 0.
The output messages:
Attention Button Pressed
Power Fault Detected
MRL Sensor Changed
Presence Detect Changed
Command Completed
Data Link Layer State Changed
- Remove workaround code to disable interrupt (ppb.c rev. 1.35).
Tested with Dell Latitude 2120 without if_bge.c rev. 1.304's workaround.
dmesg when bge's device timeout occured:
ppb3: Presence Detect Changed
ppb3: Data Link Layer State Changed
ppb3: Presence Detect Changed
vmstat -e |grep ppb
ppb3 Interrupt 2 0 intr
ppb3 Presence Detect Changed 2 0 misc
ppb3 Data Link Layer State Changed 1 0 misc
diffstat:
sys/dev/pci/ppb.c | 203 +++++++++++++++++++++++++++++++++++++++++++++-----
sys/dev/pci/ppbvar.h | 15 +++-
2 files changed, 196 insertions(+), 22 deletions(-)
diffs (truncated from 331 to 300 lines):
diff -r ea31dcc36ddf -r 7b0eee966e72 sys/dev/pci/ppb.c
--- a/sys/dev/pci/ppb.c Tue Apr 18 04:35:18 2017 +0000
+++ b/sys/dev/pci/ppb.c Tue Apr 18 05:21:34 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ppb.c,v 1.56 2017/04/05 03:51:36 msaitoh Exp $ */
+/* $NetBSD: ppb.c,v 1.57 2017/04/18 05:21:34 msaitoh Exp $ */
/*
* Copyright (c) 1996, 1998 Christopher G. Demetriou. All rights reserved.
@@ -31,12 +31,13 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.56 2017/04/05 03:51:36 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.57 2017/04/18 05:21:34 msaitoh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
+#include <sys/evcnt.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -52,8 +53,19 @@
"1.25", "2.5", "5.0", "8.0",
};
-static bool ppb_resume(device_t, const pmf_qual_t *);
-static bool ppb_suspend(device_t, const pmf_qual_t *);
+int ppb_printevent = 0; /* Print event type if the value is not 0 */
+
+static int ppbmatch(device_t, cfdata_t, void *);
+static void ppbattach(device_t, device_t, void *);
+static int ppbdetach(device_t, int);
+static void ppbchilddet(device_t, device_t);
+static int ppb_intr(void *);
+static bool ppb_resume(device_t, const pmf_qual_t *);
+static bool ppb_suspend(device_t, const pmf_qual_t *);
+
+CFATTACH_DECL3_NEW(ppb, sizeof(struct ppb_softc),
+ ppbmatch, ppbattach, ppbdetach, NULL, NULL, ppbchilddet,
+ DVF_DETACH_SHUTDOWN);
static int
ppbmatch(device_t parent, cfdata_t match, void *aux)
@@ -91,7 +103,7 @@
}
static void
-ppb_fix_pcie(device_t self)
+ppb_print_pcie(device_t self)
{
struct ppb_softc *sc = device_private(self);
pcireg_t reg;
@@ -181,14 +193,6 @@
aprint_normal(">\n");
break;
}
-
- reg = pci_conf_read(sc->sc_pc, sc->sc_tag, off + 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,
- off + PCIE_SLCSR, reg);
- }
}
static void
@@ -198,7 +202,9 @@
struct pci_attach_args *pa = aux;
pci_chipset_tag_t pc = pa->pa_pc;
struct pcibus_attach_args pba;
- pcireg_t busdata;
+ char const *intrstr;
+ char intrbuf[PCI_INTRSTR_LEN];
+ pcireg_t busdata, reg;
pci_aprint_devinfo(pa, NULL);
@@ -213,7 +219,7 @@
return;
}
- ppb_fix_pcie(self);
+ ppb_print_pcie(self);
#if 0
/*
@@ -227,6 +233,78 @@
pa->pa_bus, PPB_BUSINFO_PRIMARY(busdata));
#endif
+ /* 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)) {
+#if 0
+ /*
+ * XXX Initialize workqueue or something else for
+ * HotPlug support.
+ */
+#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,
+ device_xname(sc->sc_dev));
+
+ if (sc->sc_intrhand) {
+ pcireg_t slcap, slcsr, val;
+
+ intrstr = pci_intr_string(pc, sc->sc_pihp[0], intrbuf,
+ sizeof(intrbuf));
+ aprint_normal_dev(self, "%s\n", intrstr);
+
+ /* Clear any pending events */
+ slcsr = pci_conf_read(pc, pa->pa_tag,
+ sc->sc_pciecapoff + PCIE_SLCSR);
+ pci_conf_write(pc, pa->pa_tag,
+ sc->sc_pciecapoff + PCIE_SLCSR, slcsr);
+
+ /* Enable interrupt. */
+ 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 ((slcap & PCIE_SLCAP_NCCS) == 0)
+ val |= PCIE_SLCSR_CCE;
+ /* Attention indicator off by default */
+ if (slcap & PCIE_SLCAP_AIP) {
+ val |= __SHIFTIN(PCIE_SLCSR_IND_OFF,
+ PCIE_SLCSR_AIC);
+ }
+ /* Power indicator */
+ if (slcap & PCIE_SLCAP_PIP) {
+ /*
+ * Indicator off:
+ * a) card not present
+ * b) power fault
+ * c) MRL sensor off
+ */
+ if (((slcsr & PCIE_SLCSR_PDS) == 0)
+ || ((slcsr & PCIE_SLCSR_PFD) != 0)
+ || (((slcap & PCIE_SLCAP_MSP) != 0)
+ && ((slcsr & PCIE_SLCSR_MS) != 0)))
+ val |= __SHIFTIN(PCIE_SLCSR_IND_OFF,
+ PCIE_SLCSR_PIC);
+ else
+ val |= __SHIFTIN(PCIE_SLCSR_IND_ON,
+ PCIE_SLCSR_PIC);
+ }
+
+ val |= PCIE_SLCSR_DLLSCE | PCIE_SLCSR_HPE
+ | PCIE_SLCSR_PDE;
+ slcsr = val;
+ pci_conf_write(pc, pa->pa_tag,
+ sc->sc_pciecapoff + PCIE_SLCSR, slcsr);
+ }
+ }
+
if (!pmf_device_register(self, ppb_suspend, ppb_resume))
aprint_error_dev(self, "couldn't establish power handler\n");
@@ -248,14 +326,40 @@
pba.pba_intrswiz = pa->pa_intrswiz;
pba.pba_intrtag = pa->pa_intrtag;
+ /* Attach event counters */
+ evcnt_attach_dynamic(&sc->sc_ev_intr, EVCNT_TYPE_INTR, NULL,
+ device_xname(sc->sc_dev), "Interrupt");
+ evcnt_attach_dynamic(&sc->sc_ev_abp, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "Attention Button Pressed");
+ evcnt_attach_dynamic(&sc->sc_ev_pfd, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "Power Fault Detected");
+ evcnt_attach_dynamic(&sc->sc_ev_msc, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "MRL Sensor Changed");
+ evcnt_attach_dynamic(&sc->sc_ev_pdc, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "Presence Detect Changed");
+ evcnt_attach_dynamic(&sc->sc_ev_cc, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "Command Completed");
+ evcnt_attach_dynamic(&sc->sc_ev_lacs, EVCNT_TYPE_MISC, NULL,
+ device_xname(sc->sc_dev), "Data Link Layer State Changed");
+
config_found_ia(self, "pcibus", &pba, pcibusprint);
}
static int
ppbdetach(device_t self, int flags)
{
+ struct ppb_softc *sc = device_private(self);
int rc;
+ /* Detach event counters */
+ evcnt_detach(&sc->sc_ev_intr);
+ evcnt_detach(&sc->sc_ev_abp);
+ evcnt_detach(&sc->sc_ev_pfd);
+ evcnt_detach(&sc->sc_ev_msc);
+ evcnt_detach(&sc->sc_ev_pdc);
+ evcnt_detach(&sc->sc_ev_cc);
+ evcnt_detach(&sc->sc_ev_lacs);
+
if ((rc = config_detach_children(self, flags)) != 0)
return rc;
pmf_device_deregister(self);
@@ -276,8 +380,6 @@
sc->sc_pciconfext[(off - 0x40)/4]);
}
- ppb_fix_pcie(dv);
-
return true;
}
@@ -300,6 +402,67 @@
/* we keep no references to child devices, so do nothing */
}
-CFATTACH_DECL3_NEW(ppb, sizeof(struct ppb_softc),
- ppbmatch, ppbattach, ppbdetach, NULL, NULL, ppbchilddet,
- DVF_DETACH_SHUTDOWN);
+static int
+ppb_intr(void *arg)
+{
+ struct ppb_softc *sc = 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);
+
+ /* Clear interrupts. */
+ pci_conf_write(sc->sc_pc, sc->sc_tag,
+ sc->sc_pciecapoff + PCIE_SLCSR, reg);
+
+ /* Attention Button Pressed */
+ if (reg & PCIE_SLCSR_ABP) {
+ sc->sc_ev_abp.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "Attention Button Pressed\n");
+ }
+
+ /* Power Fault Detected */
+ if (reg & PCIE_SLCSR_PFD) {
+ sc->sc_ev_pfd.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "Power Fault Detected\n");
+ }
+
+ /* MRL Sensor Changed */
+ if (reg & PCIE_SLCSR_MSC) {
+ sc->sc_ev_msc.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "MRL Sensor Changed\n");
+ }
+
+ /* Presence Detect Changed */
+ if (reg & PCIE_SLCSR_PDC) {
+ sc->sc_ev_pdc.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "Presence Detect Changed\n");
+ if (reg & PCIE_SLCSR_PDS) {
+ /* XXX Insert */
+ } else {
+ /* XXX Remove */
+ }
+ }
+
+ /* Command Completed */
+ if (reg & PCIE_SLCSR_CC) {
+ sc->sc_ev_cc.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "Command Completed\n");
+ }
+
+ /* Data Link Layer State Changed */
+ if (reg & PCIE_SLCSR_LACS) {
+ sc->sc_ev_lacs.ev_count++;
+ if (ppb_printevent)
+ device_printf(dev, "Data Link Layer State Changed\n");
+ }
+
+ return 0;
+}
diff -r ea31dcc36ddf -r 7b0eee966e72 sys/dev/pci/ppbvar.h
--- a/sys/dev/pci/ppbvar.h Tue Apr 18 04:35:18 2017 +0000
+++ b/sys/dev/pci/ppbvar.h Tue Apr 18 05:21:34 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ppbvar.h,v 1.1 2017/04/05 03:51:36 msaitoh Exp $ */
+/* $NetBSD: ppbvar.h,v 1.2 2017/04/18 05:21:34 msaitoh Exp $ */
/*
* Copyright (c) 1996, 1998 Christopher G. Demetriou. All rights reserved.
@@ -31,12 +31,13 @@
Home |
Main Index |
Thread Index |
Old Index