@@ -412,13 +412,44 @@ void pci_dpc_init(struct pci_dev *pdev)
412412 }
413413}
414414
415+ static void dpc_enable (struct pcie_device * dev )
416+ {
417+ struct pci_dev * pdev = dev -> port ;
418+ int dpc = pdev -> dpc_cap ;
419+ u16 ctl ;
420+
421+ /*
422+ * Clear DPC Interrupt Status so we don't get an interrupt for an
423+ * old event when setting DPC Interrupt Enable.
424+ */
425+ pci_write_config_word (pdev , dpc + PCI_EXP_DPC_STATUS ,
426+ PCI_EXP_DPC_STATUS_INTERRUPT );
427+
428+ pci_read_config_word (pdev , dpc + PCI_EXP_DPC_CTL , & ctl );
429+ ctl &= ~PCI_EXP_DPC_CTL_EN_MASK ;
430+ ctl |= PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN ;
431+ pci_write_config_word (pdev , dpc + PCI_EXP_DPC_CTL , ctl );
432+ }
433+
434+ static void dpc_disable (struct pcie_device * dev )
435+ {
436+ struct pci_dev * pdev = dev -> port ;
437+ int dpc = pdev -> dpc_cap ;
438+ u16 ctl ;
439+
440+ /* Disable DPC triggering and DPC interrupts */
441+ pci_read_config_word (pdev , dpc + PCI_EXP_DPC_CTL , & ctl );
442+ ctl &= ~(PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN );
443+ pci_write_config_word (pdev , dpc + PCI_EXP_DPC_CTL , ctl );
444+ }
445+
415446#define FLAG (x , y ) (((x) & (y)) ? '+' : '-')
416447static int dpc_probe (struct pcie_device * dev )
417448{
418449 struct pci_dev * pdev = dev -> port ;
419450 struct device * device = & dev -> device ;
420451 int status ;
421- u16 ctl , cap ;
452+ u16 cap ;
422453
423454 if (!pcie_aer_is_native (pdev ) && !pcie_ports_dpc_native )
424455 return - ENOTSUPP ;
@@ -433,11 +464,7 @@ static int dpc_probe(struct pcie_device *dev)
433464 }
434465
435466 pci_read_config_word (pdev , pdev -> dpc_cap + PCI_EXP_DPC_CAP , & cap );
436-
437- pci_read_config_word (pdev , pdev -> dpc_cap + PCI_EXP_DPC_CTL , & ctl );
438- ctl &= ~PCI_EXP_DPC_CTL_EN_MASK ;
439- ctl |= PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN ;
440- pci_write_config_word (pdev , pdev -> dpc_cap + PCI_EXP_DPC_CTL , ctl );
467+ dpc_enable (dev );
441468
442469 pci_info (pdev , "enabled with IRQ %d\n" , dev -> irq );
443470 pci_info (pdev , "error containment capabilities: Int Msg #%d, RPExt%c PoisonedTLP%c SwTrigger%c RP PIO Log %d, DL_ActiveErr%c\n" ,
@@ -450,21 +477,30 @@ static int dpc_probe(struct pcie_device *dev)
450477 return status ;
451478}
452479
453- static void dpc_remove (struct pcie_device * dev )
480+ static int dpc_suspend (struct pcie_device * dev )
454481{
455- struct pci_dev * pdev = dev -> port ;
456- u16 ctl ;
482+ dpc_disable (dev );
483+ return 0 ;
484+ }
457485
458- pci_read_config_word (pdev , pdev -> dpc_cap + PCI_EXP_DPC_CTL , & ctl );
459- ctl &= ~(PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN );
460- pci_write_config_word (pdev , pdev -> dpc_cap + PCI_EXP_DPC_CTL , ctl );
486+ static int dpc_resume (struct pcie_device * dev )
487+ {
488+ dpc_enable (dev );
489+ return 0 ;
490+ }
491+
492+ static void dpc_remove (struct pcie_device * dev )
493+ {
494+ dpc_disable (dev );
461495}
462496
463497static struct pcie_port_service_driver dpcdriver = {
464498 .name = "dpc" ,
465499 .port_type = PCIE_ANY_PORT ,
466500 .service = PCIE_PORT_SERVICE_DPC ,
467501 .probe = dpc_probe ,
502+ .suspend = dpc_suspend ,
503+ .resume = dpc_resume ,
468504 .remove = dpc_remove ,
469505};
470506
0 commit comments