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