Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Purpose: PCI Express Port Bus Driver
0004  * Author:  Tom Nguyen <tom.l.nguyen@intel.com>
0005  *
0006  * Copyright (C) 2004 Intel
0007  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
0008  */
0009 
0010 #include <linux/pci.h>
0011 #include <linux/kernel.h>
0012 #include <linux/errno.h>
0013 #include <linux/pm.h>
0014 #include <linux/pm_runtime.h>
0015 #include <linux/init.h>
0016 #include <linux/aer.h>
0017 #include <linux/dmi.h>
0018 
0019 #include "../pci.h"
0020 #include "portdrv.h"
0021 
0022 /* If this switch is set, PCIe port native services should not be enabled. */
0023 bool pcie_ports_disabled;
0024 
0025 /*
0026  * If the user specified "pcie_ports=native", use the PCIe services regardless
0027  * of whether the platform has given us permission.  On ACPI systems, this
0028  * means we ignore _OSC.
0029  */
0030 bool pcie_ports_native;
0031 
0032 /*
0033  * If the user specified "pcie_ports=dpc-native", use the Linux DPC PCIe
0034  * service even if the platform hasn't given us permission.
0035  */
0036 bool pcie_ports_dpc_native;
0037 
0038 static int __init pcie_port_setup(char *str)
0039 {
0040     if (!strncmp(str, "compat", 6))
0041         pcie_ports_disabled = true;
0042     else if (!strncmp(str, "native", 6))
0043         pcie_ports_native = true;
0044     else if (!strncmp(str, "dpc-native", 10))
0045         pcie_ports_dpc_native = true;
0046 
0047     return 1;
0048 }
0049 __setup("pcie_ports=", pcie_port_setup);
0050 
0051 /* global data */
0052 
0053 #ifdef CONFIG_PM
0054 static int pcie_port_runtime_suspend(struct device *dev)
0055 {
0056     if (!to_pci_dev(dev)->bridge_d3)
0057         return -EBUSY;
0058 
0059     return pcie_port_device_runtime_suspend(dev);
0060 }
0061 
0062 static int pcie_port_runtime_idle(struct device *dev)
0063 {
0064     /*
0065      * Assume the PCI core has set bridge_d3 whenever it thinks the port
0066      * should be good to go to D3.  Everything else, including moving
0067      * the port to D3, is handled by the PCI core.
0068      */
0069     return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
0070 }
0071 
0072 static const struct dev_pm_ops pcie_portdrv_pm_ops = {
0073     .suspend    = pcie_port_device_suspend,
0074     .resume_noirq   = pcie_port_device_resume_noirq,
0075     .resume     = pcie_port_device_resume,
0076     .freeze     = pcie_port_device_suspend,
0077     .thaw       = pcie_port_device_resume,
0078     .poweroff   = pcie_port_device_suspend,
0079     .restore_noirq  = pcie_port_device_resume_noirq,
0080     .restore    = pcie_port_device_resume,
0081     .runtime_suspend = pcie_port_runtime_suspend,
0082     .runtime_resume = pcie_port_device_runtime_resume,
0083     .runtime_idle   = pcie_port_runtime_idle,
0084 };
0085 
0086 #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
0087 
0088 #else /* !PM */
0089 
0090 #define PCIE_PORTDRV_PM_OPS NULL
0091 #endif /* !PM */
0092 
0093 /*
0094  * pcie_portdrv_probe - Probe PCI-Express port devices
0095  * @dev: PCI-Express port device being probed
0096  *
0097  * If detected invokes the pcie_port_device_register() method for
0098  * this port device.
0099  *
0100  */
0101 static int pcie_portdrv_probe(struct pci_dev *dev,
0102                     const struct pci_device_id *id)
0103 {
0104     int type = pci_pcie_type(dev);
0105     int status;
0106 
0107     if (!pci_is_pcie(dev) ||
0108         ((type != PCI_EXP_TYPE_ROOT_PORT) &&
0109          (type != PCI_EXP_TYPE_UPSTREAM) &&
0110          (type != PCI_EXP_TYPE_DOWNSTREAM) &&
0111          (type != PCI_EXP_TYPE_RC_EC)))
0112         return -ENODEV;
0113 
0114     if (type == PCI_EXP_TYPE_RC_EC)
0115         pcie_link_rcec(dev);
0116 
0117     status = pcie_port_device_register(dev);
0118     if (status)
0119         return status;
0120 
0121     pci_save_state(dev);
0122 
0123     dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE |
0124                        DPM_FLAG_SMART_SUSPEND);
0125 
0126     if (pci_bridge_d3_possible(dev)) {
0127         /*
0128          * Keep the port resumed 100ms to make sure things like
0129          * config space accesses from userspace (lspci) will not
0130          * cause the port to repeatedly suspend and resume.
0131          */
0132         pm_runtime_set_autosuspend_delay(&dev->dev, 100);
0133         pm_runtime_use_autosuspend(&dev->dev);
0134         pm_runtime_mark_last_busy(&dev->dev);
0135         pm_runtime_put_autosuspend(&dev->dev);
0136         pm_runtime_allow(&dev->dev);
0137     }
0138 
0139     return 0;
0140 }
0141 
0142 static void pcie_portdrv_remove(struct pci_dev *dev)
0143 {
0144     if (pci_bridge_d3_possible(dev)) {
0145         pm_runtime_forbid(&dev->dev);
0146         pm_runtime_get_noresume(&dev->dev);
0147         pm_runtime_dont_use_autosuspend(&dev->dev);
0148     }
0149 
0150     pcie_port_device_remove(dev);
0151 }
0152 
0153 static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
0154                     pci_channel_state_t error)
0155 {
0156     if (error == pci_channel_io_frozen)
0157         return PCI_ERS_RESULT_NEED_RESET;
0158     return PCI_ERS_RESULT_CAN_RECOVER;
0159 }
0160 
0161 static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
0162 {
0163     size_t off = offsetof(struct pcie_port_service_driver, slot_reset);
0164     device_for_each_child(&dev->dev, &off, pcie_port_device_iter);
0165 
0166     pci_restore_state(dev);
0167     pci_save_state(dev);
0168     return PCI_ERS_RESULT_RECOVERED;
0169 }
0170 
0171 static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
0172 {
0173     return PCI_ERS_RESULT_RECOVERED;
0174 }
0175 
0176 /*
0177  * LINUX Device Driver Model
0178  */
0179 static const struct pci_device_id port_pci_ids[] = {
0180     /* handle any PCI-Express port */
0181     { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_NORMAL, ~0) },
0182     /* subtractive decode PCI-to-PCI bridge, class type is 060401h */
0183     { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, ~0) },
0184     /* handle any Root Complex Event Collector */
0185     { PCI_DEVICE_CLASS(((PCI_CLASS_SYSTEM_RCEC << 8) | 0x00), ~0) },
0186     { },
0187 };
0188 
0189 static const struct pci_error_handlers pcie_portdrv_err_handler = {
0190     .error_detected = pcie_portdrv_error_detected,
0191     .slot_reset = pcie_portdrv_slot_reset,
0192     .mmio_enabled = pcie_portdrv_mmio_enabled,
0193 };
0194 
0195 static struct pci_driver pcie_portdriver = {
0196     .name       = "pcieport",
0197     .id_table   = &port_pci_ids[0],
0198 
0199     .probe      = pcie_portdrv_probe,
0200     .remove     = pcie_portdrv_remove,
0201     .shutdown   = pcie_portdrv_remove,
0202 
0203     .err_handler    = &pcie_portdrv_err_handler,
0204 
0205     .driver_managed_dma = true,
0206 
0207     .driver.pm  = PCIE_PORTDRV_PM_OPS,
0208 };
0209 
0210 static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d)
0211 {
0212     pr_notice("%s detected: will not use MSI for PCIe PME signaling\n",
0213           d->ident);
0214     pcie_pme_disable_msi();
0215     return 0;
0216 }
0217 
0218 static const struct dmi_system_id pcie_portdrv_dmi_table[] __initconst = {
0219     /*
0220      * Boxes that should not use MSI for PCIe PME signaling.
0221      */
0222     {
0223      .callback = dmi_pcie_pme_disable_msi,
0224      .ident = "MSI Wind U-100",
0225      .matches = {
0226              DMI_MATCH(DMI_SYS_VENDOR,
0227                 "MICRO-STAR INTERNATIONAL CO., LTD"),
0228              DMI_MATCH(DMI_PRODUCT_NAME, "U-100"),
0229              },
0230      },
0231      {}
0232 };
0233 
0234 static void __init pcie_init_services(void)
0235 {
0236     pcie_aer_init();
0237     pcie_pme_init();
0238     pcie_dpc_init();
0239     pcie_hp_init();
0240 }
0241 
0242 static int __init pcie_portdrv_init(void)
0243 {
0244     if (pcie_ports_disabled)
0245         return -EACCES;
0246 
0247     pcie_init_services();
0248     dmi_check_system(pcie_portdrv_dmi_table);
0249 
0250     return pci_register_driver(&pcie_portdriver);
0251 }
0252 device_initcall(pcie_portdrv_init);