cregit-Linux how code gets into the kernel

Release 4.7 drivers/pci/pcie/portdrv_pci.c

Directory: drivers/pci/pcie
/*
 * File:        portdrv_pci.c
 * Purpose:     PCI Express Port Bus Driver
 *
 * Copyright (C) 2004 Intel
 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
 */

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/init.h>
#include <linux/pcieport_if.h>
#include <linux/aer.h>
#include <linux/dmi.h>
#include <linux/pci-aspm.h>

#include "portdrv.h"
#include "aer/aerdrv.h"

/*
 * Version Information
 */

#define DRIVER_VERSION "v1.0"

#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"

#define DRIVER_DESC "PCIe Port Bus Driver"

MODULE_AUTHOR(DRIVER_AUTHOR);

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

/* If this switch is set, PCIe port native services should not be enabled. */

bool pcie_ports_disabled;

/*
 * If this switch is set, ACPI _OSC will be used to determine whether or not to
 * enable PCIe port native services.
 */

bool pcie_ports_auto = true;


static int __init pcie_port_setup(char *str) { if (!strncmp(str, "compat", 6)) { pcie_ports_disabled = true; } else if (!strncmp(str, "native", 6)) { pcie_ports_disabled = false; pcie_ports_auto = false; } else if (!strncmp(str, "auto", 4)) { pcie_ports_disabled = false; pcie_ports_auto = true; } return 1; }

Contributors

PersonTokensPropCommitsCommitProp
rafael j. wysockirafael j. wysocki78100.00%2100.00%
Total78100.00%2100.00%

__setup("pcie_ports=", pcie_port_setup); /* global data */ /** * pcie_clear_root_pme_status - Clear root port PME interrupt status. * @dev: PCIe root port or event collector. */
void pcie_clear_root_pme_status(struct pci_dev *dev) { pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME); }

Contributors

PersonTokensPropCommitsCommitProp
rafael j. wysockirafael j. wysocki1789.47%150.00%
jiang liujiang liu210.53%150.00%
Total19100.00%2100.00%


static int pcie_portdrv_restore_config(struct pci_dev *dev) { int retval; retval = pci_enable_device(dev); if (retval) return retval; pci_set_master(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang36100.00%1100.00%
Total36100.00%1100.00%

#ifdef CONFIG_PM
static int pcie_port_resume_noirq(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); /* * Some BIOSes forget to clear Root PME Status bits after system wakeup * which breaks ACPI-based runtime wakeup on PCI Express, so clear those * bits now just in case (shouldn't hurt). */ if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) pcie_clear_root_pme_status(pdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
rafael j. wysockirafael j. wysocki3692.31%150.00%
wang yijingwang yijing37.69%150.00%
Total39100.00%2100.00%

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, .resume_noirq = pcie_port_resume_noirq, }; #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) #else /* !PM */ #define PCIE_PORTDRV_PM_OPS NULL #endif /* !PM */ /* * pcie_portdrv_probe - Probe PCI-Express port devices * @dev: PCI-Express port device being probed * * If detected invokes the pcie_port_device_register() method for * this port device. * */
static int pcie_portdrv_probe(struct pci_dev *dev, const struct pci_device_id *id) { int status; if (!pci_is_pcie(dev) || ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM))) return -ENODEV; status = pcie_port_device_register(dev); if (status) return status; pci_save_state(dev); /* * D3cold may not work properly on some PCIe port, so disable * it by default. */ dev->d3cold_allowed = false; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
tom l. nguyentom l. nguyen3538.89%112.50%
kenji kaneshigekenji kaneshige2628.89%112.50%
wang yijingwang yijing910.00%112.50%
rafael j. wysockirafael j. wysocki88.89%225.00%
huang yinghuang ying77.78%112.50%
yanmin zhangyanmin zhang44.44%112.50%
randy dunlaprandy dunlap11.11%112.50%
Total90100.00%8100.00%


static void pcie_portdrv_remove(struct pci_dev *dev) { pcie_port_device_remove(dev); }

Contributors

PersonTokensPropCommitsCommitProp
tom l. nguyentom l. nguyen16100.00%1100.00%
Total16100.00%1100.00%


