MODULE_LICENSE("GPL");
/* global data */
-static const char device_name[] = "pcieport-driver";
-static int pcie_portdrv_save_config(struct pci_dev *dev)
-{
- return pci_save_state(dev);
-}
-
-#ifdef CONFIG_PM
static int pcie_portdrv_restore_config(struct pci_dev *dev)
{
int retval;
- pci_restore_state(dev);
retval = pci_enable_device(dev);
if (retval)
return retval;
return 0;
}
-static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
-{
- int ret = pcie_port_device_suspend(dev, state);
+#ifdef CONFIG_PM
+static const struct dev_pm_ops pcie_portdrv_pm_ops = {
+ .suspend = pcie_port_device_suspend,
+ .resume = pcie_port_device_resume,
+ .freeze = pcie_port_device_suspend,
+ .thaw = pcie_port_device_resume,
+ .poweroff = pcie_port_device_suspend,
+ .restore = pcie_port_device_resume,
+};
- if (!ret)
- ret = pcie_portdrv_save_config(dev);
- return ret;
-}
+#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
-static int pcie_portdrv_resume(struct pci_dev *dev)
-{
- pcie_portdrv_restore_config(dev);
- return pcie_port_device_resume(dev);
-}
-#else
-#define pcie_portdrv_suspend NULL
-#define pcie_portdrv_resume NULL
-#endif
+#else /* !PM */
+
+#define PCIE_PORTDRV_PM_OPS NULL
+#endif /* !PM */
/*
* pcie_portdrv_probe - Probe PCI-Express port devices
* this port device.
*
*/
-static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
- const struct pci_device_id *id )
+static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
- int status;
-
- status = pcie_port_device_probe(dev);
- if (status)
- return status;
+ int status;
- if (pci_enable_device(dev) < 0)
+ if (!pci_is_pcie(dev) ||
+ ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+ (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
+ (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
return -ENODEV;
-
- pci_set_master(dev);
- if (!dev->irq) {
- printk(KERN_WARNING
- "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n",
- __FUNCTION__, dev->device, dev->vendor);
- }
- if (pcie_port_device_register(dev)) {
- pci_disable_device(dev);
- return -ENOMEM;
- }
- pcie_portdrv_save_config(dev);
+ if (!dev->irq && dev->pin) {
+ dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
+ "check vendor BIOS\n", dev->vendor, dev->device);
+ }
+ status = pcie_port_device_register(dev);
+ if (status)
+ return status;
- pci_enable_pcie_error_reporting(dev);
+ pci_save_state(dev);
return 0;
}
static void pcie_portdrv_remove (struct pci_dev *dev)
{
pcie_port_device_remove(dev);
- kfree(pci_get_drvdata(dev));
+ pci_disable_device(dev);
}
static int error_detected_iter(struct device *device, void *data)
static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
{
- pci_ers_result_t status;
+ pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
int retval;
/* If fatal, restore cfg space for possible link reset at upstream */
if (dev->error_state == pci_channel_io_frozen) {
+ dev->state_saved = true;
+ pci_restore_state(dev);
pcie_portdrv_restore_config(dev);
pci_enable_pcie_error_reporting(dev);
}
.resume = pcie_portdrv_err_resume,
};
-static struct pci_driver pcie_portdrv = {
- .name = (char *)device_name,
+static struct pci_driver pcie_portdriver = {
+ .name = "pcieport",
.id_table = &port_pci_ids[0],
.probe = pcie_portdrv_probe,
.remove = pcie_portdrv_remove,
- .suspend = pcie_portdrv_suspend,
- .resume = pcie_portdrv_resume,
-
.err_handler = &pcie_portdrv_err_handler,
+
+ .driver.pm = PCIE_PORTDRV_PM_OPS,
};
static int __init pcie_portdrv_init(void)
printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
goto out;
}
- retval = pci_register_driver(&pcie_portdrv);
+ retval = pci_register_driver(&pcie_portdriver);
if (retval)
pcie_port_bus_unregister();
out:
static void __exit pcie_portdrv_exit(void)
{
- pci_unregister_driver(&pcie_portdrv);
+ pci_unregister_driver(&pcie_portdriver);
pcie_port_bus_unregister();
}