Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Clearing PCI_PMCSR_PME_STS(W1C) bit is required ...
details: https://anonhg.NetBSD.org/src/rev/5d71e6415ef9
branches: trunk
changeset: 446704:5d71e6415ef9
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Sat Dec 15 05:38:45 2018 +0000
description:
Clearing PCI_PMCSR_PME_STS(W1C) bit is required to stop asserting PME#.
This change would prevent unexpected rebooting from shutdown -p or
unexpected resuming from suspend.
diffstat:
sys/dev/pci/pci.c | 35 ++++++++++++++++++++++++++++-------
1 files changed, 28 insertions(+), 7 deletions(-)
diffs (68 lines):
diff -r 574456fa835d -r 5d71e6415ef9 sys/dev/pci/pci.c
--- a/sys/dev/pci/pci.c Sat Dec 15 02:03:24 2018 +0000
+++ b/sys/dev/pci/pci.c Sat Dec 15 05:38:45 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pci.c,v 1.153 2018/12/01 01:23:24 msaitoh Exp $ */
+/* $NetBSD: pci.c,v 1.154 2018/12/15 05:38:45 msaitoh Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.153 2018/12/01 01:23:24 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.154 2018/12/15 05:38:45 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
@@ -1221,16 +1221,36 @@
return true;
}
+static void
+pci_pme_check_and_clear(device_t dv, pci_chipset_tag_t pc, pcitag_t tag,
+ int off)
+{
+ pcireg_t pmcsr;
+
+ pmcsr = pci_conf_read(pc, tag, off + PCI_PMCSR);
+
+ if (pmcsr & PCI_PMCSR_PME_STS) {
+ /* Clear W1C bit */
+ pmcsr |= PCI_PMCSR_PME_STS;
+ pci_conf_write(pc, tag, off + PCI_PMCSR, pmcsr);
+ aprint_verbose_dev(dv, "Clear PME# now\n");
+ }
+}
+
static bool
pci_child_resume(device_t dv, const pmf_qual_t *qual)
{
struct pci_child_power *priv = device_pmf_bus_private(dv);
- if (priv->p_has_pm &&
- pci_set_powerstate_int(priv->p_pc, priv->p_tag,
- PCI_PMCSR_STATE_D0, priv->p_pm_offset, priv->p_pm_cap)) {
- aprint_error_dev(dv, "unsupported state, continuing.\n");
- return false;
+ if (priv->p_has_pm) {
+ if (pci_set_powerstate_int(priv->p_pc, priv->p_tag,
+ PCI_PMCSR_STATE_D0, priv->p_pm_offset, priv->p_pm_cap)) {
+ aprint_error_dev(dv,
+ "unsupported state, continuing.\n");
+ return false;
+ }
+ pci_pme_check_and_clear(dv, priv->p_pc, priv->p_tag,
+ priv->p_pm_offset);
}
pci_conf_restore(priv->p_pc, priv->p_tag, &priv->p_pciconf);
@@ -1286,6 +1306,7 @@
priv->p_has_pm = true;
priv->p_pm_offset = off;
priv->p_pm_cap = reg;
+ pci_pme_check_and_clear(child, priv->p_pc, priv->p_tag, off);
} else {
priv->p_has_pm = false;
priv->p_pm_offset = -1;
Home |
Main Index |
Thread Index |
Old Index