Commit 8c0d3a02c1309eb6112d2e7c8172e8ceb26ecfca

Authored by Jiang Liu
Committed by Bjorn Helgaas
1 parent b2ef39be57

PCI: Add accessors for PCI Express Capability

The PCI Express Capability (PCIe spec r3.0, sec 7.8) comes in two
versions, v1 and v2.  In v1 Capability structures (PCIe spec r1.0 and
r1.1), some fields are optional, so the structure size depends on the
device type.

This patch adds functions to access this capability so drivers don't
have to be aware of the differences between v1 and v2.  Note that these
new functions apply only to the "PCI Express Capability," not to any of
the other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.)

Function pcie_capability_read_word/dword() reads the PCIe Capabilities
register and returns the value in the reference parameter "val".  If
the PCIe Capabilities register is not implemented on the PCIe device,
"val" is set to 0.

Function pcie_capability_write_word/dword() writes the value to the
specified PCIe Capability register.

Function pcie_capability_clear_and_set_word/dword() sets and/or clears bits
of a PCIe Capability register.

[bhelgaas: changelog, drop "pci_" prefixes, don't export
pcie_capability_reg_implemented()]
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

Showing 3 changed files with 236 additions and 0 deletions Side-by-side Diff

drivers/pci/access.c
... ... @@ -469,4 +469,206 @@
469 469 raw_spin_unlock_irqrestore(&pci_lock, flags);
470 470 }
471 471 EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
  472 +
  473 +static inline int pcie_cap_version(const struct pci_dev *dev)
  474 +{
  475 + return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
  476 +}
  477 +
  478 +static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
  479 +{
  480 + return true;
  481 +}
  482 +
  483 +static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
  484 +{
  485 + int type = pci_pcie_type(dev);
  486 +
  487 + return pcie_cap_version(dev) > 1 ||
  488 + type == PCI_EXP_TYPE_ROOT_PORT ||
  489 + type == PCI_EXP_TYPE_ENDPOINT ||
  490 + type == PCI_EXP_TYPE_LEG_END;
  491 +}
  492 +
  493 +static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
  494 +{
  495 + int type = pci_pcie_type(dev);
  496 +
  497 + return pcie_cap_version(dev) > 1 ||
  498 + type == PCI_EXP_TYPE_ROOT_PORT ||
  499 + (type == PCI_EXP_TYPE_DOWNSTREAM &&
  500 + dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
  501 +}
  502 +
  503 +static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
  504 +{
  505 + int type = pci_pcie_type(dev);
  506 +
  507 + return pcie_cap_version(dev) > 1 ||
  508 + type == PCI_EXP_TYPE_ROOT_PORT ||
  509 + type == PCI_EXP_TYPE_RC_EC;
  510 +}
  511 +
  512 +static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
  513 +{
  514 + if (!pci_is_pcie(dev))
  515 + return false;
  516 +
  517 + switch (pos) {
  518 + case PCI_EXP_FLAGS_TYPE:
  519 + return true;
  520 + case PCI_EXP_DEVCAP:
  521 + case PCI_EXP_DEVCTL:
  522 + case PCI_EXP_DEVSTA:
  523 + return pcie_cap_has_devctl(dev);
  524 + case PCI_EXP_LNKCAP:
  525 + case PCI_EXP_LNKCTL:
  526 + case PCI_EXP_LNKSTA:
  527 + return pcie_cap_has_lnkctl(dev);
  528 + case PCI_EXP_SLTCAP:
  529 + case PCI_EXP_SLTCTL:
  530 + case PCI_EXP_SLTSTA:
  531 + return pcie_cap_has_sltctl(dev);
  532 + case PCI_EXP_RTCTL:
  533 + case PCI_EXP_RTCAP:
  534 + case PCI_EXP_RTSTA:
  535 + return pcie_cap_has_rtctl(dev);
  536 + case PCI_EXP_DEVCAP2:
  537 + case PCI_EXP_DEVCTL2:
  538 + case PCI_EXP_LNKCAP2:
  539 + case PCI_EXP_LNKCTL2:
  540 + case PCI_EXP_LNKSTA2:
  541 + return pcie_cap_version(dev) > 1;
  542 + default:
  543 + return false;
  544 + }
  545 +}
  546 +
  547 +/*
  548 + * Note that these accessor functions are only for the "PCI Express
  549 + * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the
  550 + * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.)
  551 + */
  552 +int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
  553 +{
  554 + int ret;
  555 +
  556 + *val = 0;
  557 + if (pos & 1)
  558 + return -EINVAL;
  559 +
  560 + if (pcie_capability_reg_implemented(dev, pos)) {
  561 + ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val);
  562 + /*
  563 + * Reset *val to 0 if pci_read_config_word() fails, it may
  564 + * have been written as 0xFFFF if hardware error happens
  565 + * during pci_read_config_word().
  566 + */
  567 + if (ret)
  568 + *val = 0;
  569 + return ret;
  570 + }
  571 +
  572 + /*
  573 + * For Functions that do not implement the Slot Capabilities,
  574 + * Slot Status, and Slot Control registers, these spaces must
  575 + * be hardwired to 0b, with the exception of the Presence Detect
  576 + * State bit in the Slot Status register of Downstream Ports,
  577 + * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8)
  578 + */
  579 + if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA &&
  580 + pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
  581 + *val = PCI_EXP_SLTSTA_PDS;
  582 + }
  583 +
  584 + return 0;
  585 +}
  586 +EXPORT_SYMBOL(pcie_capability_read_word);
  587 +
  588 +int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val)
  589 +{
  590 + int ret;
  591 +
  592 + *val = 0;
  593 + if (pos & 3)
  594 + return -EINVAL;
  595 +
  596 + if (pcie_capability_reg_implemented(dev, pos)) {
  597 + ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val);
  598 + /*
  599 + * Reset *val to 0 if pci_read_config_dword() fails, it may
  600 + * have been written as 0xFFFFFFFF if hardware error happens
  601 + * during pci_read_config_dword().
  602 + */
  603 + if (ret)
  604 + *val = 0;
  605 + return ret;
  606 + }
  607 +
  608 + if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL &&
  609 + pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) {
  610 + *val = PCI_EXP_SLTSTA_PDS;
  611 + }
  612 +
  613 + return 0;
  614 +}
  615 +EXPORT_SYMBOL(pcie_capability_read_dword);
  616 +
  617 +int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val)
  618 +{
  619 + if (pos & 1)
  620 + return -EINVAL;
  621 +
  622 + if (!pcie_capability_reg_implemented(dev, pos))
  623 + return 0;
  624 +
  625 + return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val);
  626 +}
  627 +EXPORT_SYMBOL(pcie_capability_write_word);
  628 +
  629 +int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val)
  630 +{
  631 + if (pos & 3)
  632 + return -EINVAL;
  633 +
  634 + if (!pcie_capability_reg_implemented(dev, pos))
  635 + return 0;
  636 +
  637 + return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val);
  638 +}
  639 +EXPORT_SYMBOL(pcie_capability_write_dword);
  640 +
  641 +int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos,
  642 + u16 clear, u16 set)
  643 +{
  644 + int ret;
  645 + u16 val;
  646 +
  647 + ret = pcie_capability_read_word(dev, pos, &val);
  648 + if (!ret) {
  649 + val &= ~clear;
  650 + val |= set;
  651 + ret = pcie_capability_write_word(dev, pos, val);
  652 + }
  653 +
  654 + return ret;
  655 +}
  656 +EXPORT_SYMBOL(pcie_capability_clear_and_set_word);
  657 +
  658 +int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
  659 + u32 clear, u32 set)
  660 +{
  661 + int ret;
  662 + u32 val;
  663 +
  664 + ret = pcie_capability_read_dword(dev, pos, &val);
  665 + if (!ret) {
  666 + val &= ~clear;
  667 + val |= set;
  668 + ret = pcie_capability_write_dword(dev, pos, val);
  669 + }
  670 +
  671 + return ret;
  672 +}
  673 +EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
