linux/drivers/pci/pcie/portdrv_core.c
<<
>>
Prefs
   1/*
   2 * File:        portdrv_core.c
   3 * Purpose:     PCI Express Port Bus Driver's Core Functions
   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/pm_runtime.h>
  15#include <linux/string.h>
  16#include <linux/slab.h>
  17#include <linux/pcieport_if.h>
  18#include <linux/aer.h>
  19
  20#include "../pci.h"
  21#include "portdrv.h"
  22
  23bool pciehp_msi_disabled;
  24
  25static int __init pciehp_setup(char *str)
  26{
  27        if (!strncmp(str, "nomsi", 5))
  28                pciehp_msi_disabled = true;
  29
  30        return 1;
  31}
  32__setup("pcie_hp=", pciehp_setup);
  33
  34/**
  35 * release_pcie_device - free PCI Express port service device structure
  36 * @dev: Port service device to release
  37 *
  38 * Invoked automatically when device is being removed in response to
  39 * device_unregister(dev).  Release all resources being claimed.
  40 */
  41static void release_pcie_device(struct device *dev)
  42{
  43        kfree(to_pcie_device(dev));
  44}
  45
  46/**
  47 * pcie_port_enable_msix - try to set up MSI-X as interrupt mode for given port
  48 * @dev: PCI Express port to handle
  49 * @irqs: Array of interrupt vectors to populate
  50 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
  51 *
  52 * Return value: 0 on success, error code on failure
  53 */
  54static int pcie_port_enable_msix(struct pci_dev *dev, int *irqs, int mask)
  55{
  56        int nr_entries, entry, nvec = 0;
  57
  58        /*
  59         * Allocate as many entries as the port wants, so that we can check
  60         * which of them will be useful.  Moreover, if nr_entries is correctly
  61         * equal to the number of entries this port actually uses, we'll happily
  62         * go through without any tricks.
  63         */
  64        nr_entries = pci_alloc_irq_vectors(dev, 1, PCIE_PORT_MAX_MSIX_ENTRIES,
  65                        PCI_IRQ_MSIX);
  66        if (nr_entries < 0)
  67                return nr_entries;
  68
  69        if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) {
  70                u16 reg16;
  71
  72                /*
  73                 * The code below follows the PCI Express Base Specification 2.0
  74                 * stating in Section 6.1.6 that "PME and Hot-Plug Event
  75                 * interrupts (when both are implemented) always share the same
  76                 * MSI or MSI-X vector, as indicated by the Interrupt Message
  77                 * Number field in the PCI Express Capabilities register", where
  78                 * according to Section 7.8.2 of the specification "For MSI-X,
  79                 * the value in this field indicates which MSI-X Table entry is
  80                 * used to generate the interrupt message."
  81                 */
  82                pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
  83                entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
  84                if (entry >= nr_entries)
  85                        goto out_free_irqs;
  86
  87                irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pci_irq_vector(dev, entry);
  88                irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pci_irq_vector(dev, entry);
  89
  90                nvec = max(nvec, entry + 1);
  91        }
  92
  93        if (mask & PCIE_PORT_SERVICE_AER) {
  94                u32 reg32, pos;
  95
  96                /*
  97                 * The code below follows Section 7.10.10 of the PCI Express
  98                 * Base Specification 2.0 stating that bits 31-27 of the Root
  99                 * Error Status Register contain a value indicating which of the
 100                 * MSI/MSI-X vectors assigned to the port is going to be used
 101                 * for AER, where "For MSI-X, the value in this register
 102                 * indicates which MSI-X Table entry is used to generate the
 103                 * interrupt message."
 104                 */
 105                pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
 106                pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
 107                entry = reg32 >> 27;
 108                if (entry >= nr_entries)
 109                        goto out_free_irqs;
 110
 111                irqs[PCIE_PORT_SERVICE_AER_SHIFT] = pci_irq_vector(dev, entry);
 112
 113                nvec = max(nvec, entry + 1);
 114        }
 115
 116        /*
 117         * If nvec is equal to the allocated number of entries, we can just use
 118         * what we have.  Otherwise, the port has some extra entries not for the
 119         * services we know and we need to work around that.
 120         */
 121        if (nvec != nr_entries) {
 122                /* Drop the temporary MSI-X setup */
 123                pci_free_irq_vectors(dev);
 124
 125                /* Now allocate the MSI-X vectors for real */
 126                nr_entries = pci_alloc_irq_vectors(dev, nvec, nvec,
 127                                PCI_IRQ_MSIX);
 128                if (nr_entries < 0)
 129                        return nr_entries;
 130        }
 131
 132        return 0;
 133
 134out_free_irqs:
 135        pci_free_irq_vectors(dev);
 136        return -EIO;
 137}
 138
 139/**
 140 * pcie_init_service_irqs - initialize irqs for PCI Express port services
 141 * @dev: PCI Express port to handle
 142 * @irqs: Array of irqs to populate
 143 * @mask: Bitmask of port capabilities returned by get_port_device_capability()
 144 *
 145 * Return value: Interrupt mode associated with the port
 146 */
 147static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 148{
 149        unsigned flags = PCI_IRQ_LEGACY | PCI_IRQ_MSI;
 150        int ret, i;
 151
 152        for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
 153                irqs[i] = -1;
 154
 155        /*
 156         * If MSI cannot be used for PCIe PME or hotplug, we have to use
 157         * INTx or other interrupts, e.g. system shared interrupt.
 158         */
 159        if (((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) ||
 160            ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())) {
 161                flags &= ~PCI_IRQ_MSI;
 162        } else {
 163                /* Try to use MSI-X if supported */
 164                if (!pcie_port_enable_msix(dev, irqs, mask))
 165                        return 0;
 166        }
 167
 168        ret = pci_alloc_irq_vectors(dev, 1, 1, flags);
 169        if (ret < 0)
 170                return -ENODEV;
 171
 172        for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
 173                if (i != PCIE_PORT_SERVICE_VC_SHIFT)
 174                        irqs[i] = pci_irq_vector(dev, 0);
 175        }
 176
 177        return 0;
 178}
 179
 180/**
 181 * get_port_device_capability - discover capabilities of a PCI Express port
 182 * @dev: PCI Express port to examine
 183 *
 184 * The capabilities are read from the port's PCI Express configuration registers
 185 * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
 186 * 7.9 - 7.11.
 187 *
 188 * Return value: Bitmask of discovered port capabilities
 189 */
 190static int get_port_device_capability(struct pci_dev *dev)
 191{
 192        int services = 0;
 193        int cap_mask = 0;
 194
 195        if (pcie_ports_disabled)
 196                return 0;
 197
 198        cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP
 199                        | PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_DPC;
 200        if (pci_aer_available())
 201                cap_mask |= PCIE_PORT_SERVICE_AER;
 202
 203        if (pcie_ports_auto)
 204                pcie_port_platform_notify(dev, &cap_mask);
 205
 206        /* Hot-Plug Capable */
 207        if ((cap_mask & PCIE_PORT_SERVICE_HP) && dev->is_hotplug_bridge) {
 208                services |= PCIE_PORT_SERVICE_HP;
 209                /*
 210                 * Disable hot-plug interrupts in case they have been enabled
 211                 * by the BIOS and the hot-plug service driver is not loaded.
 212                 */
 213                pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
 214                          PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
 215        }
 216        /* AER capable */
 217        if ((cap_mask & PCIE_PORT_SERVICE_AER)
 218            && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) {
 219                services |= PCIE_PORT_SERVICE_AER;
 220                /*
 221                 * Disable AER on this port in case it's been enabled by the
 222                 * BIOS (the AER service driver will enable it when necessary).
 223                 */
 224                pci_disable_pcie_error_reporting(dev);
 225        }
 226        /* VC support */
 227        if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
 228                services |= PCIE_PORT_SERVICE_VC;
 229        /* Root ports are capable of generating PME too */
 230        if ((cap_mask & PCIE_PORT_SERVICE_PME)
 231            && pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
 232                services |= PCIE_PORT_SERVICE_PME;
 233                /*
 234                 * Disable PME interrupt on this port in case it's been enabled
 235                 * by the BIOS (the PME service driver will enable it when
 236                 * necessary).
 237                 */
 238                pcie_pme_interrupt_enable(dev, false);
 239        }
 240        if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC))
 241                services |= PCIE_PORT_SERVICE_DPC;
 242
 243        return services;
 244}
 245
 246/**
 247 * pcie_device_init - allocate and initialize PCI Express port service device
 248 * @pdev: PCI Express port to associate the service device with
 249 * @service: Type of service to associate with the service device
 250 * @irq: Interrupt vector to associate with the service device
 251 */
 252static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
 253{
 254        int retval;
 255        struct pcie_device *pcie;
 256        struct device *device;
 257
 258        pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
 259        if (!pcie)
 260                return -ENOMEM;
 261        pcie->port = pdev;
 262        pcie->irq = irq;
 263        pcie->service = service;
 264
 265        /* Initialize generic device interface */
 266        device = &pcie->device;
 267        device->bus = &pcie_port_bus_type;
 268        device->release = release_pcie_device;  /* callback to free pcie dev */
 269        dev_set_name(device, "%s:pcie%03x",
 270                     pci_name(pdev),
 271                     get_descriptor_id(pci_pcie_type(pdev), service));
 272        device->parent = &pdev->dev;
 273        device_enable_async_suspend(device);
 274
 275        retval = device_register(device);
 276        if (retval) {
 277                put_device(device);
 278                return retval;
 279        }
 280
 281        pm_runtime_no_callbacks(device);
 282
 283        return 0;
 284}
 285
 286/**
 287 * pcie_port_device_register - register PCI Express port
 288 * @dev: PCI Express port to register
 289 *
 290 * Allocate the port extension structure and register services associated with
 291 * the port.
 292 */
 293int pcie_port_device_register(struct pci_dev *dev)
 294{
 295        int status, capabilities, i, nr_service;
 296        int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
 297
 298        /* Enable PCI Express port device */
 299        status = pci_enable_device(dev);
 300        if (status)
 301                return status;
 302
 303        /* Get and check PCI Express port services */
 304        capabilities = get_port_device_capability(dev);
 305        if (!capabilities)
 306                return 0;
 307
 308        pci_set_master(dev);
 309        /*
 310         * Initialize service irqs. Don't use service devices that
 311         * require interrupts if there is no way to generate them.
 312         * However, some drivers may have a polling mode (e.g. pciehp_poll_mode)
 313         * that can be used in the absence of irqs.  Allow them to determine
 314         * if that is to be used.
 315         */
 316        status = pcie_init_service_irqs(dev, irqs, capabilities);
 317        if (status) {
 318                capabilities &= PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_HP;
 319                if (!capabilities)
 320                        goto error_disable;
 321        }
 322
 323        /* Allocate child services if any */
 324        status = -ENODEV;
 325        nr_service = 0;
 326        for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
 327                int service = 1 << i;
 328                if (!(capabilities & service))
 329                        continue;
 330                if (!pcie_device_init(dev, service, irqs[i]))
 331                        nr_service++;
 332        }
 333        if (!nr_service)
 334                goto error_cleanup_irqs;
 335
 336        return 0;
 337
 338error_cleanup_irqs:
 339        pci_free_irq_vectors(dev);
 340error_disable:
 341        pci_disable_device(dev);
 342        return status;
 343}
 344
 345#ifdef CONFIG_PM
 346static int suspend_iter(struct device *dev, void *data)
 347{
 348        struct pcie_port_service_driver *service_driver;
 349
 350        if ((dev->bus == &pcie_port_bus_type) && dev->driver) {
 351                service_driver = to_service_driver(dev->driver);
 352                if (service_driver->suspend)
 353                        service_driver->suspend(to_pcie_device(dev));
 354        }
 355        return 0;
 356}
 357
 358/**
 359 * pcie_port_device_suspend - suspend port services associated with a PCIe port
 360 * @dev: PCI Express port to handle
 361 */
 362int pcie_port_device_suspend(struct device *dev)
 363{
 364        return device_for_each_child(dev, NULL, suspend_iter);
 365}
 366
 367static int resume_iter(struct device *dev, void *data)
 368{
 369        struct pcie_port_service_driver *service_driver;
 370
 371        if ((dev->bus == &pcie_port_bus_type) &&
 372            (dev->driver)) {
 373                service_driver = to_service_driver(dev->driver);
 374                if (service_driver->resume)
 375                        service_driver->resume(to_pcie_device(dev));
 376        }
 377        return 0;
 378}
 379
 380/**
 381 * pcie_port_device_resume - resume port services associated with a PCIe port
 382 * @dev: PCI Express port to handle
 383 */
 384int pcie_port_device_resume(struct device *dev)
 385{
 386        return device_for_each_child(dev, NULL, resume_iter);
 387}
 388#endif /* PM */
 389
 390static int remove_iter(struct device *dev, void *data)
 391{
 392        if (dev->bus == &pcie_port_bus_type)
 393                device_unregister(dev);
 394        return 0;
 395}
 396
 397/**
 398 * pcie_port_device_remove - unregister PCI Express port service devices
 399 * @dev: PCI Express port the service devices to unregister are associated with
 400 *
 401 * Remove PCI Express port service devices associated with given port and
 402 * disable MSI-X or MSI for the port.
 403 */
 404void pcie_port_device_remove(struct pci_dev *dev)
 405{
 406        device_for_each_child(&dev->dev, NULL, remove_iter);
 407        pci_free_irq_vectors(dev);
 408        pci_disable_device(dev);
 409}
 410
 411/**
 412 * pcie_port_probe_service - probe driver for given PCI Express port service
 413 * @dev: PCI Express port service device to probe against
 414 *
 415 * If PCI Express port service driver is registered with
 416 * pcie_port_service_register(), this function will be called by the driver core
 417 * whenever match is found between the driver and a port service device.
 418 */
 419static int pcie_port_probe_service(struct device *dev)
 420{
 421        struct pcie_device *pciedev;
 422        struct pcie_port_service_driver *driver;
 423        int status;
 424
 425        if (!dev || !dev->driver)
 426                return -ENODEV;
 427
 428        driver = to_service_driver(dev->driver);
 429        if (!driver || !driver->probe)
 430                return -ENODEV;
 431
 432        pciedev = to_pcie_device(dev);
 433        status = driver->probe(pciedev);
 434        if (status)
 435                return status;
 436
 437        dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", driver->name);
 438        get_device(dev);
 439        return 0;
 440}
 441
 442/**
 443 * pcie_port_remove_service - detach driver from given PCI Express port service
 444 * @dev: PCI Express port service device to handle
 445 *
 446 * If PCI Express port service driver is registered with
 447 * pcie_port_service_register(), this function will be called by the driver core
 448 * when device_unregister() is called for the port service device associated
 449 * with the driver.
 450 */
 451static int pcie_port_remove_service(struct device *dev)
 452{
 453        struct pcie_device *pciedev;
 454        struct pcie_port_service_driver *driver;
 455
 456        if (!dev || !dev->driver)
 457                return 0;
 458
 459        pciedev = to_pcie_device(dev);
 460        driver = to_service_driver(dev->driver);
 461        if (driver && driver->remove) {
 462                dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n",
 463                        driver->name);
 464                driver->remove(pciedev);
 465                put_device(dev);
 466        }
 467        return 0;
 468}
 469
 470/**
 471 * pcie_port_shutdown_service - shut down given PCI Express port service
 472 * @dev: PCI Express port service device to handle
 473 *
 474 * If PCI Express port service driver is registered with
 475 * pcie_port_service_register(), this function will be called by the driver core
 476 * when device_shutdown() is called for the port service device associated
 477 * with the driver.
 478 */
 479static void pcie_port_shutdown_service(struct device *dev) {}
 480
 481/**
 482 * pcie_port_service_register - register PCI Express port service driver
 483 * @new: PCI Express port service driver to register
 484 */
 485int pcie_port_service_register(struct pcie_port_service_driver *new)
 486{
 487        if (pcie_ports_disabled)
 488                return -ENODEV;
 489
 490        new->driver.name = new->name;
 491        new->driver.bus = &pcie_port_bus_type;
 492        new->driver.probe = pcie_port_probe_service;
 493        new->driver.remove = pcie_port_remove_service;
 494        new->driver.shutdown = pcie_port_shutdown_service;
 495
 496        return driver_register(&new->driver);
 497}
 498EXPORT_SYMBOL(pcie_port_service_register);
 499
 500/**
 501 * pcie_port_service_unregister - unregister PCI Express port service driver
 502 * @drv: PCI Express port service driver to unregister
 503 */
 504void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
 505{
 506        driver_unregister(&drv->driver);
 507}
 508EXPORT_SYMBOL(pcie_port_service_unregister);
 509