0001
0002
0003
0004
0005
0006
0007
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
0023 bool pcie_ports_disabled;
0024
0025
0026
0027
0028
0029
0030 bool pcie_ports_native;
0031
0032
0033
0034
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
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
0066
0067
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
0089
0090 #define PCIE_PORTDRV_PM_OPS NULL
0091 #endif
0092
0093
0094
0095
0096
0097
0098
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
0129
0130
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
0178
0179 static const struct pci_device_id port_pci_ids[] = {
0180
0181 { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_NORMAL, ~0) },
0182
0183 { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, ~0) },
0184
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
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);