... ... @@ -816,6 +816,39 @@
816 816 return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
817 817 }
818 818  
  819 +int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val);
  820 +int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val);
  821 +int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val);
  822 +int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val);
  823 +int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos,
  824 + u16 clear, u16 set);
  825 +int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
  826 + u32 clear, u32 set);
  827 +
  828 +static inline int pcie_capability_set_word(struct pci_dev *dev, int pos,
  829 + u16 set)
  830 +{
  831 + return pcie_capability_clear_and_set_word(dev, pos, 0, set);
  832 +}
  833 +
  834 +static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos,
  835 + u32 set)
  836 +{
  837 + return pcie_capability_clear_and_set_dword(dev, pos, 0, set);
  838 +}
  839 +
  840 +static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos,
  841 + u16 clear)
  842 +{
  843 + return pcie_capability_clear_and_set_word(dev, pos, clear, 0);
  844 +}
  845 +
  846 +static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos,
  847 + u32 clear)
  848 +{
  849 + return pcie_capability_clear_and_set_dword(dev, pos, clear, 0);
  850 +}
  851 +
819 852 /* user-space driven config access */
820 853 int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
821 854 int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
include/linux/pci_regs.h
... ... @@ -549,6 +549,7 @@
549 549 #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */
550 550 #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
551 551 #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
  552 +#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
552 553 #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
553 554  
554 555 /* Extended Capabilities (PCI-X 2.0 and Express) */