PCI/DPC: Cache DPC capabilities in pci_init_capabilities()
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Tue, 24 Mar 2020 00:26:04 +0000 (17:26 -0700)
committerBjorn Helgaas <bhelgaas@google.com>
Sat, 28 Mar 2020 18:19:01 +0000 (13:19 -0500)
Since Error Disconnect Recover needs to use DPC error handling routines
even if the OS doesn't have control of DPC, move the initalization and
caching of DPC capabilities from the DPC driver to pci_init_capabilities().

Link: https://lore.kernel.org/r/5888380657c8b9551675b5dbd48e370e4fd2703d.1585000084.git.sathyanarayanan.kuppuswamy@linux.intel.com
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci.h
drivers/pci/pcie/dpc.c
drivers/pci/probe.c

index efbe94096050d8bb0b3eec89c70f4628b48ed6b2..e48677a0ba42cdcddcc9dec9436db0ebb55478ed 100644 (file)
@@ -448,9 +448,11 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
 #ifdef CONFIG_PCIE_DPC
 void pci_save_dpc_state(struct pci_dev *dev);
 void pci_restore_dpc_state(struct pci_dev *dev);
+void pci_dpc_init(struct pci_dev *pdev);
 #else
 static inline void pci_save_dpc_state(struct pci_dev *dev) {}
 static inline void pci_restore_dpc_state(struct pci_dev *dev) {}
+static inline void pci_dpc_init(struct pci_dev *pdev) {}
 #endif
 
 #ifdef CONFIG_PCI_ATS
index 1ae5d94944eb9b1d6618d2842f5e691f3ffc63d9..a1c9d45876bdf82b77a779f44f30456e50662ddd 100644 (file)
@@ -249,6 +249,27 @@ static irqreturn_t dpc_irq(int irq, void *context)
        return IRQ_HANDLED;
 }
 
+void pci_dpc_init(struct pci_dev *pdev)
+{
+       u16 cap;
+
+       pdev->dpc_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DPC);
+       if (!pdev->dpc_cap)
+               return;
+
+       pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CAP, &cap);
+       if (!(cap & PCI_EXP_DPC_CAP_RP_EXT))
+               return;
+
+       pdev->dpc_rp_extensions = true;
+       pdev->dpc_rp_log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8;
+       if (pdev->dpc_rp_log_size < 4 || pdev->dpc_rp_log_size > 9) {
+               pci_err(pdev, "RP PIO log size %u is invalid\n",
+                       pdev->dpc_rp_log_size);
+               pdev->dpc_rp_log_size = 0;
+       }
+}
+
 #define FLAG(x, y) (((x) & (y)) ? '+' : '-')
 static int dpc_probe(struct pcie_device *dev)
 {
@@ -260,8 +281,6 @@ static int dpc_probe(struct pcie_device *dev)
        if (pcie_aer_get_firmware_first(pdev) && !pcie_ports_dpc_native)
                return -ENOTSUPP;
 
-       pdev->dpc_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DPC);
-
        status = devm_request_threaded_irq(device, dev->irq, dpc_irq,
                                           dpc_handler, IRQF_SHARED,
                                           "pcie-dpc", pdev);
@@ -274,16 +293,6 @@ static int dpc_probe(struct pcie_device *dev)
        pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CAP, &cap);
        pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, &ctl);
 
-       pdev->dpc_rp_extensions = (cap & PCI_EXP_DPC_CAP_RP_EXT) ? 1 : 0;
-       if (pdev->dpc_rp_extensions) {
-               pdev->dpc_rp_log_size = (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8;
-               if (pdev->dpc_rp_log_size < 4 || pdev->dpc_rp_log_size > 9) {
-                       pci_err(pdev, "RP PIO log size %u is invalid\n",
-                               pdev->dpc_rp_log_size);
-                       pdev->dpc_rp_log_size = 0;
-               }
-       }
-
        ctl = (ctl & 0xfff4) | PCI_EXP_DPC_CTL_EN_FATAL | PCI_EXP_DPC_CTL_INT_EN;
        pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_CTL, ctl);
 
index 512cb4312dddc3c2fd267b29fb5c52f869ab0b81..c6f91f88681856a6be9795aa73ed9ba9d0c636ff 100644 (file)
@@ -2329,6 +2329,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_enable_acs(dev);            /* Enable ACS P2P upstream forwarding */
        pci_ptm_init(dev);              /* Precision Time Measurement */
        pci_aer_init(dev);              /* Advanced Error Reporting */
+       pci_dpc_init(dev);              /* Downstream Port Containment */
 
        pcie_report_downtraining(dev);