On Wed, Mar 14, 2018 at 12:41 PM, Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> wrote: > When system is resumed if the interrupt generation is enabled it may > trigger immediately when interrupts are enabled depending on what is in > the status register. This may generate spurious DPC conditions and > unnecessary removal of devices. > > Make this work better with system suspend and disable interrupt > generation when the system is suspended. > > Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > --- > drivers/pci/pcie/pcie-dpc.c | 29 +++++++++++++++++++++++++---- > 1 file changed, 25 insertions(+), 4 deletions(-) > > diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c > index 38e40c6c576f..14b96983dbbd 100644 > --- a/drivers/pci/pcie/pcie-dpc.c > +++ b/drivers/pci/pcie/pcie-dpc.c > @@ -280,23 +280,44 @@ static int dpc_probe(struct pcie_device *dev) > return status; > } > > -static void dpc_remove(struct pcie_device *dev) > +static void dpc_interrupt_enable(struct dpc_dev *dpc, bool enable) > { > - struct dpc_dev *dpc = get_service_data(dev); > - struct pci_dev *pdev = dev->port; > + struct pci_dev *pdev = dpc->dev->port; > u16 ctl; > > pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, &ctl); > - ctl &= ~(PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN); > + if (enable) > + ctl |= PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN; > + else > + ctl &= ~(PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN); > pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, ctl); > } > > +static void dpc_remove(struct pcie_device *dev) > +{ > + dpc_interrupt_enable(get_service_data(dev), false); > +} > + > +static int dpc_suspend(struct pcie_device *dev) > +{ > + dpc_interrupt_enable(get_service_data(dev), false); > + return 0; > +} > + > +static int dpc_resume(struct pcie_device *dev) > +{ > + dpc_interrupt_enable(get_service_data(dev), true); > + return 0; > +} Have you considered putting these things into the ->suspend_late and ->resume_early callbacks, respectively? That might be slightly better as runtime resume is still enabled when the ->suspend and ->resume callbacks run. > + > static struct pcie_port_service_driver dpcdriver = { > .name = "dpc", > .port_type = PCIE_ANY_PORT, > .service = PCIE_PORT_SERVICE_DPC, > .probe = dpc_probe, > .remove = dpc_remove, > + .suspend = dpc_suspend, > + .resume = dpc_resume, > }; > > static int __init dpc_service_init(void) > -- -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html