aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/access.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/access.c')
-rw-r--r--drivers/pci/access.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index ba91a7e17519..3af0478c057b 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -469,3 +469,205 @@ void pci_cfg_access_unlock(struct pci_dev *dev)
469 raw_spin_unlock_irqrestore(&pci_lock, flags); 469 raw_spin_unlock_irqrestore(&pci_lock, flags);
470} 470}
471EXPORT_SYMBOL_GPL(pci_cfg_access_unlock); 471EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
472
473static inline int pcie_cap_version(const struct pci_dev *dev)
474{
475 return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
476}
477
478static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
479{
480 return true;
481}
482
483static 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
493static 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
503static 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
512static 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 */
552int 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}
586EXPORT_SYMBOL(pcie_capability_read_word);
587
588int 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}
615EXPORT_SYMBOL(pcie_capability_read_dword);
616
617int 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}
627EXPORT_SYMBOL(pcie_capability_write_word);
628
629int 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}
639EXPORT_SYMBOL(pcie_capability_write_dword);
640
641int 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}
656EXPORT_SYMBOL(pcie_capability_clear_and_set_word);
657
658int 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}
673EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);