linux/drivers/pci/pcie/portdrv_pci.c
<<
>>
Prefs
   1/*
   2 * File:        portdrv_pci.c
   3 * Purpose:     PCI Express Port Bus Driver
   4 *
   5 * Copyright (C) 2004 Intel
   6 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/pci.h>
  11#include <linux/kernel.h>
  12#include <linux/errno.h>
  13#include <linux/pm.h>
  14#include <linux/init.h>
  15#include <linux/pcieport_if.h>
  16#include <linux/aer.h>
  17#include <linux/dmi.h>
  18#include <linux/pci-aspm.h>
  19
  20#include "portdrv.h"
  21#include "aer/aerdrv.h"
  22
  23/*
  24 * Version Information
  25 */
  26#define DRIVER_VERSION "v1.0"
  27#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
  28#define DRIVER_DESC "PCIe Port Bus Driver"
  29MODULE_AUTHOR(DRIVER_AUTHOR);
  30MODULE_DESCRIPTION(DRIVER_DESC);
  31MODULE_LICENSE("GPL");
  32
  33/* If this switch is set, PCIe port native services should not be enabled. */
  34bool pcie_ports_disabled;
  35
  36/*
  37 * If this switch is set, ACPI _OSC will be used to determine whether or not to
  38 * enable PCIe port native services.
  39 */
  40bool pcie_ports_auto = true;
  41
  42static int __init pcie_port_setup(char *str)
  43{
  44        if (!strncmp(str, "compat", 6)) {
  45                pcie_ports_disabled = true;
  46        } else if (!strncmp(str, "native", 6)) {
  47                pcie_ports_disabled = false;
  48                pcie_ports_auto = false;
  49        } else if (!strncmp(str, "auto", 4)) {
  50                pcie_ports_disabled = false;
  51                pcie_ports_auto = true;
  52        }
  53
  54        return 1;
  55}
  56__setup("pcie_ports=", pcie_port_setup);
  57
  58/* global data */
  59
  60/**
  61 * pcie_clear_root_pme_status - Clear root port PME interrupt status.
  62 * @dev: PCIe root port or event collector.
  63 */
  64void pcie_clear_root_pme_status(struct pci_dev *dev)
  65{
  66        int rtsta_pos;
  67        u32 rtsta;
  68
  69        rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA;
  70
  71        pci_read_config_dword(dev, rtsta_pos, &rtsta);
  72        rtsta |= PCI_EXP_RTSTA_PME;
  73        pci_write_config_dword(dev, rtsta_pos, rtsta);
  74}
  75
  76static int pcie_portdrv_restore_config(struct pci_dev *dev)
  77{
  78        int retval;
  79
  80        retval = pci_enable_device(dev);
  81        if (retval)
  82                return retval;
  83        pci_set_master(dev);
  84        return 0;
  85}
  86
  87#ifdef CONFIG_PM
  88static int pcie_port_resume_noirq(struct device *dev)
  89{
  90        struct pci_dev *pdev = to_pci_dev(dev);
  91
  92        /*
  93         * Some BIOSes forget to clear Root PME Status bits after system wakeup
  94         * which breaks ACPI-based runtime wakeup on PCI Express, so clear those
  95         * bits now just in case (shouldn't hurt).
  96         */
  97        if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
  98                pcie_clear_root_pme_status(pdev);
  99        return 0;
 100}
 101
 102static const struct dev_pm_ops pcie_portdrv_pm_ops = {
 103        .suspend        = pcie_port_device_suspend,
 104        .resume         = pcie_port_device_resume,
 105        .freeze         = pcie_port_device_suspend,
 106        .thaw           = pcie_port_device_resume,
 107        .poweroff       = pcie_port_device_suspend,
 108        .restore        = pcie_port_device_resume,
 109        .resume_noirq   = pcie_port_resume_noirq,
 110};
 111
 112#define PCIE_PORTDRV_PM_OPS     (&pcie_portdrv_pm_ops)
 113
 114#else /* !PM */
 115
 116#define PCIE_PORTDRV_PM_OPS     NULL
 117#endif /* !PM */
 118
 119/*
 120 * pcie_portdrv_probe - Probe PCI-Express port devices
 121 * @dev: PCI-Express port device being probed
 122 *
 123 * If detected invokes the pcie_port_device_register() method for
 124 * this port device.
 125 *
 126 */
 127static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
 128                                        const struct pci_device_id *id)
 129{
 130        int status;
 131
 132        if (!pci_is_pcie(dev) ||
 133            ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
 134             (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
 135             (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
 136                return -ENODEV;
 137
 138        if (!dev->irq && dev->pin) {
 139                dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
 140                         "check vendor BIOS\n", dev->vendor, dev->device);
 141        }
 142        status = pcie_port_device_register(dev);
 143        if (status)
 144                return status;
 145
 146        pci_save_state(dev);
 147
 148        return 0;
 149}
 150
 151static void pcie_portdrv_remove(struct pci_dev *dev)
 152{
 153        pcie_port_device_remove(dev);
 154        pci_disable_device(dev);
 155}
 156
 157static int error_detected_iter(struct device *device, void *data)
 158{
 159        struct pcie_device *pcie_device;
 160        struct pcie_port_service_driver *driver;
 161        struct aer_broadcast_data *result_data;
 162        pci_ers_result_t status;
 163
 164        result_data = (struct aer_broadcast_data *) data;
 165
 166        if (device->bus == &pcie_port_bus_type && device->driver) {
 167                driver = to_service_driver(device->driver);
 168                if (!driver ||
 169                        !driver->err_handler ||
 170                        !driver->err_handler->error_detected)
 171                        return 0;
 172
 173                pcie_device = to_pcie_device(device);
 174
 175                /* Forward error detected message to service drivers */
 176                status = driver->err_handler->error_detected(
 177                        pcie_device->port,
 178                        result_data->state);
 179                result_data->result =
 180                        merge_result(result_data->result, status);
 181        }
 182
 183        return 0;
 184}
 185
 186static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
 187                                        enum pci_channel_state error)
 188{
 189        struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
 190        int ret;
 191
 192        /* can not fail */
 193        ret = device_for_each_child(&dev->dev, &data, error_detected_iter);
 194
 195        return data.result;
 196}
 197
 198static int mmio_enabled_iter(struct device *device, void *data)
 199{
 200        struct pcie_device *pcie_device;
 201        struct pcie_port_service_driver *driver;
 202        pci_ers_result_t status, *result;
 203
 204        result = (pci_ers_result_t *) data;
 205
 206        if (device->bus == &pcie_port_bus_type && device->driver) {
 207                driver = to_service_driver(device->driver);
 208                if (driver &&
 209                        driver->err_handler &&
 210                        driver->err_handler->mmio_enabled) {
 211                        pcie_device = to_pcie_device(device);
 212
 213                        /* Forward error message to service drivers */
 214                        status = driver->err_handler->mmio_enabled(
 215                                        pcie_device->port);
 216                        *result = merge_result(*result, status);
 217                }
 218        }
 219
 220        return 0;
 221}
 222
 223static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
 224{
 225        pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
 226        int retval;
 227
 228        /* get true return value from &status */
 229        retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
 230        return status;
 231}
 232
 233static int slot_reset_iter(struct device *device, void *data)
 234{
 235        struct pcie_device *pcie_device;
 236        struct pcie_port_service_driver *driver;
 237        pci_ers_result_t status, *result;
 238
 239        result = (pci_ers_result_t *) data;
 240
 241        if (device->bus == &pcie_port_bus_type && device->driver) {
 242                driver = to_service_driver(device->driver);
 243                if (driver &&
 244                        driver->err_handler &&
 245                        driver->err_handler->slot_reset) {
 246                        pcie_device = to_pcie_device(device);
 247
 248                        /* Forward error message to service drivers */
 249                        status = driver->err_handler->slot_reset(
 250                                        pcie_device->port);
 251                        *result = merge_result(*result, status);
 252                }
 253        }
 254
 255        return 0;
 256}
 257
 258static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
 259{
 260        pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
 261        int retval;
 262
 263        /* If fatal, restore cfg space for possible link reset at upstream */
 264        if (dev->error_state == pci_channel_io_frozen) {
 265                dev->state_saved = true;
 266                pci_restore_state(dev);
 267                pcie_portdrv_restore_config(dev);
 268                pci_enable_pcie_error_reporting(dev);
 269        }
 270
 271        /* get true return value from &status */
 272        retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
 273
 274        return status;
 275}
 276
 277static int resume_iter(struct device *device, void *data)
 278{
 279        struct pcie_device *pcie_device;
 280        struct pcie_port_service_driver *driver;
 281
 282        if (device->bus == &pcie_port_bus_type && device->driver) {
 283                driver = to_service_driver(device->driver);
 284                if (driver &&
 285                        driver->err_handler &&
 286                        driver->err_handler->resume) {
 287                        pcie_device = to_pcie_device(device);
 288
 289                        /* Forward error message to service drivers */
 290                        driver->err_handler->resume(pcie_device->port);
 291                }
 292        }
 293
 294        return 0;
 295}
 296
 297static void pcie_portdrv_err_resume(struct pci_dev *dev)
 298{
 299        int retval;
 300        /* nothing to do with error value, if it ever happens */
 301        retval = device_for_each_child(&dev->dev, NULL, resume_iter);
 302}
 303
 304/*
 305 * LINUX Device Driver Model
 306 */
 307static const struct pci_device_id port_pci_ids[] = { {
 308        /* handle any PCI-Express port */
 309        PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0),
 310        }, { /* end: all zeroes */ }
 311};
 312MODULE_DEVICE_TABLE(pci, port_pci_ids);
 313
 314static struct pci_error_handlers pcie_portdrv_err_handler = {
 315                .error_detected = pcie_portdrv_error_detected,
 316                .mmio_enabled = pcie_portdrv_mmio_enabled,
 317                .slot_reset = pcie_portdrv_slot_reset,
 318                .resume = pcie_portdrv_err_resume,
 319};
 320
 321static struct pci_driver pcie_portdriver = {
 322        .name           = "pcieport",
 323        .id_table       = &port_pci_ids[0],
 324
 325        .probe          = pcie_portdrv_probe,
 326        .remove         = pcie_portdrv_remove,
 327
 328        .err_handler    = &pcie_portdrv_err_handler,
 329
 330        .driver.pm      = PCIE_PORTDRV_PM_OPS,
 331};
 332
 333static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d)
 334{
 335        pr_notice("%s detected: will not use MSI for PCIe PME signaling\n",
 336                        d->ident);
 337        pcie_pme_disable_msi();
 338        return 0;
 339}
 340
 341static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = {
 342        /*
 343         * Boxes that should not use MSI for PCIe PME signaling.
 344         */
 345        {
 346         .callback = dmi_pcie_pme_disable_msi,
 347         .ident = "MSI Wind U-100",
 348         .matches = {
 349                     DMI_MATCH(DMI_SYS_VENDOR,
 350                                "MICRO-STAR INTERNATIONAL CO., LTD"),
 351                     DMI_MATCH(DMI_PRODUCT_NAME, "U-100"),
 352                     },
 353         },
 354         {}
 355};
 356
 357static int __init pcie_portdrv_init(void)
 358{
 359        int retval;
 360
 361        if (pcie_ports_disabled)
 362                return pci_register_driver(&pcie_portdriver);
 363
 364        dmi_check_system(pcie_portdrv_dmi_table);
 365
 366        retval = pcie_port_bus_register();
 367        if (retval) {
 368                printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
 369                goto out;
 370        }
 371        retval = pci_register_driver(&pcie_portdriver);
 372        if (retval)
 373                pcie_port_bus_unregister();
 374 out:
 375        return retval;
 376}
 377
 378module_init(pcie_portdrv_init);
 379