static int error_detected_iter(struct device *device, void *data) { struct pcie_device *pcie_device; struct pcie_port_service_driver *driver; struct aer_broadcast_data *result_data; pci_ers_result_t status; result_data = (struct aer_broadcast_data *) data; if (device->bus == &pcie_port_bus_type && device->driver) { driver = to_service_driver(device->driver); if (!driver || !driver->err_handler || !driver->err_handler->error_detected) return 0; pcie_device = to_pcie_device(device); /* Forward error detected message to service drivers */ status = driver->err_handler->error_detected( pcie_device->port, result_data->state); result_data->result = merge_result(result_data->result, status); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang10481.89%150.00%
henrik kretzschmarhenrik kretzschmar2318.11%150.00%
Total127100.00%2100.00%


static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, enum pci_channel_state error) { struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; /* get true return value from &data */ device_for_each_child(&dev->dev, &data, error_detected_iter); return data.result; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang2965.91%116.67%
tom l. nguyentom l. nguyen1125.00%350.00%
hidetoshi setohidetoshi seto36.82%116.67%
bjorn helgaasbjorn helgaas12.27%116.67%
Total44100.00%6100.00%


static int mmio_enabled_iter(struct device *device, void *data) { struct pcie_device *pcie_device; struct pcie_port_service_driver *driver; pci_ers_result_t status, *result; result = (pci_ers_result_t *) data; if (device->bus == &pcie_port_bus_type && device->driver) { driver = to_service_driver(device->driver); if (driver && driver->err_handler && driver->err_handler->mmio_enabled) { pcie_device = to_pcie_device(device); /* Forward error message to service drivers */ status = driver->err_handler->mmio_enabled( pcie_device->port); *result = merge_result(*result, status); } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang10894.74%133.33%
li shaohuali shaohua43.51%133.33%
tom l. nguyentom l. nguyen21.75%133.33%
Total114100.00%3100.00%


static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev) { pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; /* get true return value from &status */ device_for_each_child(&dev->dev, &status, mmio_enabled_iter); return status; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang2678.79%125.00%
tom l. nguyentom l. nguyen618.18%250.00%
greg kroah-hartmangreg kroah-hartman13.03%125.00%
Total33100.00%4100.00%


static int slot_reset_iter(struct device *device, void *data) { struct pcie_device *pcie_device; struct pcie_port_service_driver *driver; pci_ers_result_t status, *result; result = (pci_ers_result_t *) data; if (device->bus == &pcie_port_bus_type && device->driver) { driver = to_service_driver(device->driver); if (driver && driver->err_handler && driver->err_handler->slot_reset) { pcie_device = to_pcie_device(device); /* Forward error message to service drivers */ status = driver->err_handler->slot_reset( pcie_device->port); *result = merge_result(*result, status); } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang11298.25%150.00%
tom l. nguyentom l. nguyen21.75%150.00%
Total114100.00%2100.00%


static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) { pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; /* 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); } /* get true return value from &status */ device_for_each_child(&dev->dev, &status, slot_reset_iter); return status; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang3553.85%222.22%
tom l. nguyentom l. nguyen1726.15%333.33%
rafael j. wysockirafael j. wysocki1116.92%222.22%
linas vepstaslinas vepstas11.54%111.11%
greg kroah-hartmangreg kroah-hartman11.54%111.11%
Total65100.00%9100.00%


static int resume_iter(struct device *device, void *data) { struct pcie_device *pcie_device; struct pcie_port_service_driver *driver; if (device->bus == &pcie_port_bus_type && device->driver) { driver = to_service_driver(device->driver); if (driver && driver->err_handler && driver->err_handler->resume) { pcie_device = to_pcie_device(device); /* Forward error message to service drivers */ driver->err_handler->resume(pcie_device->port); } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang87100.00%1100.00%
Total87100.00%1100.00%


static void pcie_portdrv_err_resume(struct pci_dev *dev) { device_for_each_child(&dev->dev, NULL, resume_iter); }

Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang23100.00%1100.00%
Total23100.00%1100.00%

/* * LINUX Device Driver Model */ static const struct pci_device_id port_pci_ids[] = { { /* handle any PCI-Express port */ PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), }, { /* end: all zeroes */ } }; MODULE_DEVICE_TABLE(pci, port_pci_ids); static const struct pci_error_handlers pcie_portdrv_err_handler = { .error_detected = pcie_portdrv_error_detected, .mmio_enabled = pcie_portdrv_mmio_enabled, .slot_reset = pcie_portdrv_slot_reset, .resume = pcie_portdrv_err_resume, }; static struct pci_driver pcie_portdriver = { .name = "pcieport", .id_table = &port_pci_ids[0], .probe = pcie_portdrv_probe, .remove = pcie_portdrv_remove, .err_handler = &pcie_portdrv_err_handler, .driver.pm = PCIE_PORTDRV_PM_OPS, };
static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) { pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", d->ident); pcie_pme_disable_msi(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
rafael j. wysockirafael j. wysocki28100.00%1100.00%
Total28100.00%1100.00%

static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = { /* * Boxes that should not use MSI for PCIe PME signaling. */ { .callback = dmi_pcie_pme_disable_msi, .ident = "MSI Wind U-100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), DMI_MATCH(DMI_PRODUCT_NAME, "U-100"), }, }, {} };
static int __init pcie_portdrv_init(void) { int retval; if (pcie_ports_disabled) return pci_register_driver(&pcie_portdriver); dmi_check_system(pcie_portdrv_dmi_table); retval = pcie_port_bus_register(); if (retval) { printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); goto out; } retval = pci_register_driver(&pcie_portdriver); if (retval) pcie_port_bus_unregister(); out: return retval; }

Contributors

PersonTokensPropCommitsCommitProp
tom l. nguyentom l. nguyen3144.29%114.29%
randy dunlaprandy dunlap2130.00%114.29%
rafael j. wysockirafael j. wysocki1622.86%342.86%
sam ravnborgsam ravnborg11.43%114.29%
christophe lucaschristophe lucas11.43%114.29%
Total70100.00%7100.00%

module_init(pcie_portdrv_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
yanmin zhangyanmin zhang60947.17%38.82%
rafael j. wysockirafael j. wysocki32024.79%926.47%
tom l. nguyentom l. nguyen24819.21%38.82%
kenji kaneshigekenji kaneshige262.01%12.94%
henrik kretzschmarhenrik kretzschmar231.78%12.94%
randy dunlaprandy dunlap221.70%25.88%
wang yijingwang yijing120.93%12.94%
huang yinghuang ying70.54%12.94%
li shaohuali shaohua40.31%12.94%
hidetoshi setohidetoshi seto40.31%12.94%
zheng yanzheng yan30.23%12.94%
bjorn helgaasbjorn helgaas20.15%25.88%
sam ravnborgsam ravnborg20.15%12.94%
greg kroah-hartmangreg kroah-hartman20.15%12.94%
jiang liujiang liu20.15%12.94%
alexey dobriyanalexey dobriyan10.08%12.94%
christophe lucaschristophe lucas10.08%12.94%
linas vepstaslinas vepstas10.08%12.94%
stefan assmannstefan assmann10.08%12.94%
stephen hemmingerstephen hemminger10.08%12.94%
Total1291100.00%34100.00%
Directory: drivers/pci/pcie
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}