diff options
Diffstat (limited to 'drivers/pci/hotplug/pnv_php.c')
-rw-r--r-- | drivers/pci/hotplug/pnv_php.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c index 41304b313512..63cd9f354b79 100644 --- a/drivers/pci/hotplug/pnv_php.c +++ b/drivers/pci/hotplug/pnv_php.c | |||
@@ -717,7 +717,8 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data) | |||
717 | if (sts & PCI_EXP_SLTSTA_DLLSC) { | 717 | if (sts & PCI_EXP_SLTSTA_DLLSC) { |
718 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts); | 718 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts); |
719 | added = !!(lsts & PCI_EXP_LNKSTA_DLLLA); | 719 | added = !!(lsts & PCI_EXP_LNKSTA_DLLLA); |
720 | } else if (sts & PCI_EXP_SLTSTA_PDC) { | 720 | } else if (!(php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) && |
721 | (sts & PCI_EXP_SLTSTA_PDC)) { | ||
721 | ret = pnv_pci_get_presence_state(php_slot->id, &presence); | 722 | ret = pnv_pci_get_presence_state(php_slot->id, &presence); |
722 | if (ret) { | 723 | if (ret) { |
723 | dev_warn(&pdev->dev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n", | 724 | dev_warn(&pdev->dev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n", |
@@ -768,6 +769,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data) | |||
768 | static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) | 769 | static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) |
769 | { | 770 | { |
770 | struct pci_dev *pdev = php_slot->pdev; | 771 | struct pci_dev *pdev = php_slot->pdev; |
772 | u32 broken_pdc = 0; | ||
771 | u16 sts, ctrl; | 773 | u16 sts, ctrl; |
772 | int ret; | 774 | int ret; |
773 | 775 | ||
@@ -779,9 +781,18 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) | |||
779 | return; | 781 | return; |
780 | } | 782 | } |
781 | 783 | ||
784 | /* Check PDC (Presence Detection Change) is broken or not */ | ||
785 | ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc", | ||
786 | &broken_pdc); | ||
787 | if (!ret && broken_pdc) | ||
788 | php_slot->flags |= PNV_PHP_FLAG_BROKEN_PDC; | ||
789 | |||
782 | /* Clear pending interrupts */ | 790 | /* Clear pending interrupts */ |
783 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts); | 791 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts); |
784 | sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); | 792 | if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) |
793 | sts |= PCI_EXP_SLTSTA_DLLSC; | ||
794 | else | ||
795 | sts |= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); | ||
785 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts); | 796 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts); |
786 | 797 | ||
787 | /* Request the interrupt */ | 798 | /* Request the interrupt */ |
@@ -795,9 +806,15 @@ static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) | |||
795 | 806 | ||
796 | /* Enable the interrupts */ | 807 | /* Enable the interrupts */ |
797 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); | 808 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); |
798 | ctrl |= (PCI_EXP_SLTCTL_HPIE | | 809 | if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) { |
799 | PCI_EXP_SLTCTL_PDCE | | 810 | ctrl &= ~PCI_EXP_SLTCTL_PDCE; |
800 | PCI_EXP_SLTCTL_DLLSCE); | 811 | ctrl |= (PCI_EXP_SLTCTL_HPIE | |
812 | PCI_EXP_SLTCTL_DLLSCE); | ||
813 | } else { | ||
814 | ctrl |= (PCI_EXP_SLTCTL_HPIE | | ||
815 | PCI_EXP_SLTCTL_PDCE | | ||
816 | PCI_EXP_SLTCTL_DLLSCE); | ||
817 | } | ||
801 | pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl); | 818 | pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl); |
802 | 819 | ||
803 | /* The interrupt is initialized successfully when @irq is valid */ | 820 | /* The interrupt is initialized successfully when @irq is valid */ |